Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to remove unwanted files with git filter-branch without git rm failing

I have a project of an SNMP agent where the related MIB files (*.smiv2 files) were developed along with it, but now I want them in a separate git repository.

In order not to lose any of the MIB files history, since they didn't start in the same directory they are now, I couldn't just use --subdirectory-filter filter-branch, so I tried the --filter-index approach, based on this question. The idea would be to remove every file which doesn't end with .smiv2 (obviously on a fresh clone of the original project, which shall be pushed to my new MIBs repo by the end of the process).

To make it simpler, I chose using ls-files over ls-tree, so instead of:

git filter-branch --prune-empty --index-filter 'git ls-tree -r --name-only \
--full-tree $GIT_COMMIT | grep -v ".smiv2$" | xargs git rm --cached \
--ignore-unmatch -r'

I used this:

git filter-branch --prune-empty --index-filter 'git ls-files | \
grep -v ".smiv2$" | xargs git rm --cached --ignore-unmatch'

but any of these failed in the first commit, since it appears git rm was fed no arguments at all (I suppose --ignore-unmatch will work fine if the supplied arguments are not found, but not in the case no arguments are supplied):

$ git filter-branch --prune-empty --index-filter 'git ls-files | \
>     grep -v ".smiv2$" | xargs git rm --cached --ignore-unmatch'
Rewrite 4cd2f1c98dbaa96bc103ae81fbd405bd1d991d9a (1/418)usage: git rm [options] [--] <file>...

    -n, --dry-run         dry run
    -q, --quiet           do not list removed files
    --cached              only remove from the index
    -f, --force           override the up-to-date check
    -r                    allow recursive removal
    --ignore-unmatch      exit with a zero status even if nothing matched

index filter failed: git ls-files | \
    grep -v ".smiv2$" | xargs git rm --cached --ignore-unmatch

I got it working wrapping git rm in a script which returns success even when it fails due to lack of arguments (saved it in /usr/local/bin/gitrm_alt):

#!/bin/sh
git rm --cached --ignore-unmatch "$@" 
exit 0

and then calling that instead of git rm:

git filter-branch --prune-empty --index-filter 'git ls-files | \
    grep -v ".smiv2$" | xargs gitrm_alt'

but I found that extremely ugly and clunky, so I'd like to ask if there's a more direct/proper way to do this.

like image 425
Claudio Avatar asked Aug 29 '12 13:08

Claudio


People also ask

How do I delete unnecessary files in git?

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 a git branch?

The easiest way to delete a file in your Git repository is to execute the “git rm” command and to specify the file to be deleted. Note that by using the “git rm” command, the file will also be deleted from the filesystem.

How do you remove delete a large file from commit history in the git repository?

If the large file was added in the most recent commit, you can just run: git rm --cached <filename> to remove the large file, then. git commit --amend -C HEAD to edit the commit.

What does git filter branch do?

git-filter-branch can be used to get rid of a subset of files, usually with some combination of --index-filter and --subdirectory-filter .


2 Answers

The simplest solution would be to add a dummy argument to git rm so that it always has at least one file parameter.

E.g.

... | xargs git rm --cached --ignore-unmatch DoesNotExistInMyProject
like image 165
CB Bailey Avatar answered Sep 19 '22 13:09

CB Bailey


xargs's -r|--no-run-if-empty flag might be cleaner:

... | xargs--no-run-if-emptygit rm --cached --ignore-unmatched

like image 34
jthill Avatar answered Sep 21 '22 13:09

jthill