Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove files from a bare Git Repository Globally

Tags:

git

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!

like image 746
Multitut Avatar asked Mar 26 '14 00:03

Multitut


People also ask

How do I remove unwanted files from my git repository?

Git can help you clean up files that you have told it you don't want. The command git clean -n will show you a list of files that are in the repository, but whose history Git is not currently tracking. A similar command git clean -f will then delete those files.

How do I remove a file from my repository without deleting locally?

Using the git rm –cached Command However, the git rm command provides the –cached option to allow us only to remove files from the repository's index and keep the local file untouched.


2 Answers

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}

like image 52
Dave Avatar answered Sep 20 '22 10:09

Dave


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.

like image 41
TimWolla Avatar answered Sep 21 '22 10:09

TimWolla