是否可以使用交互式git rebase从历史记录中删除文件?

是否可以使用交互式git rebase从历史记录中删除文件?,git,git-rebase,git-filter-branch,Git,Git Rebase,Git Filter Branch,在我的本地存储库中有一个旧的提交,它添加了一些文件,包括一个名为“无用的.txt”的文件。在随后的提交中,该文件与其他文件一起被修改。是否可以使用交互式git rebase从历史记录中完全删除文件“多余的.txt”? 我知道使用“git filter branch”可以实现这一点,但由于我正在学习git,并且我想了解“git rebase-I”的全部潜力,我想知道这个命令是否可以用于此类操作。您应该能够通过编辑有问题的提交来实现这一点(即在rebase todo列表中提交之前的e或edit),然

在我的本地存储库中有一个旧的提交,它添加了一些文件,包括一个名为“无用的.txt”的文件。在随后的提交中,该文件与其他文件一起被修改。是否可以使用交互式git rebase从历史记录中完全删除文件“多余的.txt”?
我知道使用“git filter branch”可以实现这一点,但由于我正在学习git,并且我想了解“git rebase-I”的全部潜力,我想知道这个命令是否可以用于此类操作。

您应该能够通过编辑有问题的提交来实现这一点(即在rebase todo列表中提交之前的
e
edit
),然后按如下方式删除文件:

git rm unwanted.txt
git commit --amend
git rebase --continue
    A - B - C - F    [abandoned]
   /  \       /
  /     D - E
 /
I - A' - B' - C' - F'   <-- master
       \         /
         D' - E'
这可能会在以后更改文件的提交中产生冲突,但这应该通过再次删除文件并继续重新基址来解决

编辑
您很可能还必须确保没有分支指向不需要的文件仍然存在的任何提交,并运行
git gc
清除repo中的未引用blob。如果这是一个纯私有的repo,不与任何其他人共享,这应该不会是一个问题。

理论上是可能的,但实际上通常是太多了恩富尔

这种方法在rebase和filter branch中都是一样的。如果您认识到交互式rebase的所有功能都是,
git cherry pick
,就像类固醇一样;
git filter branch
只是跨多个分支和合并保存的一个自动化的超复杂的rebase,这可能会有所帮助

与git一样,它主要归结为操作提交图,并添加新的提交,这些提交看起来像现有的提交,但在本例中有所改变,即附加到这些提交的树。(一旦一个提交不同,它就会得到一个不同的SHA-1,这意味着所有后续提交也必须更改,以列出随着新图形的增长而出现的不同SHA-1。)

要了解它是如何工作的,请从绘制提交图开始。您需要一个相当完整的图,这取决于您必须走多远才能停止查看
不需要的.txt
文件。但我将只绘制一个简单的图,其中只有一个命名分支,
master

I - A - B - C - F   <-- master
      \       /
        D - E
使用
--preserve merges
的交互式重新基址可以处理这种特殊情况。但是,如果有多个分支,则必须根据需要使用
--on
小心地将其他分支重新基址,以使用新的提交,新的提交必须与旧的提交相匹配,最有可能是使用您需要的SHA-1映射文件在运行时手动构建

还有一个缺点,就是默认情况下,
git commit
拒绝进行“空”提交,其中“空”定义为“与上一次提交具有相同的树”(并且不是合并)。筛选器分支脚本会自动为您处理此问题,如果您选择删除空提交,则会将多个新提交映射到单个旧提交(当上一个提交和新提交都放弃不需要的文件时,仅修改不需要的文件的提交将变为空)。在保存合并时,交互式重新基不能很好地处理此问题,因此会带来更多的痛苦


还有其他一些细微的区别:例如,当rebase“放弃”一系列提交时,它们仍保留在“reflog”中对于已重定基址的分支,以及在reflog for
HEAD
中。筛选器分支脚本使用不同的方法:它将所有引用复制到子名称空间
refs/original/
。当您想要清除旧的、放弃的提交时,这一切都很重要:使用重定基址,“过期”旧引用,但使用过滤器分支,您可以强制删除原始引用。

另一种选择是BFG。