git fetch 显示 [new branch] 不是真分叉,是你自己在两台机器上重复提交了
服务器上有一个 PHP 项目,长期以来的工作方式是"SSH 进去直接改代码",偶尔也会在本地 clone 一份改完再推。某天终于想规范化,打算把两侧历史合并到远端。一跑 git fetch,傻眼了:
$ git fetch origin
* [new branch] master -> origin/master[new branch]?master 从来都在啊,怎么变成新分支了?紧接着一看数量:
$ git rev-list --left-right --count origin/master...HEAD
21 19远端 21 个 commit,本地 19 个——看起来是经典的分叉,两侧都有独立进展,似乎该 rebase 或 merge。
但事情没那么简单。
现象
git push报 non-fast-forward,无法直接推git fetch显示[new branch] origin/master,说明本地从未配置过 upstream- 两侧各有一批"独有"commit,subject 列表却高度相似
- 你确信这段时间只有自己一个人在改代码
根因
这不是分叉,而是重复提交。
场景还原:同一个人在两个工作副本(比如本机和服务器)对同一批文件各自做了 commit,commit message 相同但 SHA 完全不同。Git 看到的是两条平行历史,实际上业务代码字节级完全一致。
[new branch] origin/master 这个提示更是个迷惑项——它不是说远端分支被重建了,而是说本地 .git/config 里从未配置 [branch "master"] 的 upstream,导致本地 master 从未跟踪过 origin/master,fetch 时才把远端当新分支处理。
两侧大量同 subject commit + merge → 产生一堆空冲突或重复历史。 rebase 同理,会触发大量 "empty commit"。 force push 更危险,直接覆盖远端——如果你判断错了,对方的真实工作就没了。 在确认根因之前,三种操作全部应该冻结。
诊断方法(只读,零风险)
四步快速确认,全部是读操作,不改任何状态。
Step 1:列出双方独有 commit
git log origin/master --not HEAD --oneline # 远端独有
git log HEAD --not origin/master --oneline # 本地独有Step 2:检查作者分布
git log origin/master --not HEAD --format='%an' | sort -u
git log HEAD --not origin/master --format='%an' | sort -u两侧作者集合一致,且只有你一个人 → 强烈怀疑重复提交。
Step 3:subject 配对
git log origin/master --not HEAD --format='%s' | sort > /tmp/remote-subjects.txt
git log HEAD --not origin/master --format='%s' | sort > /tmp/local-subjects.txt
diff /tmp/remote-subjects.txt /tmp/local-subjects.txtdiff 输出几乎为空 → 确证。
Step 4:业务代码字节级比对
git diff origin/master HEAD -- path/to/key-file.php输出为空 → 业务代码 100% 一致,分叉是假象。
正解
确认是重复提交后,标准处理路径:
# 1. stash 保护 working tree
git stash push --include-untracked --message "pre-align"
# 2. 基于远端 master 建对齐分支
git checkout -b align-master origin/master
# 3. cherry-pick 真正独有的 commit(subject 在远端没有对应的那批)
git cherry-pick <真正独有的 commit SHA>
# 若提示 "empty commit" → 说明远端已有相同改动,跳过
git cherry-pick --skip
# 4. fast-forward 推送
git push origin align-master:master
# 5. 本地 master 对齐
git checkout master
git reset --hard align-master
git branch -d align-master
# 6. 恢复 working tree
git stash pop不 merge、不 rebase、不 force push。找出两侧 subject 不重叠的那批 commit(真正独有的工作),cherry-pick 到对方基础上,再 fast-forward 推送。全程无破坏性操作,生产 working tree 不受影响。
git branch --set-upstream-to=origin/master master以后 git status 就能正确显示 ahead/behind,不会再有 [new branch] 的误导。
一句话外卖
[new branch] origin/master加上"只有我一个人改",先怀疑是重复提交,跑四步只读诊断,确认根因再动手,比直觉 rebase 安全一百倍。