Skip to main content

Git 实用技巧:暂存现场、挑选提交与定位 Bug(阅读笔记)

· 9 min read

原文作者:imDwAaY

原文:6篇文章讲清楚Git:Git 实用技巧:暂存现场、挑选提交与定位 Bug (5/6)

原文发布于:2026-09-28 19:22

这篇文章涉及的命令,可以按工作目的分成三组:追查历史、保存工作现场,以及调整提交。下面按这个顺序整理阅读笔记,命令示例重新编写,并结合 Git 官方文档补充细节。

追查历史:从线索到复现​

已掌握的线索选择的工具能回答的问题
文件、关键词、作者或时间git log哪些提交值得进一步检查?
某段代码所在的行git blame当前这些行对应哪些修改记录?
一个正常版本和一个异常版本git bisect哪次提交开始出现可复现的问题?

筛选提交和查看行历史​

git log --oneline -- src/parser.ts
git log -p -S 'parseInput' -- src/parser.ts
git log -p -G 'timeout[[:space:]]*=' -- src/parser.ts
git log --author='Alice' --since='2026-09-01' --grep='parser'
git log -L 30,50:src/parser.ts
git log --merges --oneline

git blame -w -L 30,50 -- src/parser.ts
git blame -C -- src/parser.ts

-S 比较指定字符串在修改前后的出现次数;-G 检查补丁中新增或删除的行是否匹配正则。两者筛选条件不同。例如某个字符串从一行移到另一行,次数未变,未必能被 -S 找到。-L 用于追踪指定行范围的演变。参见 git-log 文档。

blame 的结果反映当前行的修改归属,不能单凭它判断问题责任。-w 能忽略空白差异,-C 有助于寻找跨文件复制的来源;接下来仍需阅读对应提交及其上下文。

用二分验证缩小范围​

先确定一条稳定的判断规则,再开始二分。例如:固定输入下解析结果是否正确。假设 v1.2.0 已验证正常,当前版本异常:

git bisect start
git bisect bad HEAD
git bisect good v1.2.0

Git 会检出候选版本。每轮验证后,根据实际结果执行下面两条命令之一:

git bisect good
git bisect bad

对于无法构建或无法判断的候选版本,可以使用 git bisect skip。找到结果后执行 git bisect reset,恢复开始排查前的位置。

如果已有检测脚本,可以让 Git 自动推进:

git bisect start HEAD v1.2.0
git bisect run /tmp/check-parser.sh
git bisect reset

检测脚本返回 0 表示正常,1 至 127 中除 125 外的值表示异常,125 表示跳过。脚本应只检测目标问题,避免把依赖缺失误判为代码回归。退出码约定见 git-bisect 文档。

保存工作现场:临时收起还是同时保留​

用 stash 收起未完成的改动​

普通 git stash push 保存已跟踪文件的改动;-u 加入未跟踪文件,-a 还会加入被忽略的文件。给记录写明用途,恢复时更容易核对。

git stash push -u -m 'parser: unfinished validation'
git stash list
git stash show -p --include-untracked 'stash@{0}'
git stash apply --index 'stash@{0}'

apply 保留记录,pop 在成功应用后移除记录;若 pop 发生冲突,记录会保留。上例的 --index 会尝试恢复原先的暂存状态。确认工作恢复正确后,再用 git stash drop 'stash@{0}' 删除记录。具体行为见 git-stash 文档。

stash 列表由仓库共享,恢复前要检查当前分支与记录内容。git stash branch recover-parser 'stash@{0}' 可从保存时的基点创建分支并恢复改动。

stash 使用 Git 对象持久保存,重启不会让它消失。但删除记录后只能尝试寻找尚未清理的对象,不能保证找回;重要工作应及时提交到分支。

用 worktree 保留多个工作目录​

需要并行维护分支、对比运行结果时,可以增加一个工作目录:

git worktree add -b hotfix/parser ../parser-hotfix main
git worktree list

这样可以在原目录继续开发,在 ../parser-hotfix 修复问题。关联工作目录共享对象数据库等仓库数据,各自拥有工作区、索引和 HEAD。额外检出的文件及安装的依赖仍占磁盘空间,同一分支默认也不能同时检出到多个工作目录。参见 git-worktree 文档。

处理并提交完改动后,用 git worktree remove ../parser-hotfix 移除工作目录;这不会同时删除对应分支。

调整提交:迁移修复和整理历史​

cherry-pick:向当前分支引入指定改动​

当修复已经形成独立提交,而所在分支还有未完成的功能时,可以只引入修复。下面的哈希为示例,执行时替换为实际提交:

git switch main
git cherry-pick 7a31bc2

它会在当前分支重新应用该提交的改动,通常产生新的提交对象。需要一起迁移的依赖提交,也应按依赖顺序纳入。

写法用途
git cherry-pick A B按给定顺序应用两个提交
git cherry-pick A..B应用 B 可达、A 不可达的提交集合;线性历史中不含 A
git cherry-pick A^..B在线性历史中包含起点 A;A 需有父提交
git cherry-pick -n A应用改动但暂不创建提交

遇到冲突后,修复文件、用 git add 标记,再执行 git cherry-pick --continue;放弃本轮操作则使用 git cherry-pick --abort。频繁迁移相同修复时,也值得重新检查分支之间的集成方式。

交互式 rebase:整理尚未共享的提交​

git rebase -i HEAD~3 会打开最近三个提交的操作列表,按从旧到新的顺序排列。可以调整行顺序,或修改每行的动作:

动作含义
pick应用提交
reword修改提交说明
edit暂停以修改提交
squash合入前一提交,并编辑合并后的说明
fixup合入前一提交,通常舍弃本条说明
drop移除该提交
exec执行指定的 shell 命令

例如,一次功能提交后跟着两次小修正,可以保留第一行的 pick,把后两行改成 fixup,将改动整理成一次提交。

rebase 会重写相关历史。整理后需要重新验证代码;涉及他人已使用的分支时,应先协调历史更新。操作受阻时,可解决冲突并暂存后运行 git rebase --continue,或用 git rebase --abort 放弃本轮整理。