web-dev-qa-db-ja.com

gitリポジトリからファイルを削除(履歴)

(解決済み、質問本文の下部を参照)
これを長い間探していましたが、私が今まで持っているものは次のとおりです。

ほぼ同じ方法ですが、両方ともオブジェクトをパックファイルに残します...スタックします。
試したこと:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_name'
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc

パックにまだファイルがあり、これは私がそれを知っている方法です:

git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3

この:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch file_name" HEAD
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --Prune

同じ...

git cloneトリック、いくつかのファイル(〜3000個)を削除しましたが、最大のファイルがまだ残っています...

リポジトリにはいくつかの大きなレガシーファイルがあり、200Mまでありますが、本当にそこにはいりません...そして、リポジトリを0にリセットしたくないです:(

解決策:これは、ファイルを削除する最短の方法です。

  1. .git/packed-refsを確認してください-私の問題は、refs/remotes/Origin/master行。リモートリポジトリの場合は削除します。そうしないと、gitはこれらのファイルを削除しません。
  2. (オプション)git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5-最大のファイルを確認する
  3. (オプション)git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98-それらのファイルが何であるかを確認する
  4. git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names'-すべてのリビジョンからファイルを削除します
  5. rm -rf .git/refs/original/-gitのバックアップを削除します
  6. git reflog expire --all --expire='0 days'-すべてのルーズオブジェクトを期限切れにする
  7. git fsck --full --unreachable-緩いオブジェクトがあるかどうかを確認します
  8. git repack -A -d-再梱包
  9. git Prune-これらのオブジェクトを最終的に削除します
76
Boris Churzin

リポジトリデータにアクセスせずに確実に言うことはできませんが、おそらくgit filter-branchを実行する前からの古いコミットを参照している1つ以上のパックされた参照があると思います。これにより、reflogの有効期限が切れて元の(アンパックされた)refが削除されたにもかかわらず、git fsck --full --unreachableが大きなblobを到達不能オブジェクトと呼ばない理由が説明されます。

私がやることは次のとおりです(git filter-branchおよびgit gcが実行された後):

1)元の参照がなくなっていることを確認してください:

rm -rf .git/refs/original

2)すべてのreflogエントリを期限切れにします:

git reflog expire --all --expire='0 days'

)古いパックされた参照の確認

使用するパックrefの数によっては、これは難しい場合があります。これを自動化するGitコマンドは知らないので、手動でこれを行う必要があると思います。 .git/packed-refsのバックアップを作成します。次に.git/packed-refsを編集します。古い参照を確認します(特に、.git/refs/originalの参照をパックしているかどうかを確認します)。そこにある必要のない古いものを見つけたら、それらを削除します(その参照の行を削除します)。

packed-refsファイルのクリーンアップが完了したら、git fsckが到達不能オブジェクトに気付いたかどうかを確認します。

git fsck --full --unreachable

それが機能し、git fsckが大きなBLOBに到達不能として報告するようになったら、次のステップに進むことができます。

4)パックされたアーカイブを再パックします

git repack -A -d

これにより、到達不能オブジェクトがアンパックされ、stayアンパックされることが保証されます。

5)ルーズ(到達不能)オブジェクトのプルーニング

git Prune

そして、それはそれを行う必要があります。 Gitには、パックされた参照を管理するためのより良い方法が必要です。たぶん、私が知らないより良い方法があるでしょう。より良い方法がない場合、packed-refsファイルを手動で編集することが唯一の方法です。

64
Dan Moulding

BFG Repo-Cleaner を使用することをお勧めします。これは、Git履歴からファイルを書き換えるために特別に設計されたgit-filter-branchのよりシンプルで高速な代替手段です。ここであなたの生活を楽にする一つの方法は、デフォルトでall参照(すべてのタグ、ブランチ、refs/remotes/Origin/masterなど)を実際に処理することですが、それも 10-50x 速くなりました。

ここでこれらの手順を注意深く実行する必要があります: http://rtyley.github.com/bfg-repo-cleaner/#usage -しかし、コアビットはこれだけです: BFGのjar (Java 6以上が必要))で、次のコマンドを実行します。

$ Java -jar bfg.jar  --delete-files file_name  my-repo.git

file_namelatest commitにない)という名前のファイルは、リポジトリの履歴からtotally removedになります。その後、git gcを使用して、デッドデータを一掃できます。

$ git gc --Prune=now --aggressive

BFGは一般にgit-filter-branchよりもはるかに簡単に使用できます-オプションは次の2つの一般的なユースケースに合わせて調整されます。

  • 削除Crazy Big Files
  • パスワード、クレデンシャルおよびその他プライベートデータの削除

完全な開示:私はBFGリポジトリクリーナーの作成者です。

15
Roberto Tyley

上記は実際には役に立たなかったため、フォルダー全体を削除することに関してこれが非常に役立つことがわかりました: https://help.github.com/articles/remove-sensitive-data

私が使用した:

git filter-branch -f --force \
--index-filter 'git rm -rf --cached --ignore-unmatch folder/sub-folder' \
--Prune-empty --tag-name-filter cat -- --all

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --Prune=now
git gc --aggressive --Prune=now
6
Mike Averto

私は歴史の中で大きなファイルを取り除こうとしていましたが、上記の答えはうまくいきました。ポイントは、タグがあると機能しないことです。大きなファイルを含むコミットがタグから到達可能な場合、次のようにfilter-branchesコマンドを調整する必要があります。

git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags
5
BHMulder

参照: gitの履歴から機密ファイルを削除する方法

ファイルがリビジョンに存在しない場合、上記は失敗します。その場合、「-ignore-unmatch」スイッチで修正されます。

git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD

次に、すべてのゆるいオブジェクトを再配置から取得するには:

git gc --Prune='0 days ago'
2
Wayne Conrad

git gcの後のgitリポジトリサイズがまだ大きい理由はさまざまです。なぜなら、それは すべての緩いオブジェクトを削除しない であるためです。

これらの理由については、「 gitリポジトリサイズを小さくする 」で詳しく説明します。

しかし、あなたのケースでテストする1つのトリックは、 clone「クリーンな」Gitリポジトリ で、クローンに適切なサイズ。

( '"cleaned"リポジトリ'は、filter-branchを適用した後、gcPruneを適用したリポジトリです)

1
VonC

これは、Git Extrasのgit obliterateコマンドでカバーする必要があります( https://github.com/visionmedia/git-extras )。

git obliterate <filename>
1
Spain Train

私は同じ問題を抱えていて、誤ってコミットしたファイルを取り除く方法を段階的に説明する素晴らしい tutorial をgithubで見つけました。

Cupcakeが提案した手順の概要を以下に示します。

履歴から削除するfile_to_removeという名前のファイルがある場合:

cd path_to_parent_dir

git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch file_to_remove' \
  --Prune-empty --tag-name-filter cat -- --all
0
Cyril Leroux