git filter-branch について勉強したメモ。最強なだけあって奥が深い...
git filter-branch について
最強のオプション: filter-branch
- 大量のコミットの書き換えを機械的に行いたい場合に使う
- 少量のコミットの書き換えをを対話的に行う場合は git rebase -iが便利!
注意事項
- プロジェクトを一般に公開した後や書き換え対象のコミットを元にしてだれかが作業を始めている場合は使うのを避けたほうがよい
- どうしても必要な場合は、すべての関係者に知らせてそれぞれのローカルリポジトリに対しても変更を反映してもらう必要がある
コマンド例
プロジェクトの各チェックアウトに対して指定したコマンドを実行し、結果を再コミットします。
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
↑この場合は、すべてのスナップショットから passwords.txt というファイルを削除します。
git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch passwords.txt' HEAD
↑ワークツリーにファイルを残したい場合はこんな感じ。
オプションについて
- --tree-filter
- 各チェックアウトに対してコマンドを実行し、結果を再コミットする
- --index-filter
- インデックスを書き換える
- ツリーをチェックアウトせずインデックスを書き換えるので、--tree-filterよりはるかに高速
余談:「スナップショット」とは...?
Gitは内部構造的に、「差分」を集積しているのではなく、「スナップショット」を保存している。
なので、コミットする=変更後のスナップショットを保存するということなのです!
参考
http://git-scm.com/book/ja/v1/Git-のさまざまなツール-歴史の書き換え#最強のオプション:-filter-branch
http://git-scm.com/book/ja/v1/Gitの内側-メインテナンスとデータリカバリ#オブジェクトの除去