进阶技巧
这一章收了几个平时用得不多、但遇到特定问题时很好用的命令:挑选提交、找回误删的提交、定位引入 Bug 的版本等。
git cherry-pick:挑选提交
想把另一个分支上的某个提交应用到当前分支,而不是合并整个分支?用 cherry-pick:
# 把指定提交应用到当前分支
git cherry-pick a1b2c3d
# 挑选多个提交
git cherry-pick a1b2c3d e4f5g6h
# 挑选一个范围(不含 A,包含 B)
git cherry-pick A..B
# 只应用修改,不自动提交
git cherry-pick -n a1b2c3d典型场景:在开发分支上修复了一个 Bug,需要同步到发布分支。
遇到冲突时,解决后执行 git cherry-pick --continue,或用 --abort 放弃。
git reflog:后悔药
reflog 记录了 HEAD 和分支指针的每一次变动,包括 commit、reset、rebase、checkout 等。它是恢复"丢失"数据的最后一道防线:
git reflog
# e4f5g6h HEAD@{0}: rebase (finish): returning to refs/heads/feature
# a1b2c3d HEAD@{5}: commit: 添加登录接口
# 恢复误删的分支
git branch recovered-branch a1b2c3d
# 回到 rebase 之前的状态
git reset --hard HEAD@{5}注意
reflog 只保存在本地,不会被推送;条目默认保留 90 天。
git bisect:二分查找 Bug
某个功能以前正常,现在坏了,但中间有上百个提交,不知道是哪一个引入的问题?git bisect 可以用二分法快速定位:
# 开始二分查找
git bisect start
# 标记当前版本是坏的
git bisect bad
# 标记一个已知正常的版本
git bisect good v1.0.0
# Git 会检出中间的一个提交,测试后告诉 Git 结果
git bisect good # 或 git bisect bad
# 重复上面的步骤,直到 Git 找到第一个坏提交
# a1b2c3d is the first bad commit
# 结束,回到原来的分支
git bisect reset如果有自动化测试脚本,还可以让 Git 全自动完成:
git bisect run npm test100 个提交最多只需要测试 7 次左右。
git worktree:同时检出多个分支
需要在修复 Bug 的同时保留当前开发环境不动?worktree 允许一个仓库同时拥有多个工作区:
# 在 ../hotfix 目录检出 hotfix 分支
git worktree add ../hotfix hotfix
# 基于 main 新建分支并检出
git worktree add -b feature-x ../feature-x main
# 列出所有工作区
git worktree list
# 删除工作区
git worktree remove ../hotfix相比再克隆一份仓库,worktree 共享同一个 .git 数据库,节省空间且提交互通。
git grep:在仓库中搜索
# 在已跟踪的文件中搜索
git grep "TODO"
# 显示行号
git grep -n "getUserInfo"
# 在某个历史版本中搜索
git grep "apiKey" v1.0.0修改历史中的作者信息
如果之前的提交用错了邮箱:
# 修改最后一次提交的作者
git commit --amend --author="张三 <[email protected]>" --no-edit
# 修改最近多个提交:交互式变基,把需要修改的标记为 edit
git rebase -i HEAD~5
# 每停一次执行:
git commit --amend --reset-author --no-edit
git rebase --continue从历史中彻底删除文件
误提交了大文件或敏感信息,需要从所有历史中清除。官方推荐使用 git filter-repo:
# 安装
pip install git-filter-repo
# 从所有历史中删除某个文件
git filter-repo --path secrets.json --invert-paths
# 删除大于 10MB 的文件
git filter-repo --strip-blobs-bigger-than 10M警告
这会改写整个仓库的历史,所有提交哈希都会改变。执行后需要强制推送,并通知所有协作者重新克隆。泄露的密钥仍需立即更换。
Git LFS:管理大文件
Git 不擅长管理大型二进制文件(设计稿、视频、模型等)。Git LFS 会把大文件存储在单独的服务器上,仓库中只保存指针:
git lfs install
git lfs track "*.psd"
git add .gitattributes
git add design.psd
git commit -m "添加设计稿"Git Hooks:钩子
Git 可以在特定事件发生时自动执行脚本,脚本位于 .git/hooks/ 目录:
| 钩子 | 触发时机 | 常见用途 |
|---|---|---|
pre-commit | 提交前 | 运行代码检查、格式化 |
commit-msg | 编写提交说明后 | 校验提交说明格式 |
pre-push | 推送前 | 运行测试 |
post-merge | 合并后 | 自动安装依赖 |
.git/hooks 不会被提交到仓库。前端项目中常用 husky 等工具在团队内共享钩子配置。
签名提交
为了证明提交确实来自你本人,可以对提交进行签名。新版 Git 支持直接使用 SSH 密钥签名:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true把同一个公钥作为 Signing Key 添加到 GitHub 后,提交旁会显示 "Verified" 标记。