我是git命令的新手,最近遇到了git rebase命令。我怀疑为什么git rebase命令一个接一个地重放功能分支的提交而不是重放功能分支上的最新提交。
这是我在我工作的项目中的情景:
M1 --- M2 --- M3 --- M4
|
M2 --- F1 --- F2 --- F3
我们是4个开发项目的开发人员,我在M2点从上游/主站分叉项目。
我开始研究我的功能并开始添加提交。提交F1有一些基本代码。然后提交F2是提交F1的一些错误修复,同样,提交F3是F2的代码的错误修复,F3是我的最终功能准备代码。
与此同时,其他开发人员完成了他们的功能,他们的代码被合并到了上游/主人。现在我必须将我的代码放在他们的M4功能之上。现在下面的部分是我对git rebase的理解,我可能错了:
我检查了功能分支,并使用上游/主机进行了git rebase,这种功能将我的功能分支置于M4之上,并开始逐个重放我的提交(F1,F2和F3)。我在F1重播中遇到了冲突并解决了它们。由于F2是对F1的错误修复,我在同一个地方再次遇到类似的冲突并再次解决它们。最后,当F3重播时,我又在同一个地方遇到了类似的冲突。我解决了冲突,一切都很好。
但是不是重播提交F1,F2,F3,如果git试图只将我的功能分支的最后一次提交放在M4之上,那么我将只需要解决冲突中的一个。 [因为我在F3中的代码也会有F1和F2的代码]。那么为什么这些额外的重播。
我可能在这里遗漏了一些基本概念,请纠正我在做错思考的地方。谢谢!
您必须告诉Git压缩除最后一次提交之外的所有提交,以实现您只需要解决冲突一次的期望。
要执行此操作,请在签出功能分支时在M4
上启动交互式rebase:
git rebase -i M4
您将看到一个类似于以下内容的可编辑代码段:
pick 111111 F1
pick 222222 F2
pick 333333 F3
然后,您可以编辑此片段,告诉Git将F2
和F3
压缩到F1
,从而导致单个提交,代表您自分支以来的所有更改:
pick 111111 F1
squash 222222 F2
squash 222222 F3
F1
被提名为压缩的提交,因为这是命令的工作方式(即它将更改融合到先前的提交中)。
保存这些编辑,退出代码段,您应该只看到一个冲突解决步骤。
请记住,在挤压F2
和F3
时,你已经失去了那些明确的变化集。如果您希望保留它们,则无法在每个重播步骤中解决冲突。
Rebase就是一次将提交应用于另一个提交。
然后,提交[...]按顺序一个接一个地重新应用到当前分支。
因此,rebase实际上是在前一个提交的基础上合并一个提交。现在,与你在Git中可以做的other kind of merging进行比较和对比:
git checkout master
git merge feature
merge
命令完全符合您的要求:它在feature
中最新提交的master
分支中的最新提交相关的累积更改在单个操作中应用。这意味着您必须只解决一次所有冲突。
合并操作通常会导致在目标分支上创建合并提交;合并提交的目的是连接两行(或更多!)历史记录。因此,虽然常规提交只有一个父级,但合并提交自然会引用多个父级。
M1 --- M2 --- M3 --- M4 --- MF
| |
M2 --- F1 --- F2 --- F3
现在,合并操作不一定必须导致合并提交。如果您需要(这可能是您正在寻找的),您可以合并不同分支中发生的更改,同时仍然创建一个提交。
你可以创建一个所谓的squash merge:
git checkout master
git merge feature --squash
这里的区别在于,master
和feature
的组合变化记录在master
之上的单个提交中,从而产生如下历史记录:
M1 --- M2 --- M3 --- M4 --- MF
|
M2 --- F1 --- F2 --- F3
MF
包含来自M4
和F3
的组合变化,所有冲突得到解决。