进阶教程 · Git

把本地、提交、推送和合并状态说准确

用可复查的 Git 证据区分交付阶段,避免把本地完成误报成线上完成。

一段代码可以已经写完,同时仍然只存在于某台电脑。Git 的每个动作留下不同证据。交付报告把这些证据混成一句“已经好了”,接手的人就不知道下一步该检查本地目录、远端分支,还是目标环境。

本地修改和本地提交

先查工作区。

git status --short --branch
git diff --check
git diff --stat

有文件差异时,状态是本地修改。git add 把选定内容写入索引,仍未形成提交。正常检出分支时,git commit 创建本地提交对象并移动当前分支指针。处于 detached HEAD 状态时,它只移动 HEAD,不会替你创建或推进功能分支。此时可以用下面两条命令确认提交号和文件范围。

git log -1 --oneline
git show --stat --oneline HEAD
把本地、提交、推送和合并状态说准确的入口、目标与准备条件操作示意图
图 1 · 进入任务前先确认目标、范围和准备条件

推送只证明远端分支更新

git push origin codex/example 请求远端更新名为 codex/example 的引用。命令成功后,再查询远端引用,避免只凭终端里的一句摘要下结论。

git ls-remote origin refs/heads/codex/example

返回的提交号与本地目标提交一致,可以报告该分支已推送。它仍没有说明 main 已经包含这项工作。远端仓库也可能拒绝更新,或者有人在随后又推了新提交,因此报告里要带分支名和已核对的提交号。

本地分支是否领先或落后上游,可以这样看。

git branch -vv
git rev-list --left-right --count @{upstream}...HEAD

git branch -vv 会显示上游分支和跟踪摘要。计数命令分别给出上游独有提交和本地独有提交。没有设置 upstream 时,@{upstream} 会报错,这说明当前分支还没有可用于比较的跟踪关系,不能把“ahead 1”之类判断凭空写进报告。

合并要检查目标分支

先取得最新远端引用,再检查目标分支是否包含功能提交。

git fetch origin
git branch -r --contains <commit>
git log --oneline --decorate origin/main -10

普通 merge 会保留功能提交的身份,--contains 通常能直接找到。平台采用 squash merge 时,目标分支会生成新的提交号,原功能提交不会成为它的祖先。这时应核对合并请求记录、目标提交及最终差异,不能因为 --contains 没结果就断言内容缺失。

合并请求已经打开也只是待审状态。有人批准了审查,还要看目标分支引用是否真的更新。远端页面显示 merge commit 或 squash commit 后,再用 git fetch origin 取得它,核对提交内容和目标分支日志。远端缓存没有刷新时,本地 origin/main 可能仍停在旧位置。

把本地、提交、推送和合并状态说准确的三步关键操作与请求骨架示意图
图 2 · 把关键操作拆成三步,并给每一步留下可观察结果

部署和线上验收另算

Git 记录代码与引用,不记录某个平台是否完成构建、环境变量是否齐全,也不证明用户访问的域名已经更新。发布平台显示成功后,状态可以写为已部署。再访问真实页面、走完关键操作并核对版本,才能写为线上已验证。

测试也要写出证据。报告应列实际运行的命令、退出结果和没有执行的检查。测试日志来自提交前,提交后又改了文件,那份日志不能证明最新内容。可以在测试完成后再运行 git status --porcelain=v1 --untracked-files=allgit rev-parse HEAD,把检查结果绑定到确定的工作区与提交。测试依赖的忽略文件和环境变量仍要另外记录。

回滚同样有阶段差异。git revert 创建抵消旧提交的新提交,仍要推送、合并和部署。远端撤回代码以后,已经发布的实例也可能继续运行旧版本。事故记录把代码回滚与环境回滚分开写,排查会快很多。

一份可靠交付至少留下工作树路径、分支、提交号和测试结果。随后单独写当前阶段,例如 local-onlypushedmergeddeployedlive-verified。后一个词没有证据时就停在前一个词,接手的人反而更容易继续。

把本地、提交、推送和合并状态说准确的结果验收与交付证据清单示意图
图 3 · 用结果、检查与交付证据确认任务真的完成

官方参考