web-dev-qa-db-ja.com

git / GitHubの履歴からフォルダーとその内容を削除します

私は自分のGitHubアカウントでリポジトリを作成していましたが、これは私がつまずいた問題です。

  • いくつかのnpmパッケージがインストールされたフォルダーを持つNode.jsプロジェクト
  • パッケージはnode_modulesフォルダーにありました
  • そのフォルダーをgitリポジトリーに追加し、コードをgithubにプッシュしました(当時はnpmの部分については考えていませんでした)
  • そのフォルダーをコードの一部として実際に必要としないことを認識した
  • そのフォルダーを削除し、プッシュしました

その場合、合計gitリポジトリのサイズは約6MBでしたが、実際のコード(そのフォルダーを除くすべて)は約300 KB

最後に私が探しているのは、gitの履歴からそのパッケージフォルダの詳細を取り除く方法ですので、誰かがそれをクローンした場合、彼らは彼らが取得する実際のファイルだけである6mbの価値の履歴をダウンロードする必要はありません最後のコミットの時点で300KBになります。

私はこれの可能な解決策を探し、これらの2つの方法を試しました

Gistは、スクリプトを実行した後、そのフォルダーを削除したことを示し、その後50の異なるコミットが変更されたことを示したように見えました。しかし、そのコードをプッシュさせることはできませんでした。プッシュしようとすると、Branch up to dateと表示されましたが、git statusで50個のコミットが変更されたことが示されました。他の2つの方法も役に立ちませんでした。

フォルダーの履歴が削除されたことが示されたにもかかわらず、ローカルホストでレポのサイズを確認したところ、まだ約6MBでした。 (refs/originalfolderも削除しましたが、レポのサイズの変化は見られませんでした)。

私が明確にしたいのは、コミット履歴(これが起こったと思う唯一のこと)だけでなく、gitがロールバックしたいと仮定しているファイルも取り除く方法があるかどうかです。

これに対する解決策が提示され、私のローカルホストに適用されますが、そのGitHubリポジトリに再現することはできません、そのリポジトリを複製し、最初のコミットにロールバックしてトリックを実行してプッシュすることができますこれらのコミットの履歴はまだありますか?-別名6MB)。

ここでの私の最終目標は、基本的にgitからフォルダーのコンテンツを削除する最良の方法を見つけ、ユーザーが6MB相当のものをダウンロードする必要がなく、モジュールフォルダーに触れたことのない他のコミットを保持できるようにすることですそれらのほとんどすべて)gitの歴史の中で。

これどうやってするの?

249
Kartik

コードをコピーして貼り付けるためにここにいる場合:

これは、node_modulesを履歴から削除する例です

git filter-branch --tree-filter 'rm -rf node_modules' --Prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo node_modules/ >> .gitignore
git add .gitignore
git commit -m 'Removing node_modules from git history'
git gc
git Push Origin master --force
450
Mohsen

他の回答で使用されている--tree-filterオプションは、特に大量のコミットがある大きなリポジトリでは非常に遅くなることがあります。

以下は、--index-filterオプションを使用してgit履歴からディレクトリを完全に削除するために使用する方法です。

# Make a fresh clone of YOUR_REPO
git clone YOUR_REPO
cd YOUR_REPO

# Create tracking branches of all branches
for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

# Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits
# (repeat these two commands for as many directories that you want to remove)
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --Prune-empty --tag-name-filter cat -- --all
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

# Ensure all old refs are fully removed
rm -Rf .git/logs .git/refs/original

# Perform a garbage collection to remove commits with no refs
git gc --Prune=all --aggressive

# Force Push all branches to overwrite their history
# (use with caution!)
git Push Origin --all --force
git Push Origin --tags --force

gcの前後でリポジトリのサイズを確認できます:

git count-objects -vH
185
Lee Netherton

人気のある回答に加えて、 上記Windows-systemsにいくつかのメモを追加したいと思います。コマンド

git filter-branch --tree-filter 'rm -rf node_modules' --Prune-empty HEAD
  • 完全に動作します変更なし!したがって、Remove-Itemdel、またはrm -rfの代わりに他のものを使用しないでください

  • ファイルまたはディレクトリへのパスを指定する必要がある場合は、./path/to/node_modulesのようなスラッシュを使用します

36
participant

私が見つけた最良かつ最も正確な方法は、bfg.jarファイルをダウンロードすることでした: https://rtyley.github.io/bfg-repo-cleaner/

次に、コマンドを実行します。

git clone --bare https://project/repository project-repository
cd project-repository
Java -jar bfg.jar --delete-folders DIRECTORY_NAME  # i.e. 'node_modules' in other examples
git reflog expire --expire=now --all && git gc --Prune=now --aggressive
git Push --mirror https://project/new-repository

ファイルを削除する場合は、代わりにdelete-filesオプションを使用します。

Java -jar bfg.jar --delete-files *.pyc
18
Kim T

テスト後に、コマンドをコメントに追加するだけで(コピーアンドペーストソリューション用)、コピー&ペーストの完全なレシピを作成できます。

git filter-branch --tree-filter 'rm -rf node_modules' --Prune-empty HEAD
echo node_modules/ >> .gitignore
git add .gitignore
git commit -m 'Removing node_modules from git history'
git gc
git Push Origin master --force

この後、.gitignoreから「node_modules /」行を削除できます。

5
jgbarah

Windowsユーザーの場合、"の代わりに'を使用することに注意してください。別のバックアップが既に存在する場合にコマンドを強制する-fも追加されました。

git filter-branch -f --tree-filter "rm -rf FOLDERNAME" --Prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo FOLDERNAME/ >> .gitignore
git add .gitignore
git commit -m "Removing FOLDERNAME from git history"
git gc
git Push Origin master --force
4
Uwe

Windowsでgitを使用して、古いC#プロジェクトからbinおよびobjフォルダーを削除しました。に注意してください

git filter-branch --tree-filter "rm -rf bin" --Prune-empty HEAD

Gitインストールフォルダー内のusr/binフォルダーを削除することにより、gitインストールの整合性を破壊します。

2
LordObi