目录
- [1. 大文件管理 - 避免同步到仓库](#1. 大文件管理 - 避免同步到仓库)
- [2. 分支对比操作](#2. 分支对比操作)
- [3. 版本回退操作](#3. 版本回退操作)
- [4. 其他常用操作](#4. 其他常用操作)
1. 大文件管理 - 避免同步到仓库
1.1 使用 .gitignore 文件
.gitignore 是最常用的方法,用于告诉 Git 忽略特定的文件或目录。
创建 .gitignore 文件
在项目根目录创建 .gitignore 文件:
bash
touch .gitignore
常见的大文件忽略规则
gitignore
# 数据集目录
/data/
/dataset/
/datasets/
# 特定格式的大文件
*.csv
*.h5
*.hdf5
*.pkl
*.pickle
*.npy
*.npz
# 模型文件
*.pth
*.pt
*.ckpt
*.model
*.weights
*.pb
*.onnx
# 压缩文件
*.zip
*.tar
*.tar.gz
*.rar
*.7z
# 视频和音频文件
*.mp4
*.avi
*.mov
*.mkv
*.mp3
*.wav
# 图像文件(如果很大)
*.psd
*.raw
# 日志文件
*.log
logs/
# 临时文件
tmp/
temp/
cache/
# 数据库文件
*.db
*.sqlite
*.sqlite3
# IDE 和编辑器文件
.vscode/
.idea/
*.swp
*.swo
.DS_Store
.gitignore 语法说明
gitignore
# 注释行以 # 开头
# 忽略特定文件
filename.txt
# 忽略特定目录(使用斜杠结尾)
directory/
# 忽略特定扩展名
*.ext
# 忽略根目录下的文件(前面加斜杠)
/root-file.txt
# 忽略所有目录下的特定文件
**/file.txt
# 不忽略特定文件(使用感叹号)
!important.csv
# 忽略某个目录但不忽略其子目录的特定文件
data/*
!data/.gitkeep
1.2 已追踪文件的处理
如果文件已经被 Git 追踪,需要先从 Git 中移除:
bash
# 从 Git 中移除文件但保留本地文件
git rm --cached large-file.csv
# 从 Git 中移除整个目录但保留本地文件
git rm -r --cached data/
# 提交更改
git commit -m "Remove large files from tracking"
1.3 使用 Git LFS (Large File Storage)
对于必须版本控制的大文件,使用 Git LFS:
安装 Git LFS
bash
# Ubuntu/Debian
sudo apt-get install git-lfs
# macOS
brew install git-lfs
# Windows
# 从 https://git-lfs.github.com/ 下载安装
# 初始化
git lfs install
配置 Git LFS
bash
# 追踪特定类型的大文件
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "data/*.csv"
# 查看追踪的文件类型
git lfs track
# 确保 .gitattributes 被提交
git add .gitattributes
git commit -m "Configure Git LFS"
使用 Git LFS
bash
# 添加大文件(会自动使用 LFS)
git add large-file.zip
git commit -m "Add large file via LFS"
git push
1.4 检查仓库中的大文件
bash
# 查找仓库中最大的文件(前 10 个)
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
sed -n 's/^blob //p' | \
sort --numeric-sort --key=2 | \
tail -n 10
# 更简洁的方法(需要安装 git-sizer)
git-sizer --verbose
1.5 从历史记录中彻底删除大文件
如果大文件已经提交到历史记录,需要使用 git filter-branch 或 BFG Repo-Cleaner:
使用 git filter-repo(推荐)
bash
# 安装
pip install git-filter-repo
# 删除特定文件
git filter-repo --path large-file.csv --invert-paths
# 删除特定目录
git filter-repo --path data/ --invert-paths
# 删除大于指定大小的文件(如 100MB)
git filter-repo --strip-blobs-bigger-than 100M
使用 BFG Repo-Cleaner
bash
# 下载 BFG
# https://rtyley.github.io/bfg-repo-cleaner/
# 删除大于 100M 的文件
java -jar bfg.jar --strip-blobs-bigger-than 100M repo.git
# 删除特定文件
java -jar bfg.jar --delete-files large-file.csv repo.git
# 清理
cd repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
2. 分支对比操作
2.1 查看分支差异
比较两个分支的不同
bash
# 查看两个分支的差异概览
git diff branch1..branch2
# 查看哪些文件不同
git diff --name-only branch1 branch2
# 查看文件状态(新增、修改、删除)
git diff --name-status branch1 branch2
# 查看统计信息
git diff --stat branch1 branch2
比较当前分支与其他分支
bash
# 比较当前分支与 main 分支
git diff main
# 比较当前分支与远程分支
git diff origin/main
比较特定文件
bash
# 比较特定文件在两个分支的差异
git diff branch1 branch2 -- path/to/file.py
# 比较多个文件
git diff branch1 branch2 -- file1.py file2.py
2.2 查看分支提交差异
bash
# 查看 branch2 中有但 branch1 中没有的提交
git log branch1..branch2
# 更详细的日志
git log branch1..branch2 --oneline --graph --decorate
# 查看双向差异(两个分支各自独有的提交)
git log --left-right --graph --cherry-pick --oneline branch1...branch2
2.3 查看分支的提交历史图
bash
# 查看所有分支的图形化历史
git log --all --graph --oneline --decorate
# 查看特定分支的图形化历史
git log --graph --oneline --decorate branch1 branch2
# 更美观的输出
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all
2.4 比较分支的文件列表
bash
# 查看 branch2 相对于 branch1 新增的文件
git diff --name-only --diff-filter=A branch1 branch2
# 查看被修改的文件
git diff --name-only --diff-filter=M branch1 branch2
# 查看被删除的文件
git diff --name-only --diff-filter=D branch1 branch2
# 查看所有变化(A=新增, M=修改, D=删除)
git diff --name-status branch1 branch2
2.5 使用图形化工具对比分支
bash
# 使用 gitk 查看分支对比
gitk branch1 branch2
# 使用 git difftool
git difftool branch1 branch2
# 配置 difftool(如使用 meld)
git config --global diff.tool meld
git config --global difftool.prompt false
2.6 查找分支的共同祖先
bash
# 查找两个分支的共同祖先
git merge-base branch1 branch2
# 查看从共同祖先到 branch2 的差异
git diff $(git merge-base branch1 branch2) branch2
3. 版本回退操作
3.1 查看提交历史
bash
# 查看提交历史
git log
# 简洁的单行显示
git log --oneline
# 查看最近 n 次提交
git log -n 5
# 查看特定文件的提交历史
git log -- path/to/file.py
# 查看提交的详细信息
git show commit-hash
3.2 回退到指定 commit(保留工作区改动)
bash
# 软回退:回退到指定 commit,保留更改在暂存区
git reset --soft commit-hash
# 示例:回退到上一个 commit
git reset --soft HEAD~1
# 回退到上上个 commit
git reset --soft HEAD~2
使用场景:想要重新组织最近的提交,但保留所有改动。
3.3 回退到指定 commit(不保留暂存区)
bash
# 混合回退(默认):回退到指定 commit,更改保留在工作区但不在暂存区
git reset --mixed commit-hash
# 或者简写
git reset commit-hash
# 示例
git reset HEAD~1
使用场景:想要撤销提交和暂存,但保留文件改动。
3.4 回退到指定 commit(完全丢弃改动)
bash
# 硬回退:完全回退到指定 commit,丢弃所有更改
git reset --hard commit-hash
# 示例:回退到上一个 commit 并丢弃所有更改
git reset --hard HEAD~1
# 回退到远程分支的状态
git reset --hard origin/main
警告:此操作会永久删除未提交的更改,使用前请确保重要改动已备份。
3.5 使用 revert 创建新提交来撤销
bash
# 创建新的提交来撤销指定 commit(推荐用于已推送的提交)
git revert commit-hash
# 撤销最近的 commit
git revert HEAD
# 撤销多个 commit
git revert commit-hash1 commit-hash2
# 撤销一个范围的 commits
git revert old-commit..new-commit
优点:不会改变历史记录,适合已经推送到远程的提交。
3.6 回退单个文件到指定版本
bash
# 将文件恢复到指定 commit 的状态
git checkout commit-hash -- path/to/file.py
# 将文件恢复到上一个 commit 的状态
git checkout HEAD~1 -- path/to/file.py
# 查看文件在某个 commit 时的内容(不修改工作区)
git show commit-hash:path/to/file.py
3.7 撤销工作区的修改
bash
# 撤销单个文件的修改(恢复到最后一次 commit 的状态)
git checkout -- file.py
# 或使用新语法
git restore file.py
# 撤销所有修改
git checkout -- .
# 或
git restore .
3.8 撤销暂存区的修改
bash
# 取消暂存单个文件
git reset HEAD file.py
# 或使用新语法
git restore --staged file.py
# 取消所有暂存
git reset HEAD
# 或
git restore --staged .
3.9 查看和恢复已删除的 commit
bash
# 查看所有操作记录(包括已删除的 commit)
git reflog
# 恢复到某个已删除的 commit
git reset --hard commit-hash
# 或创建新分支指向该 commit
git branch recovery-branch commit-hash
3.10 回退已推送的提交
如果已经推送到远程,有两种方法:
方法一:使用 revert(推荐)
bash
# 创建新提交来撤销
git revert commit-hash
git push origin branch-name
方法二:强制推送(谨慎使用)
bash
# 本地回退
git reset --hard commit-hash
# 强制推送到远程(会覆盖远程历史)
git push origin branch-name --force
# 或使用更安全的 --force-with-lease
git push origin branch-name --force-with-lease
警告:强制推送会改变远程历史,可能影响其他协作者。
3.11 临时保存和恢复工作
bash
# 临时保存当前工作(包括未暂存和已暂存的修改)
git stash
# 保存时添加描述
git stash save "描述信息"
# 查看所有 stash
git stash list
# 恢复最近的 stash 并删除
git stash pop
# 恢复指定的 stash
git stash apply stash@{0}
# 删除 stash
git stash drop stash@{0}
# 清空所有 stash
git stash clear
4. 其他常用操作
4.1 分支管理
bash
# 查看所有分支
git branch -a
# 创建新分支
git branch new-branch
# 切换分支
git checkout branch-name
# 或
git switch branch-name
# 创建并切换到新分支
git checkout -b new-branch
# 或
git switch -c new-branch
# 删除本地分支
git branch -d branch-name
# 强制删除未合并的分支
git branch -D branch-name
# 删除远程分支
git push origin --delete branch-name
# 重命名分支
git branch -m old-name new-name
4.2 合并操作
bash
# 合并指定分支到当前分支
git merge branch-name
# 取消合并(如果有冲突)
git merge --abort
# 使用 rebase 合并
git rebase branch-name
# 取消 rebase
git rebase --abort
# 继续 rebase(解决冲突后)
git rebase --continue
4.3 标签管理
bash
# 创建标签
git tag v1.0.0
# 创建带注释的标签
git tag -a v1.0.0 -m "版本 1.0.0"
# 为特定 commit 打标签
git tag v1.0.0 commit-hash
# 查看所有标签
git tag
# 查看标签信息
git show v1.0.0
# 推送标签到远程
git push origin v1.0.0
# 推送所有标签
git push origin --tags
# 删除本地标签
git tag -d v1.0.0
# 删除远程标签
git push origin --delete v1.0.0
4.4 查看和清理
bash
# 查看仓库状态
git status
# 查看远程仓库
git remote -v
# 清理未跟踪的文件(预览)
git clean -n
# 清理未跟踪的文件
git clean -f
# 清理未跟踪的文件和目录
git clean -fd
# 查看仓库大小
du -sh .git
# 垃圾回收和优化
git gc --aggressive --prune=now
4.5 配置别名
bash
# 配置常用命令别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual 'log --graph --oneline --all'
# 使用别名
git st
git co main
5. 最佳实践建议
5.1 大文件管理最佳实践
- 项目初期就配置 .gitignore,避免误提交大文件
- 定期检查仓库大小,及时发现和处理大文件
- 数据集和模型文件使用外部存储,如云存储、NFS 等
- 必要时使用 Git LFS,但注意带宽成本
- 压缩文件前先评估是否必要,有时压缩文件也很大
5.2 分支管理最佳实践
- 主分支保护:main/master 分支应该始终保持稳定
- 功能分支开发:每个新功能使用独立分支
- 分支命名规范:如 feature/xxx, bugfix/xxx, hotfix/xxx
- 定期合并:避免分支长期分离导致冲突复杂
- 合并前对比:使用 diff 和 log 确认要合并的内容
5.3 版本回退最佳实践
- 慎用 reset --hard:容易丢失工作成果
- 已推送的提交优先使用 revert:保持历史记录完整
- 重要操作前创建备份分支 :
git branch backup - 善用 reflog:可以恢复误删的提交
- 提交前仔细检查 :使用
git diff --staged查看暂存内容
5.4 协作开发建议
- 频繁提交,但每次提交要有明确的目的
- 写清晰的提交信息,说明改动的原因和内容
- 推送前先拉取 :
git pull --rebase保持历史清晰 - 解决冲突时要谨慎,确保不丢失他人的工作
- 代码审查:重要分支合并前进行 code review
6. 常见问题和解决方案
6.1 误提交大文件后如何处理?
bash
# 1. 从暂存区移除
git rm --cached large-file.csv
# 2. 添加到 .gitignore
echo "large-file.csv" >> .gitignore
# 3. 提交更改
git commit --amend
# 4. 如果已推送,需要强制推送(谨慎)
git push --force-with-lease
6.2 如何处理合并冲突?
bash
# 1. 查看冲突文件
git status
# 2. 手动编辑冲突文件,解决冲突标记
# <<<<<<< HEAD
# 当前分支的内容
# =======
# 要合并分支的内容
# >>>>>>> branch-name
# 3. 标记冲突已解决
git add conflict-file.py
# 4. 完成合并
git commit
6.3 如何撤销最近的合并?
bash
# 如果还没推送
git reset --hard HEAD~1
# 如果已经推送
git revert -m 1 HEAD
6.4 如何查看某个文件的修改历史?
bash
# 查看文件的提交历史
git log -- path/to/file.py
# 查看文件的详细修改历史
git log -p -- path/to/file.py
# 查看文件的每一行最后修改信息
git blame path/to/file.py
7. 快速参考表
常用命令速查
| 操作 | 命令 |
|---|---|
| 查看状态 | git status |
| 添加文件 | git add file |
| 提交 | git commit -m "message" |
| 推送 | git push |
| 拉取 | git pull |
| 查看日志 | git log --oneline |
| 创建分支 | git branch branch-name |
| 切换分支 | git switch branch-name |
| 合并分支 | git merge branch-name |
| 比较差异 | git diff |
| 回退(保留改动) | git reset --soft HEAD~1 |
| 回退(丢弃改动) | git reset --hard HEAD~1 |
| 撤销提交 | git revert HEAD |
| 临时保存 | git stash |
| 恢复保存 | git stash pop |
8. 总结
本文档涵盖了 Git 的关键操作,特别是:
- 大文件管理:通过 .gitignore 和 Git LFS 避免仓库膨胀
- 分支对比:使用 diff 和 log 命令全面了解分支差异
- 版本回退:根据场景选择 reset、revert 或 checkout
掌握这些操作,可以让你更高效地使用 Git 进行版本控制和团队协作。记住,Git 的强大之处在于它的灵活性,但也要谨慎使用可能改变历史的命令(如 reset --hard 和 force push)。
建议:实践是最好的学习方法,在自己的测试仓库中多多尝试这些命令,熟能生巧!