Git 命令从最初添加它们的提交中删除多个已删除的行

Git 命令从最初添加它们的提交中删除多个已删除的行

当我从 git 版本控制文件中删除几行后,是否有一个 git 命令可以从最初引入这些行的提交中删除这些行,而不是进行删除这些行的新提交?例如,给定此文件:

$ echo "Line 1" >> foo
$ echo "Line 2" >> foo
$ git commit -a -m "Add 1, 2"
[master 1005cbb] Add 1, 2
 1 file changed, 2 insertions(+)

$ echo "Line 3" >> foo
$ git commit -a -m "Add 3"
[master 5036981] Add 3
 1 file changed, 1 insertion(+)

$ echo "Line 4" >> foo
$ echo "Line 5" >> foo
$ git commit -a -m "Add 5, 6"
[master 41ca6ab] Add 5, 6
 1 file changed, 2 insertions(+)

$ git blame -s foo
1005cbbb 1) Line 1
1005cbbb 2) Line 2
50369811 3) Line 3
41ca6ab6 4) Line 4
41ca6ab6 5) Line 5

假设我删除了第 2-4 行:

$ sed -i '/Line [234]/d' foo
$ git diff
diff --git a/foo b/foo
index 572d5d9..e486b1b 100644
--- a/foo
+++ b/foo
@@ -1,5 +1,2 @@
 Line 1
-Line 2
-Line 3
-Line 4
 Line 5

现在,我不想提交该更改,而是想运行一些操作,将这些行从历史记录中完全删除,从而生成一棵新树,其中1005cbb(或无论新的哈希是什么)仅添加“第 1 行”,5036981为空(或消失),并41ca6ab添加“5 号线”。

这可能吗?我能想到的最接近的事情是在变基之前单独删除每一行git commit --fixup hash-of-the-commit-that-added-that-line,但我很好奇在我尝试以这种方式自动化执行之前是否有更好的内置方法。

答案1

这是什么git filter-branch是为了.它对历史记录的每个修订运行命令并重新提交结果,无论是否更改。它将更改第一个修改版本之后每次提交的所有哈希值,使新分支与任何克隆都不兼容。

如果sed -i '/Line [234]/d' foo是进行您想要的修改的命令,您可以将其应用为树过滤器:

git filter-branch --tree-filter "sed -i '/Line [234]/d' foo" HEAD

通常,将任何复杂的内容放入自己的脚本中会更容易。过滤命令是从另一个目录运行的,因此请提供完整路径。

过滤模式有很多种。树过滤器修改文件本身,并且可以与其他过滤器组合来更改提交消息或详细信息、父级、标签等。树过滤器的行为就像您在新存储库中运行一样git add -f *- 每个存在的文件都会添加其当前内容,忽略任何本地或全局忽略,并且任何不再存在的文件都将被删除。

相关内容