web-dev-qa-db-ja.com

gitによって作成された大きな.packファイルを削除します

大量のファイルをブランチにチェックインしてマージした後、それらを削除する必要がありましたが、今は削除する方法がわからない大きな.packファイルが残っています。

git rm -rf xxxxxxを使用してすべてのファイルを削除し、--cachedオプションも実行しました。

現在次のディレクトリにある大きな.packファイルを削除する方法を教えてください。

.git/objects/pack/pack-xxxxxxxxxxxxxxxxx.pack

まだ持っているが、もう使用していないブランチを削除するだけですか?または、私が実行する必要がある何か他のものがありますか?

どれだけ違いがあるかはわかりませんが、ファイルに対して南京錠が表示されます。

ありがとう


編集

ここに、bash_historyからの抜粋を示します。これは、この状態に到達する方法を理解するためのものです(この時点で、「my-branch」と呼ばれるgitブランチで作業しており、ファイル):

git add .
git commit -m "Adding my branch changes to master"
git checkout master
git merge my-branch
git rm -rf unwanted_folder/
rm -rf unwanted_folder/     (not sure why I ran this as well but I did)

私はまた、次を実行したと思いましたが、他の人と一緒にbash_historyに表示されません:

git rm -rf --cached unwanted_folder/

また、パックファイルを整理するためにいくつかのgitコマンド(git gcなど)を実行したが、それらは.bash_historyファイルにも表示されないと思った。

82
user1116573

問題は、ファイルを削除しても、以前のリビジョンには残っているということです。これがgitの重要なポイントです。何かを削除しても、履歴にアクセスすることで元に戻すことができます。

あなたがやろうとしていることは、履歴の書き換えと呼ばれ、git filter-branchコマンドが関係していました。

GitHubのサイトでは、この問題に関する適切な説明があります。 https://help.github.com/articles/remove-sensitive-data

質問にもっと直接答えるために、基本的に実行する必要があるのは、それに応じてunwanted_filename_or_folderを置き換えたこのコマンドです。

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_filename_or_folder' --Prune-empty

これにより、レポのアクティブな履歴からファイルへのすべての参照が削除されます。

次のステップでは、GCサイクルを実行して、ファイルへのすべての参照を期限切れにし、パックファイルから削除します。これらのコマンドで何も置き換える必要はありません。

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --Prune=now
166
loganfsmyth

シナリオA:大きなファイルがブランチにのみ追加された場合、git filter-branchを実行する必要はありません。ブランチを削除して、ガベージコレクションを実行するだけです。

git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --Prune=all

シナリオB:ただし、bash履歴に基づいて、変更をマスターにマージしたように見えます。変更を誰とも共有していない場合(まだgit Pushなし)。最も簡単な方法は、大きなファイルがあったブランチとのマージの前にマスターをリセットすることです。これにより、ブランチからのすべてのコミットと、マージ後にマスターに対して行われたすべてのコミットが削除されます。そのため、大きなファイルに加えて、実際に望んでいた変更を失う可能性があります。

git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>

次に、シナリオAの手順を実行します。

シナリオC:ブランチから他の変更があった場合またはマージ後に保持したい変更がマスターにある場合、マスターをリベースし、選択的にコミットを含めることをお勧めしますあなたが欲しい:

git checkout master
git log # Find the commit hash just before the merge
git rebase -i <commit hash>

エディターで、大きなファイルを追加したコミットに対応する行を削除しますが、その他はすべてそのままにします。保存して終了します。マスターブランチには必要なもののみを含め、大きなファイルは含めないでください。 git rebaseなしの-pはマージコミットを排除するため、<commit hash>の後にmasterの線形履歴が残ることに注意してください。これはおそらく大丈夫ですが、そうでない場合は、-pで試すことができますが、git help rebasecombining -p with the -i option explicitly is generally not a good idea unless you know what you are doingと言います。

次に、シナリオAのコマンドを実行します。

6
onlynone

1つのオプション:

git gcを手動で実行して、多数のパックファイルを1つまたはいくつかのパックファイルに圧縮します。この操作は永続的です(つまり、大きなパックファイルは圧縮動作を保持します)ので、git gc --aggressiveを使用してリポジトリを定期的に圧縮すると有益な場合があります

別のオプションは、コードと.gitをどこかに保存してから.gitを削除し、この既存のコードを使用して再起動して、新しいgitリポジトリ(git init)を作成することです。

5
Michael Durrant

Loganfsmythが answer で既に述べているように、リポジトリからファイルを削除した後もファイルが存在し続けるため、git履歴を消去する必要があります。公式のGitHubドキュメント BFGを推奨filter-branchよりも使いやすいと思います:

履歴からファイルを削除する

ダウンロード BFGのWebサイトから。 Javaがインストールされていることを確認してから、ミラークローンを作成し、履歴を消去します。 YOUR_FILE_NAMEを削除するファイルの名前に置き換えてください:

git clone --mirror git://example.com/some-big-repo.git
Java -jar bfg.jar --delete-files YOUR_FILE_NAME some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --Prune=now --aggressive
git Push

フォルダーを削除する

上記と同じですが、--delete-foldersを使用します

Java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git

別のオプション

BFGでは、次のようなさらに洗練されたオプション( docs を参照)も使用できます。

履歴から100Mより大きいすべてのファイルを削除します。

Java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git

重要!

BFGを実行するときは、YOUR_FILE_NAMEYOUR_FOLDER_NAMEの両方が実際には単なるファイル/フォルダー名であることに注意してください。 これらはパスではない、したがって、foo/bar.jpgのようなものは機能しません!代わりに、指定された名前を持つすべてのファイル/フォルダーは、存在するパスまたはブランチに関係なく、レポ履歴から削除されます。

5
Timo

PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATAを、ファイル名だけでなく、削除するファイルへのパスに置き換えて、次のコマンドを実行します。これらの引数は:

  1. すべてのブランチとタグの履歴全体をGitに強制的に処理させますが、チェックアウトはさせません。
  2. 指定されたファイルと、結果として生成された空のコミットを削除します
  3. 既存のタグを上書きする
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --Prune-empty --tag-name-filter cat -- --all

これにより、レポのアクティブな履歴からファイルへのすべての参照が強制的に削除されます。

次のステップでは、GCサイクルを実行して、ファイルへのすべての参照を強制的に期限切れにし、パックファイルから削除します。これらのコマンドで何も置き換える必要はありません。

git update-ref -d refs/original/refs/remotes/Origin/master
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --Prune=now
1
Benjamin Wasula

私はショーに少し遅れましたが、上記の答えがクエリを解決しなかった場合、別の方法を見つけました。 .packから特定の大きなファイルを削除するだけです。誤って大きな2GBファイルをチェックインしたこの問題がありました。このリンクで説明されている手順に従いました: http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/

1
Rishabh Kumar