19

免責事項:この質問は純粋に情報提供であり、私が経験している実際の問題を表すものではありません。私はそれのために何かを理解しようとしているだけです(私は何かを理解するのが大好きで、あなたもそうしていることを知っているからです)。

だから私はgitで遊んでいて、修正されたコミットを期限切れにしようとしていました。私のreflogは次のようになります。

4eea1cd HEAD@{0}: commit (amend): amend commit
ff576c1 HEAD@{1}: commit: test: bar
5a1e68a HEAD@{2}: commit: test: foo
da8534a HEAD@{3}: commit (initial): initial commit

つまり、2つのコミット(da8534a5a1e68a)を作成し、次に3番目のコミットを。ff576c1で修正しまし4eea1cdた。

予想通り、私のgit log見た目は次のようになります。

* 4eea1cd (HEAD, master) amend commit
* 5a1e68a test: foo
* da8534a initial commit

私が(私は)コミットの有効期限について知っていることから、いつか(ほとんどの場合、デフォルトで30日以内に)git gc収集する必要がありff576c1ます。今、私はそれが起こるのを見るのに30日待ちたくないので、最初にいくつかのコマンドを実行し始めます:

git fsck --unreachable --no-reflogs

これは、再び予想されるように、私に与えます:

unreachable blob 5716ca5987cbf97d6bb54920bea6adde242d87e6
unreachable tree 1e60e555e3500075d00085e4c1720030e077b6c8
unreachable commit ff576c1b4b6df57ba1c20afabd718c93dacf2fc6

ff576c1私がその貧しい孤独なコミットを期限切れにするだろうとすべての自信を持って、私はそれから実行しますgit reflog expire

git reflog expire --dry-run --expire-unreachable=now --all

その時、私に与えます:

would prune commit: test: bar
would prune commit (amend): amend commit

最初HEADは参照していませんでしたが、前に示しmasterた出力からわかるgit logように、実際には参照しています。また、それをcat .git/HEAD確認します(yelding ref: refs/heads/master)。とにかく、それでもばかげていたのですが4eea1cd、私のmaster支部長です。

ですから、ここで私は、これら2つのコマンドが同じコミットを与えないことをすべて混乱させており、それが私のブランチ4eea1cdの実際の先端であるため、どうして地獄に到達できない可能性があるのか​​疑問に思っています。master

何が起こっているのかについて何か考えはありますか?

編集--rewrite:オプションをに追加するとgit reflog expire、次のようになります。

git reflog expire --dry-run --expire-unreachable=now --all --rewrite

次に、修正されたコミットのみを取得します。

would prune commit: test: bar

によると、私はまだ理解していませんgit help reflog

   --rewrite
       While expiring or deleting, adjust each reflog entry to ensure that
       the old sha1 field points to the new sha1 field of the previous
       entry.

私の場合、これは意味がありません。明らかにそれは何かを変えるので、少なくとも私はそれを理解していません。

4

1 に答える 1

12

この動作は、reflogの設計哲学とガベージコレクションの要件の間の相互作用に起因します。

ガベージコレクターによってコミットを安全に削除するには、reflogエントリ内の参照を含め、そのコミットへのすべての参照を削除する必要があります。の外観にもかかわらずreflog show、各reflogエントリには、実際には2つのSHA1識別子が含まれています。変更前のrefの値と、変更後のrefの値です。安全なガベージコレクションを確保するreflog expireには、2つのSHA1のいずれかが到達不能なコミットを識別するエントリを削除するだけです。

あなたの場合、最新のreflogエントリの変更前の値は、到達不能なコミットを参照しています。変更後の値で識別されるコミットは引き続き到達可能ですreflog expireが、エントリを削除します。

この設計は実装が簡単で、不完全ですが正確なログになります。

--rewriteオプション_

残念ながら、まだ到達可能なコミットを参照するエントリを削除するには、いくつかの問題があります。

  • ログにギャップが残っています
  • まだ到達可能なコミットに関連する有用な情報が失われます

この--rewriteオプションは、次の方法で動作を変更することにより、これらの問題に対処します。

  • 以前と同様に、変更後のSHA1によって識別されたコミットに到達できないエントリは削除されます。
  • 変更前のコミットに到達できないエントリは、削除されたエントリによって残されたギャップを埋めるために変更されます(変更前のSHA1は、前のエントリの変更後のSHA1の値に設定されます)。

残念ながら、エントリを変更すると、参照の履歴を正確に反映しなくなったログが作成されます。たとえば、変更の理由は、書き換え後に意味をなさなくなる可能性があります。これがデフォルトではない理由--rewriteです。

于 2012-02-11T00:19:49.293 に答える