如何在提交之间移动部分更改(大块)? [英] How do i move partial changes (hunks) between commits?

查看:70
本文介绍了如何在提交之间移动部分更改(大块)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有两个提交,并且它们之间有很多提交,并且在两个提交中都有很多文件,那么如何最好将一个块从一个移动到另一个,例如:

if i have two commits with a distance of many commits between them, with many files committed in both of them, how is it best to move a hunk from one to the other, for example:

在提交100中: 我有很多文件更改,并且在文件"aa.txt"中也有很多更改,还有这个: - aaaa - bbbb + cccc

in commit 100: i have many files changes and many changes in a file "aa.txt" and also this one: - aaaa - bbbb + cccc

10次提交之后,我又进行了一次提交,它更改了许多文件,还更改了"aa.txt": +dddd

10 commits later i have another commit changing a lot of files and also "aa.txt": +dddd

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

I want to move the line change -aaaa from the former to the later.

是否有任何CLI/UI工具可以帮助您轻松地做到这一点? (我显然对历史记录没有问题)

Is there any CLI/UI tool that helps you to easily do it? (i obviously have no problem with history rewriting)

推荐答案

交互式基础可能会起作用.但是,许多因素可能会使这一情况变得复杂.因此,您已经描述了很多:

It's possible that an interactive rebase would work. But a lot of factors could complicate this. So you've described this much:

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

某些行在A中已更改,因此在BCD等中也有所不同.但是,您需要一个新的历史记录,直到D才更改.所以你可以说

Some line was changed in A, and therefore also is different in B, C, D, etc. But you want a new history where it isn't changed until D. So you could say

git rebase --interactive A^ master

(其中A是先前具有更改的提交的SHA ID,请注意该ID末尾的^).在出现的文本编辑器中,您将看到一个待办事项"列表.第一行说要pick提交A;将其更改为edit.然后找到D的行(在此示例中为3以后的提交,但在您声明的示例中为10以后的提交).还要将其标记为edit.

(where A is the SHA ID for the commit that previously had the change, and note the ^ that goes at the end of said ID). In the text editor that comes up, you'll see a "todo" list. The first line says to pick commit A; change that to edit. Then find the line for D (which in this example is 3 commits later, but in your stated example might be 10 commits later). Mark it, as well, for edit.

重新设置将开始,但是在临时重新应用A之后,它将暂停,以便您可以编辑提交.

The rebase will start, but after tentatively re-applying A it will pause so you can edit the commit.

现在,如果您不希望手动/从内存中轻松撤消有问题的更改,则可以取消对该文件的更改暂存

Now, if reversing the change in question isn't something you can easily do by hand / from memory, then you can unstage the changes to that file

git reset HEAD^ -- aa.txt

然后将其再次置于补丁模式".

And then stage them again in "patch mode".

git add --patch -- aa.txt

系统将提示您如何处理每个更改请求.如果要删除的更改与其他更改显示在同一块中,则可以用e回答提示,然后编辑更改块(然后将不再要删除的行之前的-替换为).

You'll be prompted how to handle each change hunk. If the change you want to remove appears in the same hunk as other changes, you can answer the prompt with e and edit the change hunk (and then replace the - that's before the line you no longer want to delete with a ).

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

Now get your (staged) edits into the commit

git commit --amend

您从索引还原的更改仍在工作树中;摆脱它,并告诉rebase恢复工作.

The change you reverted from the index is still in the work tree; get it out of the way, and tell rebase to get back to work.

git stash 
git rebase --continue

随着rebase继续致力于提交D,介入的提交可能会发生冲突(如果它们对aa.txt的编辑过于接近您还原的更改).这些冲突应易于解决. (冲突的HEAD端将包含您不再删除的行;除了该行之外,您可能还希望冲突的另一端".)

As rebase continues working toward commit D, intervening commits could get conflicts (if they edited aa.txt too close to the change you reverted). These conflicts should be easy to resolve. (The HEAD side of the conflict will include the line you no longer deleted; other than that line, you likely want the "other" side of the conflict.)

提交D也可能会发生冲突.如果是这样,您的工作就很容易:只需保留冲突的另一"端即可解决该问题(包括删除有问题的行,因为这是您最终要执行此操作的位置).然后,当系统提示您分别编辑D(因为已在TODO列表中将其标记为edit)时,您可以立即将变基告知--continue.

Commit D might come up as a conflict, too. If so your job is easy: just resolve that one by keeping the "other" side of the conflict (including removal of the line in question, since this is where you finally want to do this). Then when separately prompted to edit D (because you marked it edit in the TODO list) you can just immediately tell rebase to --continue.

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

If D doesn't conflict, no big deal. You'll be prompted to edit it. Pop the stash you created earlier to re-apply the change you deferred from the A commit; add; commit --amend

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

Now the problems with this approach: If there are multiple refs that can reach A, this only updates the one (master in the above example). So for example

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

在这种情况下,branch仍然可以看到旧的历史记录.您最终会得到

In this case, branch still sees the old history. You end up with

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

您可以通过执行类似的操作来解决此问题

You could address this by doing something like

rebase --onto B' B branch

如果要处理很多分支,它将很快变老.

This will get old fast if there are a lot of branches to deal with.

另一个问题是,如果变基将遇到合并提交.在某种程度上,您可以使用--preserve-merges缓解此问题,但是如果合并是邪恶的"(即可以使用默认的合并策略自动解决,但以某种方式进行了编辑),它仍然会引起问题(可能默默地破坏历史记录) ).在这种情况下,您最能做的就是在各个步骤中重新建立分段基础,并仔细地复制合并.

Another problem would be if the rebase will encounter merge commits. To some extent you can use --preserve-merges to mitigate this, but it will still cause problems (possibly silently corrupting history) if the merges are "evil" (i.e. could be resolved automatically using the default merge strategy, but were edited in some way). In that case, the closest thing you could do would be to rebase in segments and reproduce the merges carefully at each step of the way.

这篇关于如何在提交之间移动部分更改(大块)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆