编辑过去提交的补丁

时间:2019-05-23 22:26:24

标签: git patch

我有一个以前的提交,在其补丁中包含一行,该行应是新提交的一部分。有什么办法可以将这条线从一个补丁移到另一个补丁?我正在尝试使用edit的{​​{1}}选项,但是无法更改补丁。这有可能吗?

2 个答案:

答案 0 :(得分:2)

您可以使用交互式资源库获得所需的内容。但是要注意一个关键点:提交不是补丁!提交是快照。即使git log -p 显示每个提交都是补丁,每个提交都具有您所有源代码的完整副本。

git log -p将提交显示为补丁(即使它们是快照)的原因很明显:说 commit#12只是一点点有用与提交#11有所不同,这里的区别是,而不是说:这里是提交#12,哈哈!因此,git log -p的工作方式是提取提交#11 提交#12,比较两者,然后向您显示发生了什么变化

您应该始终牢记这一点:提交是快照;但是Git喜欢比较两个快照,以显示它们之间的变化。您可以选择任意两个快照进行比较,但是git log -p和其他Git命令将自动使用两个相邻的父/子提交。 Rebase的复制也以这种方式工作:它将父级和子级进行比较,以查看要做什么。 (要比较您选择的两个提交,可以使用git diff并简单地命名两个提交进行比较。)

您可能还想知道,更改现有的提交在技术上是不可能的。 Rebase无法做到,也不会尝试。 git rebase所做的是复制旧的(有缺陷的)提交给新的和改进的。旧的提交会持续存在至少一段时间,如果您发现新的和改进的提交实际上是新的且更糟的,则可以将其退回。


话虽如此,这是使用交互式变基进行操作的方法。首先在需要改进的之前选择提交:

9abcdef  Subject of last commit
00afde4  Second to last commit that should have more stuff
badc0de  The commit that you dislike
ba5eba5  A commit you're OK with

在这里,提交badc0de是您要替换为新的和经过改进的提交。您希望将在{em> {em}中中进行的更改badc0de放入00afde4中,因此,您确实想用做得更少的其他提交替换badc0de,并{ {1}}和另一个执行不同的提交。然后,由于00afde4我的父母是9abcdef ,您将不得不将00afde4复制到新的改进的提交中,唯一的改进就是说我的父母是_______ ,通过制作9abcdef的新版本和改进版本来填补空白。

因此,现在您将运行00afde4并在编辑器中获得一个说明表,内容如下:

git rebase -i ba5eba5

(请注意,虽然pick badc0de The commit that you dislike pick 00afde4 Second to last commit that should have more stuff pick 9abcdef Subject of last commit end 开始并向后工作,但是git log的说明页面从您将要复制但更改的第一个提交开始,同时复制并向前移动 。)

由于我们假设您要将git rebase -i的行放入badc0de,因此现在应将三个00afde4命令中的这两个更改为{{1} },将pick(您要复制而无需更改)保留为edit命令。将说明表写回到其中的任何文件,然后退出编辑器以按照说明启动Git。

Git现在将复制提交9abcdef,但是会停止,以便您可以更改。从技术上讲,它实际上尚未复制 pick-只是进行了设置,以便您下一步执行 复制它,但在更复杂的情况下,例如我们将要看到,它会制作一个临时副本。您现在处于Git所谓的分离式HEAD 模式(根本不在任何分支上),并且执行的操作是运行编辑器来编辑应该不同的文件,进行更改,编写退出,然后退出编辑器。然后您badc0de每个这样的文件并运行:

badc0de

这将git add推到了这个分离的HEAD分支上,使git commit --amend 提交的副本现在变成了 good 提交。我们不知道它 会具有什么哈希ID,但为了引用它,我们将其称为badc0de

现在您拥有badc0de和父级1111111并具有所需的快照,请运行:

1111111

恢复交互式变基。 Git现在继续将ba5eba5复制到新的临时提交。这次确实必须制作临时副本,因为git rebase --continue 我的父母是00afde4 ,它需要一个说我的父母是{{1 }} 。 Git通过将00afde4与{em>比较 badc0de来制作此临时副本,以查看发生了什么更改,并对1111111进行相同的更改。我们不知道或不在乎这个新的临时提交将获得什么哈希ID,因为现在是时候再次启动编辑器并还原您上次丢失的行了。

如果您忘记了缺失的行,则可以轻松找到它们:例如,将00afde4(仍在您的存储库中)与它的父级进行比较(例如,badc0de)。使用编辑器将这些行放入工作树文件中。写出文件,退出编辑器。在这些文件上运行1111111,然后再次运行badc0de

Git现在将临时提交排除在外,进行新的提交,类似于git show badc0de,除了:

  • 它将git add列为其父项,并且
  • 它具有从git commit --amend恢复的行。

同样,我们不知道该 将具有什么哈希值,但在这里我们仅将其称为00afde4,以便我们进行讨论。

现在您可以再次运行1111111。此时,剩下的唯一指令是badc0de。因此,Git将2222222与它的父git rebase --continue进行比较,以查看更改了哪些内容,并对pick 9abcdef中的快照进行了相同的更改,并从中进行了新的提交。让我们将新副本称为9abcdef

Git现在具有:

00afde4

提交2222222确实与3333333相同,除了 3333333 (copy of) Subject of last commit 2222222 (copy of) Second to last commit (now with more stuff) 1111111 (copy of) The commit that you disliked (but now improved) ba5eba5 A commit you're OK with 我的父母是{{1 }}

由于复制现在已经完成,3333333会完成最后一个技巧:它使您的分支名称(无论名称如何)都标识副本9abcdef而不是原始的3333333,然后退出通过检出重新调整的分支来分离HEAD模式。因此,现在,如果您让Git查看从当前提交开始并向后工作的提交,您会看到2222222,然后是git rebase,然后是3333333,然后是9abcdef,依此类推。 。原始的提交(用新的和改进的副本替换的提交)是不可见的。它们仍然在您的存储库中 (大约一个月),但是现在很难找到它们。

答案 1 :(得分:0)

@karlosss git rebase -i commit-id-test,将在commit-id-test之后显示所有的commit-id和commit-msg,然后您可以编辑commit-msg,避免使用ctrl-c / v。

例如

pick 90b83db Replace QtMultimedia usage with 4A + gstreamer
pick f55e504 autobuild: introduce autobuild scripts