Git rebase的--merge选项有什么作用?

Jür*_*gen 6 git git-rebase

手册页git-rebase(1)说:

-m
--merge
使用合并策略进行基准调整。[...]

但是当然,如​​果不使用该--merge选项,也可能会遇到“合并冲突” 。因此,在那种情况下,也必须有任何“合并策略”来处理这些冲突。

有什么区别使得可以--merge选择重新基准。

这似乎是一个相当基本的东西:对于A rebase --merge,Git将其工作文件存储在一个名为的文件夹中$GIT_DIR/rebase-merge(与交互式rebase一样)。如果--merge未使用该选项(并且变基是非交互式的),则该文件夹名为$GIT_DIR/rebase-apply

tor*_*rek 8

一句话,什么-m--merge做的git rebase是确保重订用途git cherry-pick内部。

-m强制摘樱桃的标志通常(但并非总是)是多余的。特别是,无论如何,任何交互式资源库都始终使用自动选择。正如joanis在评论中指出的那样,指定任何-s-X选项也将强制使用Cherry-pick。所以呢-k,如下所述。

长(或至少更长)

Rebase在Git中有很长的历史:第一个rebase操作是通过将每个要重新构建的提交格式化为补丁,然后将补丁应用于其他提交来完成的。也就是说,最初git rebase主要是:

branch=$(git symbolic-ref --short HEAD)
target=$(git rev-parse ${onto:-$upstream})
git format-patch $upstream..HEAD > $temp_file
git checkout $target
git am -3 $temp_file
git checkout -B $branch HEAD
Run Code Online (Sandbox Code Playgroud)

(除了参数处理,所有错误检查,以及git am可能会因错误而停止,需要手动修复和的事实git rebase --continue;此外,上述脚本是我为降低可读性而设计的版本,可能与原始脚本不太相似)。

这种变基可以很好地处理大多数情况。不能很好处理的最常见情况是在某些文件重命名之间重新设置基准。它也不能复制“空”提交(即补丁为空的提交),因为git format-patch不允许省略补丁部分。

git rebase即使使用-m,这些空的提交通常也会被省略;您必须添加-k以保存它们。要保留它们,git rebase必须切换到cherry-pick变体(如果尚未这样做)。

要传递-s或传递-X参数,rebase必须调用git cherry-pick而不是git am,因此这些标志中的任何一个也都需要cherry-pick变体。

使用git format-patch从不执行任何重命名检测。因此,如果您要复制的提交流都应针对进行重命名检测HEAD,则此-m标志非常重要。作为一个具体的示例,请考虑以下一系列提交:

          B--C--D   <-- topic
         /
...--o--A--E--F--G   <-- mainline
Run Code Online (Sandbox Code Playgroud)

假设Ato BBto CCto 的差异D全部在名为的文件中处理lib-foo.ext。但是在commit中F,该文件被重命名lib/foo.ext。一git format-patchA..D会显示更改是文件所做的lib-foo.ext,其中没有将正确运用犯G,因为没有lib-foo.ext文件。整个重新设置将失败。

一个git cherry-pick犯的B时候HEAD标识提交G,不过,会发现重命名和应用的A航班吗B更改的版本lib/foo.ext中承诺G

          B--C--D   <-- topic
         /
...--o--A--E--F--G   <-- mainline
                  \
                   B'   <-- HEAD [detached]
Run Code Online (Sandbox Code Playgroud)

Cwhile HEAD标识的下一个Cherry-pick B'将发现B-to- Cchange to libfoo.ext应该应用于重命名的lib/foo.ext,而最后一次Cherry-pick D将会执行相同的操作,以便重新设置成功。

重命名检测代码很慢,因此通过系统运行时,无需重命名且没有“空”提交的重做基准可以更快地运行git format-patch | git am。那是原始方法比Cherry-pick变体更好的唯一方法:在受约束的情况下它更快。(但是,只有在存在大量重命名候选者时,速度才会提高,但是它们都不是实际的重命名,或者它们都不重要。)

(注意:-3参数,或者--3way使用更长的拼写,告诉git am将该标志传递给each git apply,如果需要,应用将尝试使用indexdiff 中的行中的blob哈希进行三向合并。在某些情况下,似乎可以处理重命名的文件,特别是如果blob哈希完全匹配时,cherry-pick方法执行完全重命名检测,可以处理不精确的匹配;-3不能这样做,另请参见git之间的区别是什么Jürgen所述cherry-pick和git format-patch | git am?)。

  • @joanis:不,没有(或者不是我上次看过,可能是2.15ish),我希望至少在某些情况下会失败。请注意,尽管git am使用git apply -3在blob上进行三向匹配,所以可能会找到纯重命名(而不是mod-name重命名)。我将不得不做一些实验来检查这里所有的细节。 (2认同)