我几乎没有与git interactive rebase
相关的问题。
首先,我在本地计算机上创建了一个git存储库,并执行了5次提交。
当我点击git rebase -i HEAD~5
时,我收到以下错误
fatal: Needed a single revision
invalid upstream HEAD~5
我不明白上述错误的原因
当我到达rebase交互式shell时,我使用r
标志尝试了reword选项并提供了更新的消息。当我尝试保存并退出时,启动了另一个终端来传递提交消息。我错过了什么。有人可以教育我这个行为。
答案 0 :(得分:2)
从根本上说,rebase通过复制提交。例如,假设您有四个我在下面标记为A
到D
的提交,并且您希望将branch
重新绑定到mainline
:
...--o--o--T <-- mainline
\
A--B--C--D <-- branch (HEAD)
git rebase mainline
将会复制 A
到“A'
的新提交A
,但同样好或更好“:
A' <-- temporary (HEAD)
/
...--o--o--T <-- mainline
\
A--B--C--D <-- branch
A
和A'
之间的区别在于A'
有T
,mainline
的提示,作为其父提交。 (如果您使用交互式rebase,它还有您需要做的任何其他更改。)
将A
复制到A'
后,git rebase
会继续复制B
,然后C
和D
。最终,结果是:
A'-B'-C'-D' <-- temporary (HEAD)
/
...--o--o--T <-- mainline
\
A--B--C--D <-- branch
现在所有提交都已复制,git rebase
“剥离”旧分支标签branch
并移动它以替换临时分支名称:
A'-B'-C'-D' <-- branch (HEAD)
/
...--o--o--T <-- mainline
\
A--B--C--D [abandoned]
您传递给git rebase
的参数是您希望副本执行的提交的名称。在这种情况下,名称mainline
名称提交T
,因此副本会追溯到T
。
既然您已经知道这一点,并且注意到HEAD~5
意味着“从HEAD算上五步”,我们可以解释您的问题:
git rebase -i HEAD~5
[失败]
假设您要复制的链中只有 五个提交:
A--B--C--D--E <-- master
其中A
没有父提交,即 root 提交。 HEAD
名称提交E
。 HEAD~1
个名称D
,HEAD~2
个名称C
,依此类推。什么提交是HEAD~5
?
A
之前没有提交。 git rebase
通常用于在某些现有提交之后复制提交,但如果您想复制A
本身,您将如何命名提交A
之前的提交复制应该继续,让rebase
从提交A
开始复制?
这是--root
的来源:git rebase --root
允许您复制A
本身。 Git使用了许多特殊技巧来做到这一点,最终结果是一个独立的副本链:
A--B--C--D--E [abandoned]
A'-B'-C'-D'-E' <-- master
当我到达rebase交互式shell时,我使用
r
标志尝试了reword选项并提供了更新的消息。当我尝试保存并退出时,它启动了另一个终端来传递提交消息。
所有reword
或r
都会修改复制过程:Git仍会将提交一次一个地复制到新的提交中,但是当它转到“reword”的副本时“提交,它会触发git commit --edit
而不是git commit --no-edit
。这会在原始提交消息上显示您的编辑器,您现在可以重新编写该消息。
您最初编辑的说明书不允许您更改整个提交消息,因为提交消息(或应该)不仅仅是一行。因此,除了从pick
更改命令之外,它最终完全忽略您所做的任何其他更改。
新的编辑器会话仅适用于一个特定的提交。
(更确切地说,命令pick <hash>
字面意思是对给定的哈希值运行git cherry-pick
。哈希ID必须是有效的。如果你在说明书中重新排列这些行,你会重新安排交互式rebase运行的git cherry-pick
命令的顺序。如果你删除或注释掉一行,Git绝不会挑选那个特定的提交。使用reword
代替pick
只是cherry-pick提交交互式,而不是完全自动化。)