推完代码发现本地和远端对不上,多数情况不是推送失败,而是本地分支名与远端实际创建的分支名不是同一个,或者本地分支没绑定上游、拉取时取到了另一个引用。一次完整的验证只要一条推送加一次拉取:推送前记下本地分支名和提交短哈希,推送后用 git ls-remote 看远端真实存在的分支,再用 git fetch 把远端提交拉回本地做哈希对照。下面按这个顺序走一遍。
判断这轮推送是否成立,不看终端提示语,而看三处是否一致:本地分支名、远端 refs/heads/ 下的分支名、以及两侧同一个短哈希。通常先用 git ls-remote `--heads` 确认远端分支名,再用 git branch -vv 确认追踪关系,最后用 git fetch 后对比 origin/分支名 与本地 HEAD。分支名带 feature/、release/ 前缀本身不代表错位;只有命名或上游绑定确实不一致,才需要用改名加重新绑定上游的方式纠正。
推送前先记录本地分支名和提交号
推送之前先在要推送的仓库里执行两条命令,留下后面能对照的基准:分支名和当前 HEAD 的短哈希。这两项才是判断「远端收到的到底是不是这个提交」的依据,终端里 Everything up-to-date 之类的提示语不能替代它们。
git branch
git log `--oneline` -n 5git branch 输出中带 * 的那一行是当前所在分支;git log `--oneline` -n 5 每行开头的七位左右字符就是提交号。把分支名和第一行哈希记下来,例如:
* feature/login
main
1a2b3c4 (HEAD -> feature/login) 补充登录校验
9f8e7d6 调整接口返回结构如果只想要提交号本身,可以单独取:
git rev-parse `--short` HEAD记录时要把分支名的前缀一起记下。本地叫 feature/login,远端分支名通常也会是 feature/login,只记成 login 会在后面排查时对不上号。
推送后查看远端实际存在的分支
推送完成后不要只读 git push 的输出,直接向远端询问现在有哪些分支头:
git ls-remote `--heads` origin输出每行是「提交哈希 + 制表符 + 引用全名」,大致长这样:
1a2b3c4e... refs/heads/feature/login
7c6d5e4f... refs/heads/main解读方式:refs/heads/ 之后的那段才是分支名,前面的哈希应与推送前记下的短哈希前缀一致。若 refs/heads/ 后面出现的是 refs/heads/login 而不是 refs/heads/feature/login,说明远端分支名与本地不同名,这就是分支名对不上的常见来源。refs/heads/ 之外的引用(如 refs/tags/、refs/pull/)不属于分支,不要混进来比较。远端仓库有命名规范、分支被加了团队前缀或放在目录层级下时,同样按 refs/heads/ 之后的完整字符串识别,斜杠属于分支名的一部分。只想筛某一段名字,可以加模式:
git ls-remote `--heads` origin "refs/heads/feature/*"确认本地分支有没有绑定追踪上游
git pull 或 git fetch 不带远端分支参数时会去读当前分支绑定的上游;从未绑定过的分支,命令会报类似 There is no tracking information for the current branch 或没有配置上游。查看绑定情况:
git branch -vv输出中每个分支后面的方括号就是上游,例如 [origin/feature/login],方括号后可能还会带上领先或落后的提交数量。方括号缺失,或者显示的是 [origin/main] 而当前分支是 feature/login,都属于取舍点,需要按实际意图纠正。绑定上游有两种常见写法:推送时一次性建立,或对已有分支单独设置。
# 方式一:推送同时建立上游
git push -u origin feature/login
# 方式二:给已存在的本地分支指定上游
git branch `--set-upstream-to`=origin/feature/login feature/login方式二要求 origin/feature/login 这个远端引用已经存在,因此一般先 git fetch。设置完成后再执行 git branch -vv,方括号里应出现对应的 origin/分支名。
把远端提交拉回本地做对照
要验证远端保存的提交与本地是不是同一份历史,先用 fetch 把远端引用更新到本地,再对比短哈希:
git fetch origin
git log `--oneline` -n 5 origin/feature/login
git log `--oneline` -n 5 HEAD两条 log 的第一行哈希一致,说明远端分支头和本地 HEAD 指向同一个提交。想精确比较而不靠肉眼,可以直接取引用:
git rev-parse `--short` HEAD
git rev-parse `--short` origin/feature/login远端分支引用名的书写形式是「远端名/分支名」。远端名默认是 origin,分支名保留完整前缀,例如 origin/feature/login。如果本地只写了 origin/login,会报 unknown revision,这条报错本身就说明名字没有对齐。需要注意的是 git fetch 只更新远端跟踪引用,不会改动工作区;想看清差异范围可以这样列:
git log `--oneline` HEAD..origin/feature/login
git log `--oneline` origin/feature/login..HEAD前一条列出远端有而本地没有的提交,后一条列出本地有而远端没有的提交。两个方向都为空,才算真正对齐。
分支名对不上时改名或重新绑定追踪
确认是命名错位(本地叫 login,远端却是 feature/login 之类),按顺序纠正:先把本地分支改成与远端一致的完整名字,再重新绑定上游,最后拉取验证。
# 1. 在当前分支上改名
git branch -m feature/login
# 如果当前不在该分支上,用旧名和新名两个参数
git branch -m login feature/login
# 2. 重新绑定上游
git fetch origin
git branch `--set-upstream-to`=origin/feature/login feature/login
# 3. 拉回验证
git pull `--ff-only`
git branch -vv
git log `--oneline` -n 5 origin/feature/login如果远端多出一个不再需要的错误命名分支,删除远端分支是独立的一步,建议先确认没有其他协作者的提交只落在那个分支上:
git push origin `--delete` login
git fetch `--prune`整轮验证的判定条件保持三条:git ls-remote `--heads` origin 中 refs/heads/ 后面的名字与本地分支名一致;git branch -vv 的方括号里是对应的 origin/分支名;本地短哈希与 origin/分支名 的短哈希相同。三条同时满足,这次推送加拉取才算真正对齐。