首页 > 解决方案 > Git rebase 的 --merge 选项有什么作用?

问题描述

手册页git-rebase(1)说:

-m
--merge
使用合并策略来变基。[...]

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

有什么区别可以--merge选择变基。

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

标签: gitgit-rebase

解决方案


一句话,-mor--mergegit rebase为了确保 rebase 在git cherry-pick内部使用。

-m强制挑选樱桃的标志通常是多余的,但并不总是多余的。特别是,任何交互式变基总是使用cherry-pick。正如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

(除了参数处理,所有错误检查,以及可以因错误而停止的事实git am,需要手动修复和git rebase --continue)。

这种变基可以很好地处理大多数情况。它不能很好地处理的最常见情况涉及跨某些文件重命名的 rebase。它也不能复制“空”提交——即补丁为空的提交——因为git format-patch不允许省略补丁部分。

git rebase即使在使用-m;时,这些空提交通常也会被忽略。您必须添加-k以保留它们。要保存它们,git rebase必须切换到cherry-pick 变体,如果它还没有这样做的话。

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

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

          B--C--D   <-- topic
         /
...--o--A--E--F--G   <-- mainline

假设从Ato BBtoCCto的差异D都在一个名为 的文件中处理lib-foo.ext。但是在 commit 中F,这个文件被重命名lib/foo.ext。A git format-patchofA..D将显示要对文件进行的更改,由于没有文件,lib-foo.ext这些更改都不会正确应用于提交。整个变基将失败。Glib-foo.ext

但是,当识别出 commit时, A git cherry-pickof commit将找到重命名并将-vs-更改应用于in commit的版本:BHEADGABlib/foo.extG

          B--C--D   <-- topic
         /
...--o--A--E--F--G   <-- mainline
                  \
                   B'   <-- HEAD [detached]

Cwhile HEADidentify的下一个 cherry-pickB'将发现B-to - Cchange tolibfoo.ext应该应用于改名的lib/foo.ext,并且最后一个cherry-pickD将执行相同的操作,因此 rebase 将成功。

重命名检测代码很慢,所以一个没有重命名的变基,没有“空”提交,通过系统运行时可以运行得更快git format-patch | git am。这是原始方法比樱桃挑选变体更好的唯一方法:在受限情况下它更快。(但是,只有当有很多重命名候选者时,速度才会提高,但是它们都不是实际的重命名,或者它们都不重要。)

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


推荐阅读