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

その最後の非行には、実行する前に HEADだっrebaseたコミットの SHA1 があります。技術的には必須ではありませんが、この時点で一時的なブランチまたはタグ ラベルを貼り付けることができます。ここでは、次の名前の軽量タグを付けます。rebase -itemp

git tag temp 283263c

これで、単に , or を実行できますgit log temp(リベースしたものだけに制限するため):

git log temp --not HEAD

また:

git log temp ^HEAD

(これらは同じものを綴る 2 つの方法です) 1、または:

git log -n 20 temp

(これは、リベースされた に 20 個のコミットがあるという事実を使用していますHEAD~20..HEAD。これは、元の履歴が線形であり、もちろんその部分に依存する場合にのみ当てはまります~20)。

一時的なラベルの処理が完了したら、それを削除します。

git tag -d temp

これが機能する方法は、rebase -i実際にはコミットを削除 せず、新しいコミットのみを追加 することです。(これは実際、ほぼすべての git コマンドに当てはまります。例外は、参照されていないオブジェクトを削除するガベージ コレクション プロセスです。)

リベースの「commit-and-branch」引数の完全なセット (つまり、-i-pフラグなどの重要なものは無視) は、 start-pointdestination、およびbranch-nameです。ドキュメントでは、これらのうち最初の 2 つを "upstream" と "onto" として巧妙に偽装しています (真剣に言うと、"onto" は悪い名前ではありません。start-pointの後からbranchの先端までのすべてのコミットは、本質的に、一度に 1 つずつチェリー ピックすることによって、新しいコミットが成長したブランチに追加されるので、コピーされます (または省略されるか、押しつぶされます)。目的地。元のコミット ツリーが (部分的に) 次のようになっている場合:

old -- start-point -- c2 -- c3 -- c4   <-- branch
    \
      onto -- c6 -- c7                 <-- another-branch

次に、リベースは、コピー (または「からの変更の再生」) (開始点の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-pointc2c3、およびc4) はすべて残っていることに注意してください。ブランチ ラベルがなくなっただけです。また、この特定のケース (--ontoこの特定のコミット ツリーで示されているように引数を使用) では、コミットという名前のコミット自体が「非表示」になることにも注意してください ( throughstart-pointと同じ意味で)。もちろん、リベースを実行する前または後に設定しない限り。(通常、そのような「スキップされた」コミットはありません。もちろん、インタラクティブなリベースでは、一部をスキップさせることができますが、そうするつもりだったことは明らかです。)c2c4

ラベルのない (「見えない」または「隠された」) コミットは、reflog に残っている限り (デフォルト設定を変更しない限り 90 日間) 残ります。それらをさらに長く定着させるには、ブランチ名やタグ名などのラベルを設定して、それらを指すようにします。それが私がtemp上記のタグで行うことです。gitkこれらは再び表示されるようになり、やなどのコミット ツリー ビューアーで簡単に確認できるようになりましたgit log

(インタラクティブなリベースに複数のコミットを「押しつぶす」ように依頼すると、変更が 1 つのコミットにまとめられます。新しいコミットはそれぞれコピー (いわば「リプレイ」) であるため、さらに多くの変更をスタックし続けるのは簡単です。一緒に、それらすべてを 1 つの squash-commit としてコミットします。コミットを省略すると、それをスキップして、残りのコミットのみをコピーします。コミットの順序を変更すると、新しい順序でそれらをコピーします。)


1綴り方は他にもたくさんあります。実際、どうやら間違っgit log HEAD..tempているように見えますが、うまくいきます。:-) これらのバージョンはすべて、リベースを行ったブランチの名前のままであると想定しています。ブランチにいた場合は、たとえば、一度は別の場所に移動しました。HEADsquigglegit log temp ^squiggleHEAD

于 2013-09-18T08:41:39.463 に答える