Git 变基 - 在分叉点模式下提交选择



阅读git rebasegit merge-base人文档:

在使用 git checkout -b 主题 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 时,您的主题分支是在它之上启动的。此模式使用 源/主节点,以查找 B3 作为分叉点,以便可以通过以下方式在更新的源/主节点之上重新定位主题:

$ 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选项的实际用例吗?

你是对的,$fork_point将被B3.

我相信这里的意图是省略B3"不是你的承诺"。

我认为 Git 人员在这里绘制的图表不是很好。 以下是我将如何在不对其进行太多更改的情况下重新绘制和重写它(尽管无论如何我可能只是重新写字母每个提交)。


您首先克隆(或以其他方式更新)一些(origin)存储库,其图形以提交B3结尾,然后创建一个主题分支并进行一些提交:

...--o---F---B3    <-- origin/master

G   <-- topic

随着时间的推移,加上额外的git fetch-es 和git commits,您的提交图现在如下所示:

...--o---F---B3--B2--B1    <-- origin/master

G---H---I   <-- topic

但是,突然之间,在另一个git fetch之后,你自己的提交图现在看起来像这样:

o---B1'       <-- origin/foo
/
...o---F---B2'-o---o---o---B   <-- origin/master

B3--G---H---I         <-- topic

也就是说,Git 现在会认为提交 B3 属于您的主题分支,而实际上,您的工作始于提交G。 实际上,拥有名为origin的存储库的人已经宣布提交B3是可怕的,应该被丢弃。 (他们在master上保留了B2作为B2'的副本,在他们的foo上保留了B1B1'的副本。

如果您只是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 rebase执行此操作,您必须指示 Git 找到提交B3。 你的 reflogorigin/master包含所有FB3B2B1(至少在一个 reflog 条目下,包括在本例中为origin/master@{1}),而你自己的topicFB3,但不是B2也不是B1。 因此,--fork-point选择B3作为最新(最尖端)共享提交,而不是F


这里的关键句子/想法是上游存储库编写者打算完全丢弃提交B3

(你应该如何确定这一点有点神秘。 如果变基需要,例如,丢弃一个不应该被提交并且处于B1中的文件,那么B2'B1'是副本可能并不明显,这就是为什么B1也被丢弃的原因。 事实上,这个文件现在在B2'B3'中被省略了,这使得它们不是补丁等效的,因此不是明显的副本。

(请注意,您自己的master也仍然指向B3

最新更新