如何使用 git-rm 和文件通配从某些目录中删除文件,而不是这些目录的子目录



场景

我正在尝试从 git 存储库的整个历史记录中删除一些文件。它们都有几个共同的标准:

  • 它们的文件名中有"设置"。不过,它们也可能具有各种前缀和后缀。
  • 它们将位于文件树中某个目录内的级。二级目录的名称各不相同。文件树中存在不应删除的更深的设置文件。

下面是文件树的示例:

root-directory/
  |-> apples/
  |     |-> bad-settings-alpha.txt
  |     |-> bad-settings-beta.txt
  |
  |-> oranges/
  |     |-> bad-settings-gamma.txt
  |     |-> bad-settings-delta.txt
  |     |-> navels/
  |           |-> good-settings.txt
  |
  |-> good-settings.txt

我需要过滤掉所有bad-settings文件,同时保留good-settings文件。

我的方法

因此,使用 GitHub 提供的教程,结合 git-rm 的手册页,我精心设计了这个命令(分为两行):

git filter-branch -f --index-filter 'git rm --dry-run --cached  
--ignore-unmatch root-directory/*/*settings*.txt' --prune-empty -- --all

这里特别值得注意的是我使用的文件 glob:root-directory/*/*settings*.txt 。如果我将该文件 glob 与 ls 一起使用,那么我得到的正是我要删除的文件列表。所以,它应该有效,对吧?

显然不是。如果我使用该 glob 运行我的命令,它也会取出深度超过两个级别的所有设置文件。在上面的文件树示例中,这意味着root-directory/oranges/navels/good-settings.php将被核弹。


我试图自己解决这个问题,尝试文件球体的变化,并使用精彩的--dry-run选项进行git-rm.似乎没有任何效果 - 我所能想到的就是更改我开始删除设置文件的文件树深度。

确实发现了一件似乎与我的问题极其相关的事情。在 git-rm 的手册页中,有这样一个例子:

git rm Documentation/*.txt
  Removes all *.txt files from the index that are under the Documentation
  directory and any of its subdirectories.
  Note that the asterisk * is quoted from the shell in this example; this
  lets git, and not the shell, expand the pathnames of files and
  subdirectories under the Documentation/ directory.

"全部删除...索引中的文件位于...目录及其任何子目录"与实际发生的情况一致。真正有趣的是提到引用的星号。我知道这git-rm可以处理文件全球扩展而不是bash.好。但这留下了这些问题:

  • 我为什么要这样做?
  • 我没有引用我的星号,所以bash应该进行扩展。如果这是真的,并且我的文件 glob 适用于 ls ,那么为什么它不适用于git-rm

我也看到了上面下面的例子,它似乎做了我想做的事情。然而,这不会发生在我身上,否则我就不会在这里。不过,它似乎确实证实了我想bash进行文件扩展。

为什么不使用find来显示两级深度文件:

find . -maxdepth 2 -mindepth 2 -type f -name "bad-settings*"

这将为您提供只有两级深度导演的不良设置列表。您可以通过xargs将它们管道传输到git rm

find . -maxdepth 2 -mindepth 2 -type f -name "bad-settings*" | xargs git rm

最新更新