2

私のリポジトリはオープン ソース プロジェクトからフォークされているため、ForkPoint タグの前のコミットを変更したくありません。BFG Repo Cleanerを試しましたが、範囲を指定できません。

したい

  1. で歴史をたどるForkPoint..HEAD^
  2. コミットを書き直して、10M を超えるすべてのファイルを削除します

未使用のオブジェクトを git リポジトリから削除するには? それはこのようなものであるべきだと言います

BADFILES=$(find . -type f -size +10M -exec echo -n "'{}' " \;)
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $BADFILES" ForkPoint..HEAD^

BADFILESしかし、に存在するファイルだけが含まれるわけではありませんHEADか?

たとえば、誤って をコミットしHUGE_FILE、後でそのファイルを削除する別のコミットを行った場合、現在の作業ツリーに表示されないため、検索では が見つかりませんBADFILESHUGE_FILEfind


Edit1: 現在、クローンで BFG を使用してから、フォークを元の ForkPoint に移動することを検討しています。fatRepoと与えられた場合、これは正しいコマンドslimRepoでしょうか?

mkdir merger ; cd merger ; git init
git remote add fat  ../fatRepo
git remote add slim ../slimRepo
git fetch --all
git checkout fat/ForkPoint
git cherry-pick slim/ForkPoint..slim/branchHead

Edit2:チェリーピッキングはslimRepoでマージを処理できないため、チェリーピッキングは機能しませんでした。どうにかしてslimRepoの歴史をつぶして、単純にfatRepo/ForkPointにマージすることはできますか?

git <turn into a single commit> slim/rootNode..slim/ForkPoint
git checkout fat/ForkPoint
git merge slim/branchHead
4

1 に答える 1

1

はい。それで合っています。

事前にファイルを特定できる場合は、手動で一覧表示してください。

各コミットから大きなファイルを選択する必要がある場合は、次のことができます。

  • (上記の例に示すように)index-filterを使用しますが、大きなファイルをチェックする$GIT_COMMIT、または
  • ツリーフィルターを使用して、大きなファイルを単純に削除します

(またはもちろん、あなたが思いつくことができる他のもの)。

index-filter は、あなた (および git) が、フィルター処理される各コミットを作業ツリーに変換する、またはその逆の面倒な作業をスキップできるため、はるかに高速です。ただし、コピーするコミットがほとんどない場合は、時間と精神的な労力を何かに費やすことになり、全体的に見返りは小さくなります。このようにしたい場合は$GIT_COMMIT、発生時に利用可能な変数から抽出するために十分な引用符が必要であることに注意してevalください (たとえば、以下のスクリプト トリックを参照してください。これは環境に置かれているためです)。

ツリーフィルターは簡単に使用できます。この場合、git は元のコミットをクリーンで空のサブディレクトリ (デフォルトでは.git、リポジトリを含むディレクトリ内に作成されたサブディレクトリですが、-d引数を参照してください) に抽出し、 filter (そのサブディレクトリ内)。その後に残っているファイルはすべて、他のフィルターがあればそれも適用された新しいコミットに入れられます (ドキュメントに記載されている順序で)。したがって、ツリーフィルターは次のようになります。

find . -type f -size +10M -exec rm '{}' ';'

文字列は に渡されるevalため、いくつかのレベルの引用符を使用する必要があることに注意してください。または、単純にフル パス名で実行することもできます。スクリプトを などのファイルに入れ、/tmp/cleanup.sh実行可能にして、次を使用します。

git filter-branch --tree-filter /tmp/cleanup.sh ForkPoint..HEAD^

ツリーフィルターは遅くなりますが、特に範囲にほんの一握りのコミットしか含まれていない場合は、それほど気にしないかもしれません.


編集: 特定のコミット (または他のツリー) で大きなファイルを見つけるには、そのコミットに保存されているツリーを調べます (これは、インデックス フィルターで必要になるものです)。この script-ette を使用できます (軽くテストされています)。

git ls-tree -lr $ref |
while read mode type hash size path; do
    [ $size -gt $limit ] && echo $size $path
done

$ref($GIT_COMMITインデックス フィルターの) と に適切な値を選択します$limitechoコマンドをに変更git rm --cached -- $pathして、フィルターでそれらを削除します。--ignore-unmatch(見つかったパスは、そのコミットのツリーを調べることで見つかるため、必要ありません。)

git rev-list最初に一連の参照を準備するために使用することで、これが何をするかを確認できます。

git rev-list ForkPoint..HEAD^ | /tmp/script

/tmp/script の場所:

check_tree() {
    git ls-tree -lr $1 |
    while read mode type hash size path; do
        [ $size -gt $limit ] && echo $size $path
    done
}

limit=1000000 # or whatever number

while read rev; do
    check_tree $rev
done

次に、目的のサイズ制限値を見つけたら、わずかに変更したスクリプト (上記のように) を実際のインデックス フィルターとして使用します。

于 2014-07-29T06:02:40.313 に答える