Reputation: 2169
I would like to remove a couple big files someone pushed into our git repository, so everybody else may pull from the repo without downloading them.
I already tried ignoring those files, and also removing/commiting/pushing them from the host that pushed them with no luck.
I have access to the server and the bare repo
Thanks!
Upvotes: 6
Views: 6690
Reputation: 489
There's also the BFG Repo-Cleaner which is much, much faster than git-filter-branch. However, it will not remove files that are referenced in a branch. Consult Dave's answer to remove those.
Upvotes: 0
Reputation: 32731
You have to rewrite the history using git filter-branch
or similar techniques. See this example to remove the file Rakefile
in the github help:
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch Rakefile' \
--prune-empty -- --all
You should be aware that everyone that already cloned your repository needs to hard reset their branches to the one on the remote or they'll reintroduce the files.
Upvotes: 2
Reputation: 3633
git filter-branch is your answer here.
From the bare repository, you have several choices.
1) You want to remove a file or files, from every commit.
$ git filter-branch --index-filter \
'git rm --cached --ignore-unmatch junk/bigfile' -- --all
or
$ git filter-branch --index-filter \
'git rm --cached --ignore-unmatch -r junk/' -- --all
2) You want to find a file, regardless of its path, and remove all history of its existence..
$ git filter-branch --index-filter \
'mv $GIT_INDEX_FILE /tmp/index;
GIT_INDEX_FILE=/tmp/index git ls-files -s|
grep -v FILENAME|git update-index --index-info' -- --all
3) You want to find a specific committed file, and remove only that file. For example if you commit a large binary, and later replace the file with a smaller file, you need to find the blob containing the original large file, and erase it.
$ git ls-tree -r <commit> | grep SOMEFILE
100644 blob 4cbedad5b4ab88f700bf27ae5a32bdb3627fa632 SOMEFILE
$ git filter-branch --index-filter \
'mv $GIT_INDEX_FILE /tmp/index;
GIT_INDEX_FILE=/tmp/index git ls-files -s|
grep -v 4cbedad5b4ab88f700bf27ae5a32bdb3627fa632|
git update-index --index-info' -- --all
Each time you do this, the current set of "refs" or branch heads is backed up into the refs/original directory. You can always copy these back to refs/heads to restore your repository.
If the file(s) you are removing result in an empty commit, add the '--prune-empty' option to the git-filter-branch command line. This will allow git to completely discard the commit.
As long as refs/original contains the original heads, git will never prune the excised files or blobs.
Once you are completely happy with the results, the repository itself can be shrunk
$ rm -rf refs/original
$ git fsck
$ git prune
$ git gc
$ git repack -a
And you are done.
WARNING: git-filter-branch will REWRITE EVERY COMMIT. Make sure there are no uncommitted/unpushed working changed. Everyone must be committed and pushed before doing this.
Once complete, each person should do the following $ git fetch --all $ git reset --hard @{upstream}
Upvotes: 9
Reputation: 3633
If the files you want to remove were commited on their own, you can use the rebase command to simply eliminate the commit.
1) checkout a working copy
$ git clone -s bare_repo.git
$ cd bare_repo
2) use git-log to find the commit
$ git log
384b1a3306c1247559563f855e2adf5ced80678b good commit
8abb0e7cf306ceb209cb5c4aa3b422b9460fdb64 bad commit
3) Use git rebase to rewrite the history, leaving out that commit
$ git rebase -i 8abb0e7cf306ceb209cb5c4aa3b422b9460fdb64^ <--- note the ^**
4) The bad commit should be the top line. Delete the line, save and exit. 5) git-log should show your history with the bad commit gone. 5) push the changes back. Use the -f flag to force the updates
$ git push -f origin master
6) You can now delete the working tree
Upvotes: 2