git - 列出压缩的提交

标签 git git-rebase git-reflog

在我进行交互式 rebase 之后: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 之前的 HEAD .此时您可能希望在其上粘贴一个临时分支或标记标签,尽管这在技术上不是必需的。在这里,我将放置一个名为 temp 的轻量级标签在上面:
git tag temp 283263c

现在你可以简单地运行 git log temp , 或(将其限制为您重新定位的那些):
git log temp --not HEAD

或者:
git log temp ^HEAD

(这是拼写同一事物的两种方式)1,或者:
git log -n 20 temp

(这使用了重新调整后的 HEAD~20..HEAD 中有 20 个提交的事实,这仅在原始历史是线性的情况下才成立,当然这取决于 ~20 部分)。

完成临时标签后,将其删除:
git tag -d temp

这种工作方式是 rebase -i实际上并没有删除 任何 提交,它只会添加 新品 提交。 (实际上几乎每个 git 命令都是如此。垃圾收集过程除外,它删除未引用的对象。)

一套完整的 rebase “提交和分支”参数(即忽略重要的东西,如 -i-p 标志)是:起点、目的地和分支名称。该文档巧妙地将 :-) 前两个伪装为“上游”和“onto”(说真的,“onto”不是一个坏名字,我将在下面坚持使用,但“上游”在某些情况下会产生误导)。起点之后的所有提交,直到分支的尖端,都被复制(或省略或压缩或其他什么),基本上,一次一个地挑选它们,作为一个新的提交添加到一个增长的分支上目的地。如果原始提交树看起来(部分)是这样的:
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'的 parent 是 c2' , 等等。全部完成后,它会从 branch 上剥下标签 ( c4 ) ,并将其粘贴到指向最后一个新提交 ( c4' ) 上:
old -- start-point -- c2 -- c3 -- c4   <-- [no label]
    \
      onto -- c6 -- c7                 <-- another-branch
        \
          c2' -- c3' -- c4'            <-- branch

请注意,旧的提交( start-pointc2c3c4 )仍然存在,只是不再有分支标签。还要注意,在这种特殊情况下(使用所示的 --onto 参数,使用这个特定的提交树),提交名为 start-point本身变得“不可见”(与 c2c4 的意义相同),因为它不再有任何指向它的分支或标签标签——当然,除非你在执行 rebase 之前或之后设置了一个。 (通常没有这样的“跳过”提交。当然,在交互式 rebase 中,你可以让它跳过一些,但很明显你打算这样做。)

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

(如果您要求交互式 rebase “压缩”多个提交,它只是将更改 merge 为一个提交。由于每个新提交都是一个副本 - 就像“重放”一样 - 很容易继续堆叠更多更改一起,将它们全部提交为一个压缩提交。如果您省略提交,它只会跳过它,只复制剩余的提交。如果您重新排序提交,它只会以新的顺序复制它们。)

1 还有很多拼写方法。事实上,git log HEAD..temp以某种方式,即使看起来不对,也能解决问题。 :-) 这些版本都假设 HEAD仍然是您进行 rebase 的分支的名称。如果您在分行 squiggle你可以用 git log temp ^squiggle , 一次 HEAD例如,已经搬到别处。

关于git - 列出压缩的提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18865842/

相关文章:

git - 需要一个git命令,它只给我的源分支(工作分支)更改

git - 如何检索 Git 中具有特定扩展名的所有文件的最后修改日期?

git - 索引有reflog吗?

Git reflog 一个特定的分支?

git - 在 Windows 上 checkout HEAD(和变体)时奇怪的 Git 行为

git - 我可以用 git 做一个目录列表,显示最新的提交日期吗

svn - 一个开发者值得从 SVN 转到 Git 吗?

git - 如何只保留 git rebase 中的头部更改

Git 从一个分支 rebase 到另一个分支

git - 如果它是分支中唯一的提交,我该如何删除第一个也是唯一的提交?