如何在提交之间移动部分更改(帅哥)?

时间:2017-07-12 13:27:37

标签: git

如果我有两个提交,它们之间有很多提交距离,并且在这两个提交中都有许多文件,那么如何将一个hunk从一个提交到另一个,例如:

提交100中的

: 我有很多文件更改和文件“aa.txt”中的许多更改,还有这一个: - aaaa - bbbb + cccc

10次提交后,我有另一次提交更改了很多文件,还有“aa.txt”: +dddd

我想将换行-aaaa从前者移到后者。

是否有任何CLI / UI工具可以帮助您轻松完成? (我显然没有历史改写的问题)

2 个答案:

答案 0 :(得分:4)

交互式rebase可能会起作用。但是很多因素可能会使这一点复杂化。所以你已经描述了这么多:

x -- x -- A -- B -- C -- D -- x -- x <--(master)

A中的某些行已更改,因此BCD等也有所不同。但您想要一个新的历史记录t改为D。所以你可以说

git rebase --interactive A^ master

(其中A是先前有更改的提交的SHA ID,并记下所述ID末尾的^。在出现的文本编辑器中,您将看到“待办事项”列表。第一行是pick提交A;将其更改为edit。然后找到D的行(在此示例中稍后是3次提交,但在您声明的示例中可能稍后会提交10次)。同时标记edit

rebase将会启动,但在暂时重新应用A后,它会暂停,以便您可以编辑提交。

现在,如果您无法通过手动/从内存轻松完成对问题的更改,那么您可以取消对该文件的更改

git reset HEAD^ -- aa.txt

然后以“补丁模式”再次登台。

git add --patch -- aa.txt

系统会提示您如何处理每个更改块。如果要删除的更改显示在与其他更改相同的块中,您可以使用e回答提示并编辑更改块(然后替换您不再需要的行之前的-使用删除。

现在将您的(暂存)编辑内容提交到提交

git commit --amend

您从索引中还原的更改仍在工作树中;把它弄出来,告诉rebase重新开始工作。

git stash 
git rebase --continue

随着rebase继续向commit D工作,干预提交可能会发生冲突(如果他们编辑的aa.txt太接近你还原的更改)。这些冲突应该很容易解决。 (冲突的HEAD方将包括您不再删除的行;除了该行之外,您可能还需要冲突的“其他”方。)

提交D也可能会出现冲突。如果是这样,你的工作很简单:只需通过保持冲突的“其他”方面来解决这个问题(包括删除相关行,因为这是你最终要做的事情)。然后,当单独提示编辑D时(因为您在TODO列表中将其标记为edit),您可以立即告知rebase --continue

如果D没有冲突,没什么大不了的。系统会提示您进行编辑。弹出您之前创建的存储,重新应用您从A提交中推迟的更改; add; commit --amend

现在这种方法存在问题:如果有多个引用可以达到A,则只会更新一个(上例中为master)。例如,

x -- A -- B -- C -- D -- x <--(master)
           \
            x -- x <--(branch)

在这种情况下,branch仍会看到旧历史记录。你最终得到了

x -- A' -- B' -- C' -- D' -- x <--(master)
 \
  A -- B -- x -- x <--(branch)

您可以通过执行类似

的操作来解决此问题
rebase --onto B' B branch

如果有很多分支要处理,这将会变得很快。

另一个问题是如果rebase会遇到合并提交。在某种程度上,您可以使用--preserve-merges来缓解这种情况,但如果合并是“邪恶的”(即可以使用默认合并策略自动解决,但是在编辑时,它仍然会导致问题(可能会默默地破坏历史记录))某种方式)。在这种情况下,你可以做的最接近的事情就是细分并在每一步中仔细地重现合并。

答案 1 :(得分:2)

使用git format-patch

导出更改

编辑所需的修补程序并使用applyam

应用它
$ git format-patch HEAD~10
$ git am ...

如果您想创建单个文件,可以使用--stdout并将其打印到文件中:

$ git format-patch master --stdout > changes.patch