🐱
Gitのコミット等は通常簡単には消えない
Gitのcommit等のオブジェクトはgit reset
では消えずgit stash
もcommitオブジェクトを作成します。そうなるとdangling commitやdropされたはずのstash等の不要と思われるオブジェクトの実体はいつ消されるのかを調べた備忘です。明確になっていない部分があるため理解が間違っている可能性があります。
結論
最低でも90日間、通常はそれ以上の相当の期間自動では消えない。
それほど履歴保持能力が高くバージョン管理システムとして堅牢な設計になっている。
すぐに消したい時
- ローカルリポジトリの場合
# 到達不能なreflogエントリーを削除 git reflog expire --expire-unreachable=now --all # 到達不能なオブジェクトを削除 (今よりも古い=全到達不能オブジェクト) git gc --prune=now
- 到達可能な特定のファイルを削除する場合
-
git reset
等で到達不能にしてから上記コマンド実行 - 作業ツリー,ローカルリポジトリを全削除して
git clone
-
- 到達可能な特定のファイルを削除する場合
- リモートリポジトリの場合
- サーバーでgitコマンド実行可能
git gc --prune=now
- サーバーでgitコマンド実行不能
- サーバーでgitコマンド実行可能
GitのGabage Collection概要
- 到達不能なオブジェクトの掃除コマンドとして
git gc
が存在する-
git fetch
やgit merge
等を実行した時に自動でgit gc --auto
が実行される -
git gc --auto
には実際に掃除するかの判断基準があり基準を超えない限り削除されない - デフォルト基準は約7000以上のオブジェクトファイル又は50以上のpackファイルの存在
- 小規模なレポジトリでは絶対に自動では削除されない
- packファイルはオブジェクトファイルを纏めたアーカイブファイルのようなもの
-
git gc --auto
の判断基準を超えた場合、同時にreflogやrerere等の削除も実行される
-
- 自身で作成したcommitオブジェクトはreflog(操作履歴のようなもの)から参照されている
- dangling commitだとしてもreflogエントリーが消えない限り到達可能とみなされ消えない
- これはcommitオブジェクトとして実装されているstashも同様
- デフォルトでreflogの有効期間は90日のためその期間は消えない
- 失効しても
git gc --auto
の基準を超えない限り自動削除されずreflogも残り続ける
- ローカルとリモートの整合性を保つためオブジェクトが十分古くならない限り削除されない
- 以下のようなケースでレポジトリが壊れる
- リモート側で到達不能なオブジェクトを削除
- ローカルから1.で削除したオブジェクトを参照するcommitオブジェクトがpushされる
- リモート側でそのcommitオブジェクトがnull参照のような状態となり壊れる
- 上記のような破壊を防ぐために古い,新しいというような有効期間で管理されている
- blobオブジェクトが古くても新しいtreeオブジェクトから参照されれば削除対象にならない
- treeオブジェクトが古くても新しいcommitオブジェクトから参照されれば削除対象にならない
- 以下のようなケースでレポジトリが壊れる
-
git push --force
ではリモートリポジトリに存在したcommitオブジェクトは消えない- 元々存在したcommitオブジェクトはdangling commitとして残る
- 削除するためにはリモート側で到達不能なオブジェクトの削除処理が必要
- GitHubでは定期的に
git gc
が実行されている...らしいが詳細不明
-
git push
,git pull
でreflogは同期されない- 他リポジトリで作成されたdangling commitは
git gc --prune=now
のみで消える
- 他リポジトリで作成されたdangling commitは
- 認証情報などgitで管理すべきでない情報は構造的にgitに追加されないような運用設計が重要
参考文献
- git-gc
- git-reflog
- git push --forceで履歴は消えないと言う話
- GitHub上のsensitive dataを削除するための手順と道のり
- Gitにコミットした内容を完全に削除する
- GitのDangling Commitをすべて削除する方法
- Listing and deleting Git commits that are under no branch (dangling?)
- “git prune”コマンドが何をしてくれるものなのかを操作しながら理解する
- Scaling Git’s garbage collection
- git gcの自動実行はいつ行われるのか
- Git のガベージコレクションについて
- git gc --aggressive するそのまえに
Discussion