阅读git rebase
和git merge-base
人员文档:
在使用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,并且当origin / master在B3时,您的主题分支在它之上启动。此模式使用reflog origin / master找到B3作为分叉点,以便可以通过以下方式在更新的origin / master之上重新定位主题:
$ fork_point=$(git merge-base --fork-point origin/master topic) $ git rebase --onto origin/master $fork_point topic
$fork_point
将(如果我理解正确的话)是提交对象B3
,因此提交B3..topic
将被重新定位到origin/master
分支。
Q1 为什么省略B3
提交有用? topic
分支的提交建立在B3
提交之上,因此省略它将意味着在origin/master
分支的故事中将缺少其修改。重新定位B3
提交和 topic
分支会带来更清晰的历史,不会吗?
Q2 有人可以链接/简要描述git工作流程中--fork-point
选项的实际用例吗?
答案 0 :(得分:11)
{J} $fork_point
{/ 1}}是正确的。
我相信这里的意图是省略B3
为"而不是你的提交"。
我认为Git人员在这里绘制的图表并不是那么好。这里是我如何在不改变它的情况下重绘和重写它(尽管我可能只是重写每个提交的内容)。
首先克隆(或以其他方式更新)某些(B3
)存储库,其图表以commit origin
结尾,然后创建一个主题分支并进行一些提交:
B3
随着时间的推移,使用额外的...--o---F---B3 <-- origin/master
\
G <-- topic
- es和git fetch
,您的提交图现在看起来像这样:
git commit
但是,突然之间,在另一个 ...--o---F---B3--B2--B1 <-- origin/master
\
G---H---I <-- topic
之后,您自己的提交图现在看起来像这样:
git fetch
也就是说,Git现在认为提交B3属于您的主题分支,实际上,您的工作始于提交 o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
B3--G---H---I <-- topic
。拥有名为G
的存储库的人实际上已声明提交origin
很糟糕,应该被丢弃。 (他们在B3
上保留了B2
B2'
的副本,master
上保留了B1
B1'
之一。)
如果您只是foo
,则会将原始提交git rebase
复制到新副本B3
(同时还要复制B3'
):
G-H-I
但您宁愿选择:
o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
B3'-G'--H'--I' <-- topic
要 o---B1' <-- origin/foo
/
...o---F---B2'-o---o---o---B <-- origin/master
\
G'--H'--I <-- topic
执行此操作,您必须指示Git找到提交git rebase
。您的B3
的reflog中包含所有origin/master
,F
,B3
和B2
(至少有一个reflog条目,包括本案例{ {1}}),同时您自己的B1
还有origin/master@{1}
和topic
,但F
也不是B3
。因此,B2
选择B1
作为最新(最尖端)共享提交,而不是--fork-point
。
这里的关键句子/想法是上游存储库编写者打算完全放弃提交B3
。
(你应该如何知道这一点有点神秘。如果需要重新定位,例如丢弃文件,F
和B3
可能不是很明显应该永远不会被提交 - 并且在B2'
中,这也是B1'
也被丢弃的原因。现在B1
和B1
中省略了这个文件这一事实非贴片等效,因此不是明显的副本。)
(请注意,您自己的B2'
仍然指向B3'
!)