“fatal: refusing to merge unrelated histories” 一般出现在本地先 git init、远程仓库已有提交的时候。网上都是一句 --allow-unrelated-histories。这篇在本机复现完整的报错顺序,看加了这个参数之后仓库到底变成什么样,以及不用这个参数还有哪些更干净的办法。
$ git push -u origin main 2>&1 | head -3
To ../remote.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to '../remote.git'
$ git fetch origin 2>&1 | tail -2
From ../remote
* [new branch] main -> origin/main
$ git pull origin main 2>&1 | tail -1
fatal: Need to specify how to reconcile divergent branches.
$ git pull --no-rebase origin main (退出码 128)
From ../remote
* branch main -> FETCH_HEAD
fatal: refusing to merge unrelated histories
$ git merge origin/main (退出码 128)
fatal: refusing to merge unrelated histories
$ git pull --rebase origin main 2>&1 | head -4; git log --oneline
From ../remote
* branch main -> FETCH_HEAD
Rebasing (1/1)
Successfully rebased and updated refs/heads/main.
f2dcb43 first local commit
d55edc3 Initial commit先是 push 被拒(fetch first),不带参数的 pull 报需要选择合并方式,指定合并才报 unrelated histories。
$ git fetch -q origin; git merge-base main origin/main; echo "退出码 $?"
退出码 1
$ git log --all --format='%h 父提交:[%p] %s'
4c8db55 父提交:[] first local commit
d55edc3 父提交:[] Initial commit
$ git rev-list --max-parents=0 --all | wc -l | tr -d " "
2
(上一行是所有分支里的根提交个数:正常的项目只有 1 个)两条历史各有一个根提交,merge-base 找不到共同祖先。
$ git pull --no-rebase --allow-unrelated-histories --no-edit origin main 2>&1 | tail -4
Merge made by the 'ort' strategy.
README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README.md
$ git log --oneline --graph; ls; git rev-list --max-parents=0 --all | wc -l | tr -d " "
* 9d43154 Merge branch 'main' of ../remote
|\
| * d55edc3 Initial commit
* 4c8db55 first local commit
README.md
app.py
2
$ git pull --no-rebase --allow-unrelated-histories --no-edit origin main 2>&1 | tail -4; git status --short
* [new branch] main -> origin/main
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
AA README.md
$ cat README.md
<<<<<<< HEAD
# my project
=======
# project
>>>>>>> d55edc34915f384b98b9c626365db24737ef9c5e文件不重名就合并成功,但仓库永远有两个根;同名文件是 add/add 冲突。
$ git fetch -q origin && git rebase origin/main 2>&1 | tail -2; git log --oneline --graph; git rev-list --max-parents=0 --all | wc -l | tr -d " "
Rebasing (1/1)
Successfully rebased and updated refs/heads/main.
* f2dcb43 first local commit
* d55edc3 Initial commit
1
$ git fetch -q origin && git reset --hard origin/main 2>&1 | tail -1; ls; git log --oneline
HEAD is now at d55edc3 Initial commit
README.md
d55edc3 Initial commit变基到远程历史上得到一条直线;本地没价值就 reset --hard 到远程。
同样的文件、同样的提交说明,重新 init 之前的根提交 7a4645e,之后 357531c
$ git remote add origin ../remote2.git && git fetch -q origin && git merge origin/main 2>&1 | tail -1; git push origin main 2>&1 | head -3
fatal: refusing to merge unrelated histories
To ../remote2.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to '../remote2.git'删掉 .git 重新 init 会得到不同的根提交哈希。