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.
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.
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.
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.
git-filter-branch can be used to get rid of a subset of files, usually with some combination of --index-filter and --subdirectory-filter .
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
xargs
's -r
|--no-run-if-empty
flag might be cleaner:
... | xargs
--no-run-if-empty
git rm --cached --ignore-unmatched
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With