Remove folder and its contents from git/GitHub's history

青春壹個敷衍的年華 提交于 2019-11-26 11:26:09
Mohsen

If you are here to copy-paste code:

This is an example which removes node_modules from history

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

What git actually does:

The first line iterates through all references on the same tree (--tree-filter) as HEAD (your current branch), running the command 'rm -rf node_modules'. This command deletes the node_modules folder (-r, without -r, rm won't delete folders), with no prompt given to the user (-f). The added --prune-empty deletes useless (not changing anything) commits recursively.

The second line deletes the reference to that old branch.

The rest of the commands are relatively straightforward.

Lee Netherton

I find that the --tree-filter option used in other answers can be very slow, especially on larger repositories with lots of commits.

Here is the method I use to completely remove a directory from the git history using the --index-filter option, which runs much quicker:

# 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

You can check the size of the repository before and after the gc with:

git count-objects -vH
participant

In addition to the popular answer above I would like to add a few notes for Windows-systems. The command

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD
  • works perfectly without any modification! Therefore, you must not use Remove-Item, del or anything else instead of rm -rf.

  • If you need to specify a path to a file or directory use slashes like ./path/to/node_modules

Kim T

The best and most accurate method I found was to download the bfg.jar file: https://rtyley.github.io/bfg-repo-cleaner/

Then run the commands:

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

If you want to delete files then use the delete-files option instead:

java -jar bfg.jar --delete-files *.pyc

Complete copy&paste recipe, just adding the commands in the comments (for the copy-paste solution), after testing them:

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

After this, you can remove the line "node_modules/" from .gitignore

For Windows user, please note to use " instead of ' Also added -f to force the command if another backup is already there.

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

I removed the bin and obj folders from old C# projects using git on windows. Be careful with

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

It destroys the integrity of the git installation by deleting the usr/bin folder in the git install folder.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!