149

ブランチに大量のファイルをチェックインしてマージした後、それらを削除する必要がありましたが、削除する方法がわからない大きな.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ファイルにも表示されません。

4

7 に答える 7

228

問題は、ファイルを削除しても、以前のリビジョンに残っていることです。それが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
# or, for older git versions (e.g. 1.8.3.1) which don't support --stdin
# git update-ref $(git for-each-ref --format='delete %(refname)' refs/original)
git reflog expire --expire=now --all
git gc --aggressive --prune=now
于 2012-06-30T21:45:51.103 に答える
16

シナリオ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>。これはおそらくあなたにとっては大丈夫ですが、そうでない場合は、で試すことができますが-pgit help rebaseと言いcombining -p with the -i option explicitly is generally not a good idea unless you know what you are doingます。

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

于 2015-03-25T14:26:40.483 に答える
11

loganfsmythがすでに彼の回答で述べているように、ファイルをリポジトリから削除した後もファイルはそこに存在し続けるため、git履歴を削除する必要があります。公式のGitHubドキュメントでは、 BFGを推奨していますfilter-branch

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

彼らのウェブサイトからBFGをダウンロードしてください。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では、次のようなより洗練されたオプション(ドキュメントを参照)も使用できます。

履歴から1億を超えるすべてのファイルを削除します。

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

重要!

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

于 2018-04-04T08:18:17.977 に答える
11

次のコマンドを実行し、ファイル名だけでなく、削除するファイルへのパスに置き換え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
于 2019-07-11T17:09:05.933 に答える
7

1つのオプション:

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

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

于 2012-06-15T12:36:45.013 に答える
3

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

于 2018-01-08T18:34:29.987 に答える
-5

これは、コーディングよりも便利なソリューションです。ファイルを圧縮します。zipをファイルビュー形式で開きます(解凍とは異なります)。.packファイルを削除します。フォルダを解凍して置き換えます。チャームのように機能します!

于 2019-02-01T15:16:55.837 に答える