如何在提交之间移动部分更改(大块)? [英] How do i move partial changes (hunks) between commits?
问题描述
如果我有两个提交,并且它们之间有很多提交,并且在两个提交中都有很多文件,那么如何最好将一个块从一个移动到另一个,例如:
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
中已更改,因此在B
,C
,D
等中也有所不同.但是,您需要一个新的历史记录,直到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屋!