在 git 交互式变基期间无法理解改写标志的行为

Unable to understand the behaviour of reword flag during git interactive rebase

我有几个关于 git interactive rebase 的问题。 首先,我在本地计算机上创建了一个 git 存储库并执行了 5 次提交。

  1. 当我点击 git rebase -i HEAD~5 时,出现以下错误

    fatal: Needed a single revision
    invalid upstream HEAD~5
    

    我不明白上面错误的原因

  2. 当我进入 rebase 交互 shell 时,我尝试使用 r 标志的改写选项并提供更新的消息。当我尝试保存并退出时,它启动了另一个终端来传递提交消息。我错过了一些东西。有人可以教育我这种行为吗?

从根本上说,rebase 是通过复制 提交来工作的。例如,假设您有我在下面标记为 AD 的四个提交,并且您想将 branch 变基到 mainline:

...--o--o--T   <-- mainline
      \
       A--B--C--D   <-- branch (HEAD)

git rebase mainline复制 A 到一个新的提交 A' 即 "like A, but just as good or better":

             A'   <-- temporary (HEAD)
            /
...--o--o--T   <-- mainline
      \
       A--B--C--D   <-- branch

AA' 的区别在于 A'Tmainline 的提示作为其父提交。 (此外,如果您使用交互式变基,它还有您需要对其进行的任何其他更改。)

一旦 A 被复制到 A'git rebase 继续复制 B,然后是 CD。最终结果是:

             A'-B'-C'-D'   <-- temporary (HEAD)
            /
...--o--o--T   <-- mainline
      \
       A--B--C--D   <-- branch

现在所有提交都已复制,git rebase "peels off" 旧分支标签 branch 并将其移动以替换临时分支名称:

             A'-B'-C'-D'   <-- branch (HEAD)
            /
...--o--o--T   <-- mainline
      \
       A--B--C--D   [abandoned]

您传递给 git rebase 的参数是您希望副本进行的提交的名称。在这种情况下,名称 mainline 命名为提交 T,因此副本位于 T.

之后

既然你知道了这一点,并注意到 HEAD~5 意味着来自 HEAD 的 "count back five steps",我们可以解释你的问题:

git rebase -i HEAD~5 [fails]

假设您只有 链中要复制的五个提交:

A--B--C--D--E   <-- master

其中 A 没有 parent 提交,即是 root 提交。 HEAD 名称提交 EHEAD~1 姓名 DHEAD~2 姓名 C,等等。 HEAD~5 是什么提交?

A之前没有提交。 git rebase 通常用于复制 一些现有提交之后的提交,但是如果你想复制 A 本身,你将如何命名 [=16= 之前的提交] 副本应该在后面,让 rebase 从提交开始复制 A?

这就是 --root 的用武之地:git rebase --root 允许您复制 A 本身。 Git使用了一些特殊的技巧来做到这一点,最终的结果是一个独立的副本链:

A--B--C--D--E   [abandoned]

A'-B'-C'-D'-E'  <-- master

When I get to the rebase interactive shell, I tried the reword option using the r flag and provided the updated message. When I tried to save and exit it launched another terminal to pass the commit message.

所有 rewordr 所做的就是修改复制过程:Git 仍然复制提交,一次一个,到新的提交,但是当它进行时"reword" 提交的副本,它会触发 git commit --edit 而不是 git commit --no-edit。这会在原始提交消息上显示您的编辑器,您现在可以重新措辞。

您最初编辑的指令 sheet 不允许您更改整个提交消息,因为提交消息(或应该)不仅仅是一行。所以它最终完全 忽略 您所做的任何其他更改,而不是从 pick.

更改命令

新的编辑器会话仅针对一个特定的提交。

(更准确地说,命令 pick <hash> 的字面意思是给定散列上的 *运行 git cherry-pick。散列 ID 必须有效。如果您重新排列指令 sheet,你重新安排了交互式变基 运行 的 git cherry-pick 命令的顺序。如果你删除或注释掉一行,Git 根本就不会挑选该特定提交。使用 reword 而不是 pick 只会使 cherry-pick 提交交互,而不是完全自动化。)