"git rm -r" 通配

"git rm -r" with globbing

我正在尝试使用 git rm 作为过滤器分支的一部分。我想删除目录 */*/dir1 但没有任何反应。 我使用的命令是:

git filter-branch --tag-name-filter cat --index-filter "git rm -r --cached --ignore-unmatch */*/dir1" --prune-empty -f -- --all

命令

find . -wholename "*/*/dir1"

显示了很多匹配项。

如何删除这些目录?

更新:我正在尝试从历史记录中删除这些文件夹。

解决方案:

结合@j6t 和@Sam Gleske 的回答,这是我的解决方案:

git filter-branch --tag-name-filter cat \
   --index-filter 'git ls-files | grep -E "^([^/]+/){2,3}dir1" |
                   xargs -I {} --no-run-if-empty git rm -r --cached "{}"' \
   --prune-empty -f -- --all

使用这个(完全相同的顺序):

git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch */*/dir1' --prune-empty --tag-name-filter cat -- --all
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

根据git rm documentation, you can pass it one or more files or folders. Since that is the case you can take advantage of shell globbing。在 bash 中,您必须在引号外使用 glob。

git rm -r */*/dir1

但是,有可能点击 ARG_MAX limit in Linux(即 getconf ARG_MAX)并出现错误。您可以通过在原始查找命令中使用 xargs 来解决这个问题。

find . -wholename "*/*/dir1" -print0 | xargs -0 git rm -r

我还建议将 -type d 添加到您的查找命令中,因为其他文件类型可能具有与 dir1.

相同的名称

这只会将那些目录作为新提交删除。


使用 xargs 清除所有历史记录

由于您的意图是清除所有历史记录,并且 git rm 无法按预期工作;你还有另一种选择。使用带有 xargs 的原始 find 命令,使用来自 find 的路径删除整个历史记录。方法如下:

find . -wholename "*/*/dir1" -print0 | xargs -0 -I '{}' -n10 -- git filter-branch --tag-name-filter cat --index-filter "git rm -r --cached --ignore-unmatch {}" --prune-empty -f -- --all

诀窍是注意xargs-I '{}'选项,在命令xargs中使用{}将被执行。

另见

以下应该满足您的需要:

git filter-branch --tag-name-filter cat \
   --index-filter 'git ls-files -z -- "*/*/dir1" |
                   xargs -0 --no-run-if-empty git rm -r --cached' \
   --prune-empty -f -- --all

请注意,该命令确实会进入目录,即它会匹配 a/b/c/d/dir1,即使 ** 未在 git ls-files 的参数中使用。

结合@j6t 和@Sam Gleske 的回答,这是我的解决方案:

git filter-branch --tag-name-filter cat \
   --index-filter 'git ls-files | grep -E "^([^/]+/){2,3}dir1" |
                   xargs -I {} --no-run-if-empty git rm -r --cached "{}"' \
   --prune-empty -f -- --all