git筛选器分支:通过排除、不包括来筛选目录?

git筛选器分支:通过排除、不包括来筛选目录?,git,git-filter-branch,Git,Git Filter Branch,假设我在回购中有这样的结构: repo/ dir1/ dir2/ dir3/ dir4/ dir5/ ... 现在我想保留所有目录,除了dir1和dir2 我可以使用此命令保留指定的目录 git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- dir3 dir4 dir5 ... dirN' --p

假设我在回购中有这样的结构:

repo/
  dir1/
  dir2/
  dir3/
  dir4/
  dir5/
  ...
现在我想保留所有目录,除了
dir1
dir2

我可以使用此命令保留指定的目录

git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- dir3 dir4 dir5 ... dirN' --prune-empty -- --all

现在,如果我有很多目录,那么排除我不需要的目录会比指定我需要的目录更简单。我如何才能做到这一点?

更改您的
索引过滤器
以专门删除不需要的路径,而不对任何其他路径执行任何操作,即
--索引过滤器
部分变为:

--index-filter 'git rm --cached -qr --ignore-unmatch dir1 dir2'
现在使用的索引过滤器由两个单独的命令组成,它们由
&&
连接。这些命令是文本形式的:

  • 把所有东西都拿走。(这里,
    --ignore unmatch
    是没有意义的,因为您使用
    指定“存在的一切”,而“存在的一切”显然是存在的。)
  • 然后,从当前提交中放回
    dir3
    dir4
    ,等等
由于您只想(递归地)删除“dir1中的所有内容”和“dir2中的所有内容”,请指定这些内容。如果可能存在不存在
dir1
和/或
dir2
文件的提交,则保留
--忽略不匹配。在删除了想要删除的内容之后,您不需要再放任何东西:临时索引
git filter branch
用来实现过滤的索引(见下文)——现在有了正确的文件集

边栏:这个索引到底是什么? 当您进行新的提交时,Git实际上并不使用工作树中的文件。他们在这里不重要

相反,Git主要实现为一个名为
.Git/index
的文件,实际上,Git可以调用不同的索引或暂存区域,或者(现在很少)缓存。此索引最初保存从当前提交中取出的每个文件的副本。然后可以使用
git add
git rm
更新索引中的文件,或将文件完全从索引中删除

您可以将索引视为建议的下一个提交。当您运行
git commit
时,git会打包索引中该点的文件,并将其冻结为新的、永久的1只读提交。在您的工作树中,您看到并使用的文件只针对您,而不是真正针对Git。这就是为什么,每当您修改工作树文件并希望更改进入下一次提交时,您必须始终
git add
git add
告诉git获取工作树副本并使用它覆盖索引副本,以便next提交将具有此版本

使用
git filter branch
时,有很多选项。最慢的一个,
--tree filter
,接受每个提交,将其复制到一个临时索引中,因为Git总是需要一个索引来存储这些内容,即使它不是常规的主索引,然后将临时索引中的所有文件提取到一个临时树中。然后,您可以使用
--tree过滤器
代码修改临时树中的文件。Git然后重新读取临时树,从中构建一个新的(但仍然是临时的)索引,并使用该索引进行新的提交

所有这些复制都非常慢。所以filter branch为您提供了
--索引filter
:这一次,Git将提交复制到一个临时索引,然后允许您直接修改临时索引。
git rm--cached
命令通过从索引中删除文件来修改索引,或者在本例中修改临时索引。然后过滤器分支从临时索引进行新的提交。这将跳过
--树过滤器的最慢部分

您仍然会将存储库中的每个提交复制到某个新的和改进的提交,但通过仅在filter branch提供的临时索引中进行复制,速度会快得多



1社区实际上只是半永久性的。只要Git能找到它们,它们就会持续。有关这方面的更多信息,请参阅。当您使用过滤器分支时,您将一些提交复制到一些新的和改进的提交,并让您的Git尝试忘记原始提交。最终,您的Git可能会忘记它们。

但您建议的命令似乎只是删除了文件。它在更改中显示文件将被删除。然后建议进行阶段性的改变。这看起来基本上和我手动删除文件并提交更改时一样。这个命令有什么不同?我不想看到那些目录被删除的承诺。使用我原来的命令,它会过滤掉这些目录,就好像这些更改从未存在过一样。这就是我希望它被过滤掉的方式。我的坏消息。我看错了你的答案。我以为这就是你建议的全部命令。没有注意到它是专门用于
索引过滤器的