`--abort` 和 `--quit` 作为 `cherry-pick` 的定序器子命令有什么不同?

What's different between `--abort` and `--quit` as sequencer subcommands for `cherry-pick`?

根据 doc,在 cherry-pick 的三个音序器子命令中,我们有这两个对我来说非常相似:

--quit

Forget about the current operation in progress. Can be used to clear the sequencer state after a failed cherry-pick or revert.

--abort

Cancel the operation and return to the pre-sequence state.


到目前为止,我一直使用 --abort,而且效果很好。 --quit 是 different/preferable 的用例是什么?

--abort 将带您回到开始选择操作之前的位置,而 --quit 将退出操作并让您保持在当前的修订版。我想不出一个用例,除了你想在你遇到一个无法自动挑选的修订版后转向不同的方向,这就是为什么挑选首先停止的原因,对吧?

如果您还记得 git rebase 是一系列 git cherry-pick 操作,1 再加上开始和结束时的几个有用的噱头,它使更有意义。

假设您有以下一系列提交:

...--o--*--...--o   <-- mainline
         \
          A--B--C   <-- feature

您想使 featuremainline 保持同步,因此您:

git checkout feature
git rebase mainline

Git 首先枚举可从 feature (C, B, A, *, .. .) 以及可从 mainline 到达的那些(未命名,...,*,...)。它从 feature 集合 2 中减去 mainline 集合并使用反向拓扑顺序,因此它现在具有散列 ID AB,并且 C 列在 Git 调用 sequencer 的东西中。 (sequencer 还记录了操作,在本例中为 rebase / cherry-pick。sequencer 也用于多次恢复。sequencer 可以中途停止,然后使用 --continue 恢复。这就是它需要知道的原因操作:我们是继续挑选、还原还是变基?)

Git 然后通过定序器在 mainline 和 运行 的提交处分离 HEAD 操作,无论它是什么。由于 op 是“rebase”,因此音序器的每一步都是一个简单的一次提交 cherry-pick:

(with)

...--o--*--...--o   <-- mainline, HEAD
         \
          A--B--C   <-- feature

(execute git cherry-pick A to produce)

                  A'   <-- HEAD
                 /
...--o--*--...--o   <-- mainline
         \
          A--B--C   <-- feature

这可能会因合并​​冲突而失败。如果是这样,定序器会停止,在索引和工作树中留下一团混乱的合并冲突。您可以修复它们并恢复音序器(如果需要,如果您没有自己制作 A',它将承诺您制作 A'),或者选择两种停止中的一种,“中止”或“退出”。如果你恢复——或者如果一切顺利——我们继续(尝试)挑选 B:

                  A'-B'   <-- HEAD
                 /
...--o--*--...--o   <-- mainline
         \
          A--B--C   <-- feature

假设这也成功了,我们继续尝试挑选 C,但这次尝试 失败了 。定序器停止,让您的索引和工作树一团糟,我们在上面看到的图表相同:A'B' 存在,但 C' 不存在。

假设我们决定停止:目前完成 C 的挑选太难了,我们需要退后一步,做点别的事情。您现在有两个选项,abortquit.

如果您选择 --abort,Git 会将您的 HEAD 重新附加到 feature,给出:

...--o--*--...--o   <-- mainline
         \
          A--B--C   <-- feature (HEAD)

A'B' 在哪里?好吧,如果你知道自己在做什么,你可以从 reflogs 中找出它们,或者你已经巧妙地将分支或标签名称附加到 B' before 选择 --abort。但是,如果您选择 --quit,Git 会在不移动 HEAD 的情况下终止变基 ,因此您会得到:

                  A'-B'   <-- HEAD
                 /
...--o--*--...--o   <-- mainline
         \
          A--B--C   <-- feature

但现在可以使用 git reset --hard 为自己创建一个干净的索引和工作树。 (或者,你可以把乱七八糟的东西留在原地。)所以你 没有 足够聪明,可以在 之前 --quit.

基本上就这些了。 :-) 但是在经历了 很多 冲突的漫长而令人沮丧的 rebase 之后,您想保存到目前为止所取得的成就并返回到非 rebase 工作,然后再返回稍后再次变基,“退出”变体在某种程度上感觉更令人满意。

(我认为这里真正缺少的是保存 sequencer 状态的其余部分并在以后恢复它的选项。但是,sequencer 状态是每个工作树,所以如果你有一个正在进行的 rebase 任务并且必须用更高优先级的任务中断它,你可以只为更高优先级的任务添加一个工作树。通过 Git 2.15 添加的工作树中的各种错误并不是那么令人鼓舞,但它们似乎确实现在表现良好。添加的工作树也覆盖了另一个更大的缺失部分,这是保存正在进行的冲突合并并在以后恢复它的能力。)


1但是请注意,旧式非交互git-rebase--am仍然使用git format-patchgit am。在某些情况下,此过程对重命名的文件不起作用,并且无法复制“不做任何更改”提交,但 运行 更快 。在大多数情况下,尽管底层机制发生了变化,但这种风格和 cherry-pick 风格都应该给出相同的结果,特别是因为 cherry-pick 变体 defaults 不复制 "makes no更改”提交。

2rebase 还减去了 mainline 集中存在的任何提交,并且与 [=18] 中的任何提交具有相同的 git patch-id =] 设置,当然,默认情况下,它会减去所有合并。