允许在 git rebase 中合并不相关的历史记录
Allow merging unrelated histories in git rebase
当你想变基保持合并提交的分支时,你传递 --preserve-merges
标志。当您在 git 中合并不相关的历史记录时,您需要传递 --allow-unrelated-histories
标志。
如果您正在执行 git rebase --preserve-merges
当现有合并来自不相关的历史记录时,它将失败:
fatal: refusing to merge unrelated histories
如果你尝试 git rebase --preserve-merges --allow-unrelated-histories
它会失败:
error: unknown option 'allow-unrelated-histories'
是否有其他方法告诉 rebase 允许合并?
编辑:这是一个最小复制:https://github.com/vossad01/rebase-unrelated-merge-reproduction
重现结帐master
然后执行:
git rebase --preserve-merges --onto origin/a-prime HEAD~2
蛮力方法是强制一个共同的根——因为你正在尝试变基根,没有内容历史,做一个随机数空提交并告诉 git 这是历史的父您正在合并:
git rev-list --all --max-parents=0 \
| awk '{print [=10=],empty}' empty=`:|git mktree|xargs git commit-tree` \
> .git/info/grafts
git rebase here
rm .git/info/grafts
当 git rebase
合并失败时,它不会中止变基,因此您有机会手动干预。
如果您愿意手动解决这个问题,您可以按如下方式完成合并:
git merge --allow-unrelated ORIGINAL_BRANCH_THAT_WAS_MERGED --no-commit
git commit -C ORIGINAL_MERGE_COMMIT
git rebase --continue
理想情况下,Git 可以在无需人工干预的情况下处理此问题。
To reproduce checkout master then execute:
git rebase --preserve-merges --onto origin/a-prime HEAD~2 -i
git-rebase 文档说不要合并 -i
和 --preserve-merges
。
[--preserve-merges] uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).
但即使没有 -i
它仍然会失败 fatal: refusing to merge unrelated histories
。
部分问题是 HEAD~2
是 origin/a-prime
的直系祖先。您的测试回购看起来像这样:
1 [master]
|
2
|\
| | 3 [origin/a-prime]
| | |
| 4 / [origin/b]
| /
| /
|/
5 [origin/a]
master
的HEAD~2
是5。origin/a-prime
是3。你的命令相当于:
git rebase -p --onto 3 5
5 是 3 的直接祖先,因此该命令没有多大意义。如果这有效,它会做一些奇怪的事情。
the cases I have encountered a couple of times recently have been in moving a project's documentation from GitHub Wiki to GitHub Pages (when the website already exists).
这是对 rebase 的不当使用。 Rebase 将平行历史变成线性历史,基本上假装一组更改一直在另一组之上完成。这对于在处理功能分支时保持最新状态这样的事情很有用,如果你没有一堆除了更新分支什么都不做的中间合并提交,那么簿记和审查会更容易。对于将来阅读代码和提交历史的任何人来说,这些只是噪音。
但是当你有两个真正不同的历史时,最好将它们保留为不同的历史。合并它们讲述了正确的故事:网站和文档是分开开发的,但后来合并为一个单元。
1 - 3 - 5
\
2 - 4 - 6 - 7 - 8 [master]
您可以使用 git log --topo-order
按拓扑顺序 (8, 7, 6, 5, 3, 1, 4, 2) 分别查看它们,或者您可以按日期顺序交错查看它们 (8, 7、6、5、4、3、2、1),git log
默认值。 gitk
或 GitX 等历史可视化工具将同时显示这两个订单。
在另一个之上变基是在说谎:我们在网站上工作,然后我们在文档上工作,然后在某个时候(你必须找到这个点)并且出于某种原因我们一起处理网站和文档。
1 - 3 - 5 - 2 - 4 - 6 - 7 - 8 [master]
这会丢失重要信息,并让人不解为什么某些更改在未来变得更加困难。
进行合并,这是正确的做法。
同步两个不同分支的唯一方法是将它们重新合并在一起,从而产生一个额外的合并提交和两组包含相同更改的提交(原始的和来自你的 rebased 分支的) .不用说,这是一个非常混乱的情况。
所以,在你 运行 git rebase
之前,总是问自己,“还有其他人在看这个分支吗?”如果答案是肯定的,请将手从键盘上拿开,并开始考虑以非破坏性方式进行更改(例如,git revert
命令)。否则,您可以随心所欲地重写历史。
参考:https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing
当你想变基保持合并提交的分支时,你传递 --preserve-merges
标志。当您在 git 中合并不相关的历史记录时,您需要传递 --allow-unrelated-histories
标志。
如果您正在执行 git rebase --preserve-merges
当现有合并来自不相关的历史记录时,它将失败:
fatal: refusing to merge unrelated histories
如果你尝试 git rebase --preserve-merges --allow-unrelated-histories
它会失败:
error: unknown option 'allow-unrelated-histories'
是否有其他方法告诉 rebase 允许合并?
编辑:这是一个最小复制:https://github.com/vossad01/rebase-unrelated-merge-reproduction
重现结帐master
然后执行:
git rebase --preserve-merges --onto origin/a-prime HEAD~2
蛮力方法是强制一个共同的根——因为你正在尝试变基根,没有内容历史,做一个随机数空提交并告诉 git 这是历史的父您正在合并:
git rev-list --all --max-parents=0 \
| awk '{print [=10=],empty}' empty=`:|git mktree|xargs git commit-tree` \
> .git/info/grafts
git rebase here
rm .git/info/grafts
当 git rebase
合并失败时,它不会中止变基,因此您有机会手动干预。
如果您愿意手动解决这个问题,您可以按如下方式完成合并:
git merge --allow-unrelated ORIGINAL_BRANCH_THAT_WAS_MERGED --no-commit
git commit -C ORIGINAL_MERGE_COMMIT
git rebase --continue
理想情况下,Git 可以在无需人工干预的情况下处理此问题。
To reproduce checkout master then execute:
git rebase --preserve-merges --onto origin/a-prime HEAD~2 -i
git-rebase 文档说不要合并 -i
和 --preserve-merges
。
[--preserve-merges] uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).
但即使没有 -i
它仍然会失败 fatal: refusing to merge unrelated histories
。
部分问题是 HEAD~2
是 origin/a-prime
的直系祖先。您的测试回购看起来像这样:
1 [master]
|
2
|\
| | 3 [origin/a-prime]
| | |
| 4 / [origin/b]
| /
| /
|/
5 [origin/a]
master
的HEAD~2
是5。origin/a-prime
是3。你的命令相当于:
git rebase -p --onto 3 5
5 是 3 的直接祖先,因此该命令没有多大意义。如果这有效,它会做一些奇怪的事情。
the cases I have encountered a couple of times recently have been in moving a project's documentation from GitHub Wiki to GitHub Pages (when the website already exists).
这是对 rebase 的不当使用。 Rebase 将平行历史变成线性历史,基本上假装一组更改一直在另一组之上完成。这对于在处理功能分支时保持最新状态这样的事情很有用,如果你没有一堆除了更新分支什么都不做的中间合并提交,那么簿记和审查会更容易。对于将来阅读代码和提交历史的任何人来说,这些只是噪音。
但是当你有两个真正不同的历史时,最好将它们保留为不同的历史。合并它们讲述了正确的故事:网站和文档是分开开发的,但后来合并为一个单元。
1 - 3 - 5
\
2 - 4 - 6 - 7 - 8 [master]
您可以使用 git log --topo-order
按拓扑顺序 (8, 7, 6, 5, 3, 1, 4, 2) 分别查看它们,或者您可以按日期顺序交错查看它们 (8, 7、6、5、4、3、2、1),git log
默认值。 gitk
或 GitX 等历史可视化工具将同时显示这两个订单。
在另一个之上变基是在说谎:我们在网站上工作,然后我们在文档上工作,然后在某个时候(你必须找到这个点)并且出于某种原因我们一起处理网站和文档。
1 - 3 - 5 - 2 - 4 - 6 - 7 - 8 [master]
这会丢失重要信息,并让人不解为什么某些更改在未来变得更加困难。
进行合并,这是正确的做法。
同步两个不同分支的唯一方法是将它们重新合并在一起,从而产生一个额外的合并提交和两组包含相同更改的提交(原始的和来自你的 rebased 分支的) .不用说,这是一个非常混乱的情况。
所以,在你 运行 git rebase
之前,总是问自己,“还有其他人在看这个分支吗?”如果答案是肯定的,请将手从键盘上拿开,并开始考虑以非破坏性方式进行更改(例如,git revert
命令)。否则,您可以随心所欲地重写历史。
参考:https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing