从git 1.9 / 2.0 Q1 2014开始,您将不必标记先前的分支原点,就可以将其基于重新编写的上游分支,如Aristotle Pagaltzis的答案所述:
请参阅commit 07d406b和commit d96855f:
在使用topic创建的分支之后git checkout -b topic origin/master,远程跟踪分支的历史origin/master可能已经被重新记录和重建,从而产生了这种形状的历史:
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
其中,origin/master在提交用于点B3,B2,B1现在它指向B,和你的topic分支开始在上面的回来时origin/master在B3。
此模式使用reflog的origin/masterfindB3作为派生点,因此topic可以根据更新origin/master的基础重新构建:
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
这就是该git merge-base命令具有新选项的原因:
--fork-point::
找到一个分支(或导致其的任何历史记录<commit>)与另一个分支(或任何参考)之间的分叉点<ref>。
这不仅要查找两次提交的共同祖先,而且还要考虑reflog,<ref>以查看历史是否导致了<commit>分支的早期化身<ref>。
“ git pull --rebase”命令使用分支工作的“ base”分支(通常是远程跟踪分支)的引用日志条目来计算要重新建立分支的分支点,以应对“基础”情况分支机构已倒回并重建。
例如,如果历史记录如下所示:
- “
base”分支的当前尖端位于B,但是较早的提取观察到它的尖端曾经是B3,然后B2再B1
到达当前提交之前,然后
- 根据最新的“基础”重新建立分支的分支基于commit
B3,
它试图找到B3通过的“输出去git rev-list --reflog base”(即B,B1,B2,B3),直到找到一个提交,它是当前尖端的祖先“ Derived (topic)”。
在内部,我们get_merge_bases_many()可以通过一次计算。
我们希望合并之间的合并基础Derived和虚构的合并提交,这将通过合并所有“ base (origin/master)”的历史提示而产生。
当存在这样的提交时,我们应该得到一个单一的结果,该结果与“ base”的引用条目之一完全匹配。
Git的2.1(Q3 2014)将增加使这个功能更强大的这样:看到提交1e0dacd由约翰·行动(johnkeeping)
正确处理具有以下拓扑的方案:
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
哪里:
B'是该版本的固定版本,B与并不完全相同B;
C*且与和D*补丁相同,C并且D如果以错误的顺序应用,则在文本上冲突;
E从文字上取决于D。
的正确结果git rebase master dev即B被识别为的叉点dev和master,从而C,D,E是需要被重放到提交master; 但C和D是补丁与相同C*和D*等都可以被丢弃,从而使最终结果是:
o --- B' --- C* --- D* --- E <- dev
如果未识别出分叉点,则选择B包含分支的B'结果将导致冲突;如果未正确识别补丁相同的提交,则选择C包含D(或等效D*结果)的分支将导致冲突。
当在2.20年代用C重写命令时--fork-point,“ git rebase”的“ ”模式返回,已在Git 2.27(2020年第二季度)中进行了更正。
参见Junio C Hamano()提交的f08132f(2019年12月9日)。(通过合并JUNIOÇ滨野- -在提交fb4175b 3月27日2020)gitster
gitster
rebase:--fork-point回归修复
签名人:Alex Torok
[jc:修改了补丁,并使用了Alex的测试]
签名人:Junio C Hamano
“ git rebase --fork-point master”过去工作正常,因为它内部称为“ git merge-base --fork-point”,它知道如何处理短refname并在调用基础get_fork_point()函数之前将其dwim更改为完整的refname 。
在用C重写命令之后,这种情况不再成立,因为直接对其进行的内部调用get_fork_point()不会删除短引用。
将“ git merge-base”中使用的“ dwim refname参数移至完整的refname”逻辑移至基础get_fork_point()函数,以便实现“ git rebase”的函数的另一个调用者以相同的方式进行修复这种回归。