を使用して、履歴から多数の大きなファイルを削除しようとしていますfilter-branch
。以前にこのコマンドを使用して成功したことがありますが、現在、特定のエッジ ケースで問題が発生しています。
問題は、これらの大きなファイルが実際には削除されず、同じパスを持つ小さなバージョンに置き換えられたことです。
私が知る限り、私には独特の問題があると思います。
Git ログ
詳しく説明すると、私のレポの基本的な表現は次のとおりです。
----- A ------ B ----------- HEAD
どこ:
A is the commit where the large files were introduced
B is the commit (about 30 later) where the large files were replaced with smaller ones
HEAD is thousands of commits forward of B (~2 years of active development)
Git フィルターブランチ
理論的には、次のようなことができるはずです。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filenames' <parent of A>..B
包括的ではない<parent of A>
ため、使用する必要があると思います。filter-branch
(Bの親も使用する必要があるかどうかはわかりませんが、これは今のところ私の心配の中で最も少ないです)。
これを実行すると、次のエラーが表示されます。
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch filenames' <parent of A>..B
Which ref do you want to rewrite?
だから私--glob="refs/heads/master*"
はトリックを行うように見えるコマンドの最後に含めました(source)。
実行が完了すると、ファイルは完全に削除されました - git は私が指定した上限を無視しているようです。
それで、この方法が可能かどうか疑問に思っていますか?
代替アプローチ
潜在的な答えが問題の解決に集中できるように、私が持っていた他のいくつかのアイデアをリストする必要があると思いました.
- 実用的なアプローチは、ファイル名の変更を HEAD でコミットしてから実行すること
git filter-branch ... HEAD
です。ただし、私のリポジトリには活発な開発中のブランチが多数あり、この方法は非常に面倒だと思います。 - もう 1 つの方法は、ここで説明されているようなことを行うことです。引用するには:
create a temporary branch to point at HEAD^, filter-branch it, then add a graft to stitch the remaining commit on top of it, then filter-branch HEAD and then remove the graft.
誰かが以前にこの問題に遭遇し、専門知識を貸してくれることを願っています。
アップデート
削除したいファイルの合計は500MBに達するので、当然のことながら削除したいと思っています。これらは、私が入社するずっと前にコミットされたもので、社内の Mercurial サーバーから GitHub への移行の名残です (500MB を社内サーバーにプッシュすることは、GitHub よりも目立たないと思います...)。
更新 2
私はtwalbergの2番目の回答に従っています(正しい方法で使用していると思います):
git filter-branch --index-filter '(( $(git rev-list <SHA-of-child-of-B> --not $GIT_COMMIT | wc -l) > 0 )) && git rm --cached --ignore-unmatch <filenames>'
これにより、私が期待するような出力が生成されます。
...
Rewrite dc8a4b29463bfa43c2f3efe0c6e5a29a5cc6e0ef (1071/5680)rm 'file1'
rm 'file2'
rm 'file3'
rm 'file4'
...
(予期された?) エラーで終了する前に:
Rewrite e6b712b57257e2edd0bb9fbbac59e4c9d7b5aa79 (1072/5680)index filter failed: (( $(git rev-list e6b712b --not $GIT_COMMIT | wc -l) > 0 )) && git rm -rf --ignore-unmatch <filename>
e6b712b
の子はどこですかB
。
この時点で、すべてが機能していると思いますので、リポジトリのローカル ファイルシステム クローンを作成してテストします。
git clone file://<repo> <new repo>
オブジェクトの数とパックファイルのサイズがごくわずかに減少しました。理由はわかりません。git count-objects -v
元のリポジトリとそれに対して実行されたリポジトリに対して実行することにより、次のfilter-branch
ようになります。
元のリポジトリ:
count: 0
size: 0
in-pack: 106640
packs: 1
size-pack: 815512
prune-packable: 0
garbage: 0
filter-branch
ed およびファイルシステムの複製されたリポジトリ:
count: 0
size: 0
in-pack: 96165
packs: 1
size-pack: 793656
prune-packable: 0
garbage: 0
なぜこれがまだうまくいかないのか本当にわかりません - おそらく私は提案された答えに正しく従っていませんか?