场景
我正在尝试从 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
会遭到破坏。
我试图自己解决这个问题,尝试文件 glob 的变体并--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
处理文件 glob 扩展,而不是bash
. 好的。但这留下了这些问题:
- 我为什么要这样做?
- 我没有引用我的星号,所以
bash
应该进行扩展。如果这是真的,并且我的文件 glob 可以与 一起使用ls
,那么为什么它不能与 一起使用git-rm
呢?
我也看到了上面那个下面的例子,它似乎做了我想做的事情。然而,这不会发生在我身上,否则我不会在这里。不过,它似乎确实证实了我想用 进行文件扩展bash
。