使用git filter-branch正确删除不需要的文件而不导致git rm失败

6

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

为了不丢失任何MIB文件的历史记录,因为它们没有从同一个目录开始,我不能只使用--subdirectory-filter过滤分支,所以我尝试了基于这个问题--filter-index方法。我的想法是删除每个不以.smiv2结尾的文件(显然在原始项目的新克隆上),该克隆最终将被推送到我的新MIB存储库中。

为了使它更简单,我选择使用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提供任何参数(我猜想如果提供的参数未找到,则--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命令:

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

但我发现这样非常丑陋而笨重,所以我想问是否有更直接/适当的方法来完成此操作。


为什么不给 git rm --ignore-unmatched 传递一个永远不存在的额外虚拟参数,比如 | xargs rm --cached --ignore-unmatched DoesNotExistInMyProject - CB Bailey
哈哈,太完美了@CharlesBailey,我怎么没看出来呢?你不想把它变成一个答案,这样我就可以接受它了吗?谢谢! - Claudio
4个回答

8
最简单的解决方法是向git rm添加一个虚拟参数,以便它始终具有至少一个文件参数。
例如:
... | xargs git rm --cached --ignore-unmatch DoesNotExistInMyProject

5

xargs-r--no-run-if-empty 标记可能更加简洁:

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


3

完整答案,以供参考

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

0

也可以使用 -I 开关。

some command | xargs -I % rm % 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接