Git rebase - 在fork-point模式下提交select

Seb*_*Nag 9 git version-control github

阅读git rebasegit merge-base人文档:

在使用git checkout -b topic origin/master创建的主题分支之后,远程跟踪分支origin/master的历史记录可能已经倒带和重建,从而导致了这种形状的历史记录:

                        o---B1
                       /
       ---o---o---B2--o---o---o---B (origin/master)
               \
                B3
                 \
                  Derived (topic)
Run Code Online (Sandbox Code Playgroud)

origin/master用于指向提交B3,B2,B1,现在它指向B,当origin/master位于B3时,您的主题分支在它上面启动.此模式使用origin/master的reflog来查找B3作为分叉点,以便可以通过以下方式在更新的origin/master之上重新定位主题:

$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
Run Code Online (Sandbox Code Playgroud)

$fork_point将(如果我理解正确的话)是提交对象B3,因此提交B3..topic将被重新绑定到origin/master分支.

Q1为什么省略B3提交有用?topic分支的提交建立在B3提交之上,因此省略它意味着它的修改将在origin/master分支的故事中丢失.衍合的B3提交topic分支会导致一个更清洁的历史,是不是?

Q2有人可以链接/简要描述--fork-pointgit工作流中该选项的实际用例吗?

tor*_*rek 12

你是$fork_point对的B3.

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

我认为Git人员在这里绘制的图表并不是那么好.这是我如何在不改变它的情况下重绘和重写它(尽管我可能只是重写每个提交).


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

...--o---F---B3    <-- origin/master
              \
               G   <-- topic
Run Code Online (Sandbox Code Playgroud)

随着时间的推移,使用额外的git fetch-es和git commits,您的提交图现在看起来像这样:

...--o---F---B3--B2--B1    <-- origin/master
              \
               G---H---I   <-- topic
Run Code Online (Sandbox Code Playgroud)

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

                 o---B1'       <-- origin/foo
                /
...o---F---B2'-o---o---o---B   <-- origin/master
        \
         B3--G---H---I         <-- topic
Run Code Online (Sandbox Code Playgroud)

也就是说,Git现在认为提交B3属于您的主题分支,实际上,您的工作始于提交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
Run Code Online (Sandbox Code Playgroud)

但你宁愿选择:

                 o---B1'                 <-- origin/foo
                /
...o---F---B2'-o---o---o---B             <-- origin/master
                            \
                             G'--H'--I   <-- topic
Run Code Online (Sandbox Code Playgroud)

为此git rebase,您必须指示Git找到提交B3.您的引用日志origin/master拥有所有的F,B3,B2,和B1在它(在至少一个引用日志条目,包括在这种情况下origin/master@{1}),而自己topicFB3,但不会B2,也不B1在它.因此--fork-point选择B3最新(最尖端)共享提交,而不是F.


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

(你应该如何知道这一点有点神秘.如果需要重新定义,例如丢弃一个本来应该没有提交的文件,那么可能并不明显,B2'并且B1'是副本B1,这是为什么B1还被丢弃了.这个文件现在被省略了,B2'并且B3'使它们不是补丁等价的,因此不是明显的副本.)

(注意你自己master也指向B3!)

  • @BreakingBenjamin:是的,很明显,`--fork-point` 的目的是解决上游强制推送问题。我不认为这是一个很好的实现,但是这里没有单一的正确行为。Mercurial 的 Evolve 扩展在理论上是处理这个问题的更好方法(我不知道它在实践中是如何工作的,没有使用过),但是 Evolve 不太适合 Git 的实现。 (2认同)