1

たとえば、10 個のコミットを含むローカル git リポジトリがあり、SHA ダイジェストが 0 ~ 9 であるため、git ログは次のようになります。

9 (HEAD -> master)
8
7
6
5
4
3
2
1
0 <- initial commit

コミット 5 ~ 9 はガベージであると判断し、それらのすべてのレコードをレポジトリとそれらが導入したディスク領域から完全に削除したいと考えています。基本的に、リポジトリの状態をコミット 4 が作成されたときと同じにして、5-9 が発生したことさえないようにしたいと考えています。

git reset --hard 4私のレポがコミット4に巻き戻されたように見えることはわかっていますが、私が理解していることから、コミットmasterポイントを9から4に変更するだけで、実際には何も削除しません. すべてのデータはまだそこにあり、コミット 9 の SHA がわかっている場合は回復可能です。

私も認識してgit filter-branchいますが、それはコミットではなく、履歴からファイルを削除するだけです。

私はやってみました:

git reset --hard 4
git gc --prune=now

.gitしかし、これを行った後、ディレクトリのディスク容量の使用量は同じかそれ以上になり、 git checkout 9. git gc --prune=nowコミット 5 ~ 9 をプルーニングしないのはなぜですか? 期限切れにする必要がありreflogますか?

より一般的に:

多くのブランチ、タグ、コミット、マージ、および分岐履歴を含む複雑なリポジトリがある場合、すべてのコミットを、それらが導入する変更、およびそれらが消費するディスク容量とともに、一定時間後に発生したものを完全かつ自動的に削除するにはどうすればよいですか。リポジトリ全体をその時点まで効果的に巻き戻し、その日付以降に発生したすべてのアクティビティを完全に破棄します。

4

2 に答える 2

0

これを部分的に見てみましょう...

git reset --hard 4私のレポがコミット4に巻き戻されたように見えることはわかっていますが、私が理解していることから、コミットmasterポイントを9から4に変更するだけで、実際には何も削除しません。すべてのデータはまだそこにあり、コミット 9 の SHA がわかっている場合は回復可能です。

正解です。さらに、コミット 5、6、7、8、および 9 へのポインターを保持できる reflog が2つありHEADます。それらのコミットに (それらを指していた場合— それが .何らかの方法で、たとえば別のブランチから一度にそれらを持ち込んだ)。HEADHEADmastermastermaster9reset

これらのコミットを指す追加のブランチや reflog がある場合とない場合があります。

私も認識してgit filter-branchいますが、それはコミットではなく、履歴からファイルを削除するだけです。

Wolfgang Pauli が別のことについて言ったように、これは正しくありません。git filter-branch特に、この言い回しは が物を取り除くことを暗示しています。そうではありません:新しいコミットを追加します。

Git は基本的に、新しいものを追加し、何も削除しないという考えに基づいて構築されています。これにはgit commit --amendgit rebase、およびが含まれます:新しいコミットgit filter-branchを追加します。期限切れのものを実際に削除する唯一の Git コマンドは、gc 関連のもの ( 、、、など、そしてもちろんそれ自体) です。git prunegit reflog expiregit repackgit prune-packedgit gc

私はやってみました:

git reset --hard 4
git gc --prune=now

.gitしかし、これを行った後、ディレクトリのディスク容量の使用量は同じかそれ以上になり、 git checkout 9. git gc --prune=nowコミット 5 ~ 9 をプルーニングしないのはなぜですか? reflog を期限切れにする必要がありますか?

はい。

古いオブジェクトを削除するには、次のことを行う必要があります。

  • reflog 内のものを含む、すべての参照を探し出して破棄する
  • 年齢に関係なく緩いオブジェクトを剪定する (--prune=now上記の部分)
  • それらのオブジェクトのパックされたバージョンを再パックします。

git gc --prune=nowは最後の 2 つのステップを処理しますが、最初のステップは処理しません。を使用git reflog --expire=now --expire-unreachable=nowすると、すべての reflog が消去されます (これはやり過ぎです:--expire-unreachableおそらくこれで十分です)。他の迷子の参照 (他のブランチ、タグ、緩いstash1 つまたは 2 つ、場合によってはORIG_HEADや などCHERRY_PICK_HEAD) がある場合は、それらを手動でクリーンアップする必要があります。git filter-branchまた、参照の元のセットが に残り、.git/refs/original/それらがすべての元の (事前にフィルター処理されたコピー) オブジェクトを保持していることにも注意してください。

于 2016-05-27T15:21:55.633 に答える