在我做交互式变基之后:git rebase -i HEAD~20
我得到一个新的提交,例如 ea1234ea
我知道历史记录在 reflog 中,但是如何获取在此提交中压缩的提交列表,包括它们的标识符(sha)?
git show ea1234ea
将显示一个提交消息,其中列出了被压扁的消息,但没有标识符。
在我做交互式变基之后:git rebase -i HEAD~20
我得到一个新的提交,例如 ea1234ea
我知道历史记录在 reflog 中,但是如何获取在此提交中压缩的提交列表,包括它们的标识符(sha)?
git show ea1234ea
将显示一个提交消息,其中列出了被压扁的消息,但没有标识符。
开始git reflog
。输出看起来像这样(但有更多rebase -i
条目):
aa4e140 HEAD@{0}: rebase -i (finish): returning to refs/heads/branch
aa4e140 HEAD@{1}: rebase -i (squash): c1-c3, squashed
3a422a7 HEAD@{2}: rebase -i (squash): # This is a combination of 2 commits.
f7cac12 HEAD@{3}: rebase -i (start): checkout HEAD~3
283263c HEAD@{4}: commit: blah yadda etc, but not a rebase
最后rebase
一行的 SHA1在您执行rebase -i
. 此时您可能希望在其上粘贴一个临时分支或标签标签,尽管这在技术上不是必需的。在这里,我将temp
在其上放置一个轻量级标签:
git tag temp 283263c
现在您可以简单地运行git log temp
,或者(将其限制为您重新设置的那些):
git log temp --not HEAD
或者:
git log temp ^HEAD
(这是拼写相同事物的两种方式)1,或:
git log -n 20 temp
(这使用了 rebased 中有 20 次提交的事实HEAD~20..HEAD
,这仅在原始历史是线性的情况下才成立,当然取决于那~20
部分)。
完成临时标签后,将其删除:
git tag -d temp
它的工作方式是rebase -i
实际上并没有删除 任何提交,它只添加 新的提交。(实际上几乎每个 git 命令都是如此。垃圾收集过程是个例外,它会删除未引用的对象。)
完整的变基“commit-and-branch”参数集(即忽略重要的东西,如-i
和-p
标志)是:start-point、destination和branch-name。文档巧妙地伪装 :-) 其中前两个为“upstream”和“onto”(说真的,“onto”不是一个坏名字,我会在下面坚持使用它,但“upstream”在某些情况下具有误导性)。start-point之后的所有提交,直到branch的尖端,都被复制(或省略或压扁或其他),本质上,一次一个地挑选它们,作为添加到生长在的分支上的新提交目的地。如果原始提交树(部分)看起来像这样:
old -- start-point -- c2 -- c3 -- c4 <-- branch
\
onto -- c6 -- c7 <-- another-branch
然后 rebase 通过复制(或“重播更改自”) (开始点之后c2
的第一次提交)开始复制到相同的更改(但具有不同的提交信息) ,将其放置为它的父级:c2'
onto
old -- start-point -- c2 -- c3 -- c4 <-- branch
\
onto -- c6 -- c7 <-- another-branch
\
c2'
然后它复制c3
到一个新的 ( c3'
) 版本,其中c3'
的父级是c2'
,依此类推。完成后,它将标签 ( branch
) 从 中剥离c4
,并将其粘贴到指向最后一个新提交 ( c4'
) 的位置:
old -- start-point -- c2 -- c3 -- c4 <-- [no label]
\
onto -- c6 -- c7 <-- another-branch
\
c2' -- c3' -- c4' <-- branch
请注意,旧的提交(start-point
、c2
、c3
和c4
)都还在,只是不再有分支标签。另请注意,在这种特殊情况下(使用--onto
所示的参数,使用此特定的提交树),名为自身的提交变得“不可见”(与throughstart-point
具有相同的意义),因为它不再有任何分支或标签标签指向它——当然,除非你在 rebase 之前或之后设置了一个。(通常没有这样的“跳过”提交。当然,在交互式 rebase 中,你可以让它跳过一些,但很明显你打算这样做。)c2
c4
未标记(“不可见”或“隐藏”)的提交只要保留在 reflog 中就会一直存在(90 天,除非您更改默认设置)。要使它们停留更长时间,请设置一个标签(例如分支或标签名称)以指向它们。这就是我对temp
上面的标签所做的。现在它们再次可见,并且很容易在任何提交树查看器中看到,例如gitk
or git log
。
(如果您要求交互式变基“压缩”多个提交,它只是将更改合并到一个提交中。由于每个新提交都是一个副本——实际上是一个“重放”——很容易保持堆叠更多更改一起,将它们全部作为一个 squashed-commit 提交。如果你省略了一个提交,它只会跳过它,只复制剩余的提交。如果你重新排序提交,它只会以新的顺序复制它们。)
1还有很多拼写方式。事实上,git log HEAD..temp
即使看起来错了,它也能以某种方式解决问题。:-) 这些版本都假定它HEAD
仍然是您进行变基的分支的名称。例如,如果您在分支上,则squiggle
可以使用git log temp ^squiggle
,一旦HEAD
移动到其他地方。