使用git filter-branch删除不需要的文件的正确方法,而没有git rm失败

时间:2012-08-29 13:54:50

标签: git git-filter-branch

我有一个SNMP代理项目,其中相关的MIB文件(* .smiv2文件)与它一起开发,但现在我想将它们放在一个单独的git存储库中。

为了不丢失任何MIB文件历史记录,因为它们不是在现在的同一目录中启动,所以我不能只使用--subdirectory-filter filter-branch,所以我尝试了{{ 1}}方法,基于this question。我们的想法是删除所有不以--filter-index结尾的文件(显然是在原始项目的新克隆上,在该过程结束时将其推送到我的新MIBs回购中)。

为了简单起见,我选择使用.smiv2而不是ls-files,而不是:

ls-tree

我用过这个:

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'

但是在第一次提交中任何一个都失败了,因为看起来git filter-branch --prune-empty --index-filter 'git ls-files | \ grep -v ".smiv2$" | xargs git rm --cached --ignore-unmatch' 根本没有提供任何参数(我认为如果找不到提供的参数,git rm将正常工作,但不会case没有提供参数):

--ignore-unmatch

我让它在一个脚本中包装$ 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 ,即使由于缺少参数而失败也会返回成功(保存在git rm中):

/usr/local/bin/gitrm_alt

然后调用而不是#!/bin/sh git rm --cached --ignore-unmatch "$@" exit 0

git rm

但我发现这非常丑陋和笨重,所以我想问一下是否有更直接/更合适的方法来做到这一点。

4 个答案:

答案 0 :(得分:7)

最简单的解决方案是向git rm添加一个伪参数,使其始终至少有一个文件参数。

E.g。

... | xargs git rm --cached --ignore-unmatch DoesNotExistInMyProject

答案 1 :(得分:4)

xargs&#39; -r | --no-run-if-empty标志可能更清晰:

  

... | xargs --no-run-if-empty git rm --cached --ignore-unmatched

答案 2 :(得分:3)

完整答案,供将来参考

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

答案 3 :(得分:0)

也可以使用-I开关。

some command | xargs -I % rm %