SuperAPI AI 工具集

git

编程与开发

查看项目

更新于 11-06 17:10

技能介绍

Git

单一集成分支(master)。工作只能通过 PR 进入,由人类在 CI 全绿后以 squash-merge 合并。以下内容讲的是如何不给 git 添乱。

开工时(新建分支)

动手写代码前的检查清单:

git checkout master git pull origin master # 本地 master == origin/master git fetch --prune --prune-tags # 清理过期的远端引用与标签 git worktree prune # 丢弃已删除 worktree 的元数据 git branch --merged master | grep -v master | xargs -r git branch -d git switch -c <type>/<short-desc> # 从最新的 master 切出

清理已合并分支:git branch -d 会拒绝未合并的分支,所以照写是安全的。确认没有其他人占用该名称:git branch -a --list <type>/* 和 git ls-remote --heads origin <type>/*。除非工作依赖另一功能分支,否则不要从它切出;若确实依赖,请在 PR 描述中注明基分支。

分支命名

<type>/<short-kebab-desc>:feat/、fix/、hotfix/、chore/、docs/、refactor/、test/。小写 kebab-case,不能只写 issue 编号,允许可选后缀 -<bean-id-suffix>。示例:feat/oauth-login、fix/flaky-user-test、chore/deps-weekly、docs/readme-install。

提交命名

采用 Conventional Commits,祈使现在时(写“add”而非“added”):type(scope): summary,不超过 72 字符,冒号后小写,不加句号。正文按 72 字符换行,说明做了什么与为什么,而非怎么做。类型与分支类型对应。示例:feat(auth): add PKCE login flow、fix(parser): clamp negative turn counts。

保持分支可交付

CI 状态是工作的一部分,而非事后补的:

从推送开始监控:gh pr checks <PR>(或 gh run watch)。没有检查结果这一行,就不能说“看起来完成了”:每个 job 都要通过。

红灯 = 停下并修根因;绝不在红灯时合并,也绝不为了把偶发失败刷绿而在不理解原因的情况下重跑。

一次修复 = 一个新提交;不要 amend 已推送的提交。

如果 master 有变动,再次推送前先刷新。

刷新分支:用 merge,不用 rebase

过期分支的默认刷新方式是可以普通推送的 merge:

git fetch origin git merge origin/master # 或:git merge-base --is-ancestor
# origin/master HEAD && echo up-to-date git push # 普通推送,无需强推

rebase 会改写已推送的提交,因此推送需要 --force / --force-with-lease,可能破坏队友的推送。优先用 merge。若确实必须 rebase(用户要求,或采用 rebase-merge 策略),先确保工作区干净(提交或 stash),尽量只 rebase 未推送的提交;若历史已推送,回推时用 --force-with-lease(绝不用裸 --force),并说明覆盖了什么。

共同基线(分支分叉点)

在任何 rebase 或修冲突前先找到它:

git merge-base HEAD origin/master # 合并基点 git merge-base --fork-point origin/master HEAD # 真正的分叉点,会读 reflog git log --oneline $(git merge-base HEAD origin/master)..HEAD

merge-base 是共同祖先;--fork-point 还会读 reflog,在 master 被回退(squash 合并会不断改写 master)时找出原始顶端。在没有 reflog 记录旧顶端时,fork-point 会空失败(退出码 1)——例如全新克隆、reset 之后的状态——所以始终要有回退:

git merge-base --fork-point origin/master HEAD
|| git merge-base origin/master HEAD

对比要与分叉点比,而不是与 master 顶端比:git diff $(git merge-base HEAD origin/master)。git log A...B 里的三个点也会拆成 theirs/mine/ours 视图。

解决冲突

当 master 的改动进入你分支的文件(或 CI 显示冲突):

git merge-base HEAD origin/master # 分叉点 git merge origin/master # 合并现在停在冲突处 git status # 冲突:both modified / UU

逐个编辑文件;语义不同时保留双方内容;<<<<<<<、

=======、>>>>>>> 标记必须彻底删除;不得残留任何标记

git add <file> # 逐个标记已解决文件 git commit # 结束合并

不变式:解决后文件必须能构建,并符合双方作者的意图——不是“master 的版本胜出”。编辑后重新阅读该冲突块。然后在合并提交之前跑测试(项目的门禁):能编译但破坏行为的冲突解决是披着无辜提交外衣的新 bug。合并提交上的 CI 会确认。

当选择 rebase 路径时,冲突后的 git rebase --continue 遵循同样的解决/暂存/继续循环。提交前搜索整个树有无残留标记: grep -rn '^<<<<<<<|^=======$|^>>>>>>>' --include='*' .

Worktree

仅当确有并行工作在进行时(两个代理,或一个修复打断功能开发)才用 worktree。每个分支一个 worktree,始终放在项目目录内:

git worktree add .worktrees/<branch-short-name> -b <type>/<desc>

在那里干活;master 检出仍留在仓库根目录供共享命令使用

git worktree remove .worktrees/<name> # 合并后(见下) git worktree prune # 若目录被手动删除

不要嵌套仓库,worktree 不要放在 .worktrees/ 之外,不要长期保留 worktree(会腐烂:分支过期、依赖漂移、浪费磁盘)。worktree 共享仓库对象库,但不共享未跟踪文件——构建产物和 .env 不会带过去。

PR 合并后(清理)

由用户合并 PR(绝不由代理合并,见下)。合入的那一刻:

git checkout master git pull origin master git worktree remove .worktrees/<name> # 若存在对应 worktree 先做这一步: # branch -d 会拒绝仍被 worktree 检出的分支 git branch -d <merged-branch> # -d 会拒绝未合并分支,安全 git remote prune origin git worktree prune

重复开工时的清理流程,以清除更早的残留。然后从刷新后的 master 切出下一个分支。绝不复用已合并的分支做新工作:squash 合并会让新提交获得新 SHA,复用分支会在与历史不再匹配的基础上推送——随后就容易被诱惑去强推。

人类合并,代理辅助

代理负责开 PR、修复、更新,并在“就绪”处停下:PR 描述保持最新、检查全绿、没有未解决的评审线程。

绝不要自行合并 PR。绝不要调用 gh pr merge,绝不要点击合并,绝不要绕过红灯检查。合并是人类的关卡:由人决定什么进入 master。如果用户说“合并它”,请确认一次:用户在 UI 中合并没问题,代理执行合并命令不行。

红灯检查时:修复、推送、再次监控。PR 过期时:刷新(把 master 合并进来)、推送、再次监控。

报告状态,而非信心:附上检查结果那一行,说“CI 全绿,可以合并”。