5

在我做交互式变基之后:git rebase -i HEAD~20我得到一个新的提交,例如 ea1234ea

我知道历史记录在 reflog 中,但是如何获取在此提交中压缩的提交列表,包括它们的标识符(sha)

git show ea1234ea将显示一个提交消息,其中列出了被压扁的消息,但没有标识符。

4

1 回答 1

3

开始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-pointdestinationbranch-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-pointc2c3c4)都还在,只是不再有分支标签。另请注意,在这种特殊情况下(使用--onto所示的参数,使用此特定的提交树),名为自身的提交变得“不可见”(与throughstart-point具有相同的意义),因为它不再有任何分支或标签标签指向它——当然,除非你在 rebase 之前或之后设置了一个。(通常没有这样的“跳过”提交。当然,在交互式 rebase 中,你可以让它跳过一些,但很明显你打算这样做。)c2c4

未标记(“不可见”或“隐藏”)的提交只要保留在 reflog 中就会一直存在(90 天,除非您更改默认设置)。要使它们停留更长时间,请设置一个标签(例如分支或标签名称)以指向它们。这就是我对temp上面的标签所做的。现在它们再次可见,并且很容易在任何提交树查看器中看到,例如gitkor git log

(如果您要求交互式变基“压缩”多个提交,它只是将更改合并到一个提交中。由于每个新提交都是一个副本——实际上是一个“重放”——很容易保持堆叠更多更改一起,将它们全部作为一个 squashed-commit 提交。如果你省略了一个提交,它只会跳过它,只复制剩余的提交。如果你重新排序提交,它只会以新的顺序复制它们。)


1还有很多拼写方式。事实上,git log HEAD..temp即使看起来错了,它也能以某种方式解决问题。:-) 这些版本都假定它HEAD仍然是您进行变基的分支的名称。例如,如果您在分支上,则squiggle可以使用git log temp ^squiggle,一旦HEAD移动到其他地方。

于 2013-09-18T08:41:39.463 回答