26

それで、私はStackoverflowの主題に関連する以前の質問を知っていると言って、この質問の前置きをさせてください。実際、私は見つけたすべての解決策を試しましたが、リポジトリにバイナリファイルがあり、削除を拒否し、リポジトリのサイズを大幅に拡大し続けています。

私が試した方法、

どちらも、gitリポジトリからファイルを完全に削除するというDarhuukの回答によって推奨されました

ただし、これらの解決策の両方を試した後でも、gitで大きなファイルを見つけるスクリプトは問題のあるバイナリを見つけます。ただし、この回答のスクリプトは、バイナリのコミットを検出しなくなりました。これらのスクリプトは両方とも、この回答によって提案されました。

削除を試みた後もレポは44mbのままです。これは、ソースの比較的小さいサイズには大きすぎます。大きなファイルスクリプトが適切に機能していることを示唆しているのはどれですか。githubにプッシュして(念のためフォークを作成しました)、レポジトリのサイズが減少したかどうかを確認するために新しいクローンを作成してみましたが、それでも同じサイズです。

誰かが私が間違っていることを説明したり、別の方法を提案したりできますか?

ローカルリポジトリからファイルをトリミングするだけでなく、Githubでリモートリポジトリを修正できるようにしたいことに注意してください。

4

4 に答える 4

27

2017年の編集:これを読んでいる場合は、おそらくBFGRepo-Cleanerを調べる必要があります。


恥ずかしいことに、ローカルリポジトリのサイズが縮小しなかったのは、filter-branchでファイルへの間違ったパスを使用していたためです。ですから、J-16 SDiZとCodeGnomeの回答に感謝しますが、私の問題は椅子とキーボードの間にありました。

この質問を私の愚かさの記念碑ではなく、実際に人々に役立つようにするために、Githubでレポを元に戻すために、レポをトリミングした後に実行する必要のある手順を書き留めました。 。これが誰かの助けになることを願っています。


問題のあるファイルを削除する

問題のあるファイルを削除するには、 Githubで機密データを削除する方法に基づいて、以下のシェルスクリプトを実行します

#!/usr/bin/env bash
git filter-branch --index-filter 'git rm -r -q --cached --ignore-unmatch '$1'' --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

ローカルリポジトリのすべてのブランチを調べてこれを実行しましたが、これが必要かどうかは正直わかりません(すべてのブランチでこれを実行する必要はありません)。ただし、次のステップではすべてのブランチがローカルである必要があります。心に留めておきます。完了すると、ローカルリポジトリのサイズが減少するのがわかります。また、CodeGnomeの回答でblobスクリプトを実行して、問題のあるblobが削除されるのを確認できるはずです。そうでない場合は、ファイル名とパスを再確認し、それらが正しいことを確認してください。

ここでgitfilter-branchが実際に行っているのは、リポジトリ内の各コミットで引用符で囲まれたコマンドを実行することです。

スクリプトの残りの部分は、古いデータのキャッシュされたバージョンをクリーンアップするだけです。

トリミングされたリポジトリをプッシュする

ローカルリポジトリが状態になっているので、Githubに戻すのがコツです。残念ながら、Githubリポジトリからバイナリデータを完全に削除する方法はありません。Githubの機密データのハウツーからの引用です。

強制プッシュはリモートリポジトリのコミットを消去しないことに注意してください。新しいリポジトリを導入し、ブランチポインタを移動してそれらを指すようにします。ユーザーがSHA1を介して不正なコミットに直接アクセスすることを心配している場合は、リポジトリを削除して再作成する必要があります。

Githubリポジトリを再作成する必要があるのは残念ですが、リポジトリの再作成は実際には非常に簡単です。苦痛は、問題とwikiのデータも再作成する必要があることです。これについては以下で説明します。

私がお勧めするのは、githubで新しいリポジトリを作成し、準備ができたら古いリポジトリに切り替えることです。これは、古い名前を「repo name old」のような名前に変更してから、新しく作成されたリポジトリの名前を「reponame」に変更することで実行できます。新しいリポジトリを作成するときは、READMEで初期化のチェックを外してください。そうしないと、きれいな状態を処理できなくなります。

最後の手順を完了した場合は、リポジトリをクリーンアップして準備ができているはずです。リモートは、新しいGithubリポジトリの場所と一致するように変更する必要があります。私は.git/configファイルを直接編集することでこれを行いますが、誰かがそれを行うのは正しい方法ではないと私に言うだろうと確信しています。

プッシュを実行する前に、ローカルリポジトリにプッシュするすべてのブランチとタグがあることを確認してください。準備ができたら、以下を使用してすべてのブランチをプッシュします

git push --all
git push --tags

これで、トリミングされたローカルリポジトリと一致するリモートリポジトリが必要になります。万が一に備えて、すべてのデータが作成されていることを再確認してください。

これで、問題やwikiについて心配する必要がなければ完了です。あなたが読んだら。

ウィキを移動する

Github wikiは、メインリポジトリに関連付けられているもう1つのリポジトリです。したがって、開始するには、古いwikiリポジトリのクローンをどこかに作成します。次に、ウィキを作成するために新しいリポジトリのウィキタブをクリックする必要があると私が言う限り、次の部分はちょっとトリッキーですが、新しく作成されたウィキに初期ファイルをシードします。だから私がしたこと、そしてもっと良い方法があるかどうかはわかりませんが、リモートを新しく作成したwikiリポジトリに変更し、を使用して新しい場所にプッシュすることです

git push --all --force

ここで力が必要なのは、そうしないとgitが現在のブランチの先端が一致しないと文句を言うからです。これにより、最初のページがgitレポジトリで切り離された状態になる可能性があると思いますが、レポジトリのサイズへの影響は無視できるはずです。

問題を移動する

この答えによって与えられたこれに関するアドバイスがあります。しかし、回答にリンクされているスクリプトを見ると、かなり不完全であるように見えます。コメントをインポートするためのTODOがあり、問題の状態を引き継ぐかどうかはわかりませんでした。

未解決の問題のキューがかなり少なく、未解決の問題を失ってもかまわないことを考えると、手作業で物事を持ち込むことにしました。コメントで他の人に適切に帰属することでこれを行うことは不可能であることに注意してください。したがって、より大規模で確立されたプロジェクトの場合、すべてを引き継ぐために、より堅牢なスクリプトを作成する必要があると思いますが、それは私の特定のケースでは必要ありませんでした。

于 2012-06-30T20:34:59.600 に答える
22

git-filter-branch(1)やその仲間たちと一緒に履歴からブロブをすでに削除していると仮定すると、Gitは多くの場合、reflog、packfile、および緩いリポジトリオブジェクトに物事を保持します。これらの参照されていないオブジェクトを削除するための呪文は次のとおりです。

git prune --expire=now
git reflog expire --expire-unreachable=now --rewrite --all
git repack -a -d
git prune-packed

これを実行しても、リポジトリが思ったよりも大きい場合は、リポジトリのどこかにBLOBへの参照があります。手順1に戻って、それらを削除する必要があります。これは役立つかもしれません:

# List all blobs by size in bytes.
git rev-list --all --objects   |
    awk '{print $1}'           |
    git cat-file --batch-check |
    fgrep blob                 |
    sort -k3nr
于 2012-06-29T06:31:25.010 に答える
6

gitで大きなファイルを見つけるためのスクリプト内のスクリプトは、.packファイル(つまり、生のオブジェクトリポジトリ)をチェックします。2番目のスクリプトは、ラージオブジェクトが参照されなくなったことを示しています。あなたが本当にそれをきれいにしたいのなら、あなたはとをするかもしれませgcrepack

git gc --aggressive --prune=now
git repack -A -d

それでも問題が解決しない場合は、リモートブランチにオブジェクト参照がある可能性があります。

  1. このオブジェクトを持っているコミットを見つけてください。このblobを持っているコミットを見てください。そして、やりますgit branch -a --contains <commit-ish>
  2. を使用してリモートブランチを削除しますgit branch -r -D branchname

更新-「リモートブランチ」とは何ですか?

  • git fetchリモートブランチは、 /を実行するときにgitが処理をフェッチするものですgit pull。(+git pullと同じです。git fetch refspecgit merge remote-branch

  • リモートリポジトリからクローンを作成する場合、リモートブランチを削除しても悪影響はありません。たとえば、次のような方法を使用して、リモートからいつでもフェッチ/プルできますgit fetch origin refs/heads/master:refs/remotes/origin/master(これにより、masterブランチがリモートからリモートブランチにプルされremotes/origin/masterます)。

  • このブランチが自分で作成した場合は、削除しても問題ありません。そのための「通常の」(追跡)ブランチが必要だからです。ただし、これを再確認する必要があります。

于 2012-06-29T03:51:36.327 に答える
1

誰かが私が間違っていることを説明したり、別の方法を提案したりできますか?

DMAICを適用してみましたか?定義、測定、分析改善制御

D-git履歴からファイルを削除した後も、リポジトリがまだ大きいです。
M-git initベースラインを確立するために使用して、新しいリポジトリのサイズを決定します。
A-根本原因を特定、検証、選択します。で実験してgit-repo-analysisください。
I-ソリューションを特定、テスト、および実装します。たぶんBFGレポクリーナーが役立つでしょう。多分そうではないでしょう。
C-利益を維持します。GitLFSやその他の適切な制御方法のようなものを見てください。

また、Githubのリモートリポジトリを修正できるようにしたいと思います。

これは、問題の解決方法によって異なります。たとえば、BFGを使用して履歴からファイルをトリミングすると、履歴が書き換えられ、コミットSHAが更新されるため、特定のニーズと望ましい結果に応じて、ここでいくつかのギブアンドテイクが行われます。

于 2017-05-26T05:08:38.097 に答える