带-index-filter的git-filter-branch:奇怪的bash错误(!:找不到事件)

时间:2012-09-24 11:55:23

标签: git bash git-filter-branch

我正在使用this question的答案将存储库的克隆剥离到我想要保留的文件列表中。假设我想删除目录src/main及其子目录以外的所有目录。因为我将拥有多个文件和目录,所以我使用--index-filter代替--subdirectory-filter

我认为以下内容应该有效:

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩
  src/!(main)" --prune-empty -- --all

但我得到的只是

-bash: !: event not found

我尝试了各种不同的路径,而不是src/!(main)。我总是得到那个错误信息。这似乎是一个bash问题,因为该行也没有进入我的命令行历史记录?


也就是说,如果我有顶级文件AB和子目录C/D,我如何删除所有这三个东西?

3 个答案:

答案 0 :(得分:4)

!是问题,因为它用于命令历史记录调用。在引号内,在前面加一个反斜杠也没有用,所以\!必须在引号之外。可以使用echo的几个例子进行说明:

/home/user1> echo "src/!(main)"
-bash: !: event not found
/home/user1> echo "src/\!(main)"
src/\!(main)
/home/user1> echo "src/"\!"(main)"
src/!(main)

答案 1 :(得分:3)

要回答澄清中添加的实际问题:您尝试使用bash的 \ textglob 删除src中的所有内容,main git index-filter }。这不起作用,因为索引过滤器命令是由shell执行而不是,而是由sh通过eval执行(请参阅/usr/lib/git-core/git-filter-branch:327)。

You can't tell git to enable extglob when doing this, but you can make your shell expand the extglob before passing it to index-filter

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch $(ls -xd src/!(main))" --prune-empty -- --all

答案 2 :(得分:0)

感叹号在Bash的语法中用于history expansion,这是导致混淆的原因。您必须使用反斜杠或单引号将其转义:

git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩
  src/\!(main)" --prune-empty -- --all