git squash 更改一个文件

问题描述

我有几个提交对文件进行了无效更改,但其中一些提交与对另一个文件的相关更改相结合。所以我只想压缩对一个文件的更改。我该怎么做?

示例: 以下应表示提交,[......] 表示文件内容

这就是我所拥有的:

  • 提交 5 file A: [.....] file B: [......]
  • 提交 4 file A: [ ] file B: [.... ]
  • 提交 3 file A: [.....] file B: [... ]
  • 提交 2 file A: [ ] file B: [... ]
  • 提交 1 file A: [.....] file B: [.. ]

差异将是:

  • 提交 5 file A: [+++++] file B: [....++]
  • 提交 4 file A: [-----] file B: [...+ ]
  • 提交 3 file A: [+++++] file B: [... ]
  • 提交 2 file A: [-----] file B: [..+ ]
  • 提交 1 file A: [+++++] file B: [++ ]

在这种情况下,提交 5、3 和 1 的文件 A 是相同的。

这就是我想要的: 所以我想把它压扁。

  • 提交 5 file A: [.....] file B: [......]
  • 提交 4 file A: [.....] file B: [.... ]
  • 提交 2 file A: [.....] file B: [... ]
  • 提交 1 file A: [.....] file B: [.. ]

差异将是:

  • 提交 5 file A: [.....] file B: [....++]
  • 提交 4 file A: [.....] file B: [...+ ]
  • 提交 2 file A: [.....] file B: [..+ ]
  • 提交 1 file A: [+++++] file B: [.. ]

有没有办法做到这一点。

编辑:也许我的问题不是很清楚。我知道如何进行交互式变基和壁球。更重要的是,我只想“压缩”文件 A 的无效更改,同时保留文件 B 上的更改。(这样做会导致提交 3 什么都不做,因此将其删除。)

我面临的“正常”rebase 的问题是,如果我只是压缩 1-5 的所有提交,我最终会得到我想要的文件 A 的结果,但是对文件 B 的所有中间更改都丢失了.

添加了 diff 的表示,以便更好地描述情况。

解决方法

这是可以的。这是一个历史重写,这意味着如果有一个遥控器,它将涉及强制推送分支,如果该遥控器与其他用户共享,那么你需要先与他们协调,否则你冒着他们会撤消你的风险当他们尝试从您强制推送后会遇到的错误中恢复时会发生变化。您可以在 git rebase 文档中的“从上游 rebase 恢复”下找到有关强制推送到共享存储库的问题的更多信息。


所以在像你的例子这样的小/简单情况下,你可以使用交互式 rebaes 来做到这一点。

git rebase -i HEAD~4

这将加载带有提交 2、3、4 和 5 的变基“TODO”列表。(在您的示例中,您没有更改提交 1;如果您需要更改它,您可以使用 {{1} } 在有先前历史的情况下,或者在没有的情况下使用 HEAD~5 选项。)

“TODO”列表中的每一行都代表一个提交,并以一个命令开始,告诉 rebase 如何处理该提交。在提交 3 的行上,将命令从“pick”更改为“squash”;这会将提交 2 和 3 的更改合并为一个提交。在提交 4 的行上,将命令从“pick”更改为“edit”。保存并退出编辑器。

当 rebase 准备好重写提交 4 时,它将暂停并让您在继续之前应用更改。拉取文件A的正确版本

--root

然后完成rebase

git checkout HEAD^ -- path/to/file_A
git add .

您可以从 rebase 文档页面获取有关所有交互式 rebase 选项的信息。 (还有其他方法可以在简单的情况下获得相同的效果;但在适用于小型/简单用例的方法中,git rebase --continue 是最适合目的的 IMO。)

此过程有点手动,对于包含合并或可从多个分支(或标签或其他引用)访问的更复杂的历史记录,它会遇到问题。在这些情况下,您可以使用 rebase -i。这是一个相当复杂的工具,所以有一些学习曲线。但它确实有不错的文档。

,

1.重新开始:

git reset {commit 1 HASH}

并根据需要重做提交。

2.有一个新的提交来撤销你之前的提交

 git revert {commit 1 HASH}
  1. Squash 提交在这里输入代码

    git rebase -i {commit 1 HASH}

如果您对 git-rebase 不是很满意,请不要担心。压扁 提交是一种非常简单的技术,可以通过交互式实现 git-rebase 交互式 rebase 将打开编辑器。你可以 看看 rebase -i 如何进行最后三个提交。并注意 它拥有的选项数量。让我们只专注于壁球。 作为 前面提到过,让我们将其设为单次提交。您可以看到我们将最后两次提交标记为壁球。您可以使用 squashs 来标记对压缩的提交。

Please continue following this tutorial on this page for squashing commits,it is very explanotry

我建议选择选项 1。重新开始,但这是您的选择。

,

将有多个交互式变基。总而言之,您应该在交互式 rebase 时编辑 commit 4commit 5。让我解释一下:

您已经发现压缩 commit 2commit 3 是第一步。当我们这样做时,提交历史的开始将类似于第一次交互式 rebase 之后:

  • 提交 2 file A: [.....] file B: [... ]
  • 提交 1 file A: [.....] file B: [.. ]

好吧,让我们分析一下场景。您的 file B 更改将被保留,与 commit 4commit 5 相同。但是,我们需要去掉 file A 更改。在这里,我们将从交互式变基中的 edit 选项获得帮助。

在交互式变基时,为 commit 4commit 5 选择 edit 选项。在编辑两个提交的状态时,将文件 A 更改与提交分开。因此,在第二次交互式 rebase 之后,示例历史记录将如下所示:

1--2--4A--4B--5A--5B

4A 仅包含文件 Acommit 4 的更改。然后最后rebase;将 5A 提交移动到 4A 提交旁边,并将两个提交压缩到 commit 2 中。和魔法,因为它们是相反的提交,它们会消失。在第三次交互式 rebase 之后,提交历史将如下所示:

  • 提交 5B file A: [.....] file B: [......]
  • 提交 4B file A: [.....] file B: [.... ]
  • 提交 2 file A: [.....] file B: [... ]
  • 提交 1 file A: [.....] file B: [.. ]

如你所愿。