合并到qc和master时,合并分支之间的冲突

时间:2016-04-12 21:57:13

标签: git merge conflict rebase

我们分支master(我们不使用dev分支,不要问为什么)然后当QA为分支发出合并请求时,我们将它合并到qc分支,然后当它们完成测试时,我们将它合并到主分支。我们永远不会将qc合并为master或rebase从master到rebc的分支,尽管我们可以将分支快进到master(通过git merge --ff-only master或git rebase -i),尽管通常只需合并就可以了。 / p>

但是,分支(基于经理确定的任务)可以在不同的基础上启动,以不同的顺序合并到qc中,并以不同的顺序合并回主服务器。

问题是因为我们经常不得不为不同的功能更改相同的代码行(由于代码最初的结构方式和请求的更改,我们无法完全避免这种情况)所以我们几乎得到了合并冲突每周,当事情以不同的顺序合并到不同的分支时,我们最终可能不得不一遍又一遍地修复相同的冲突,或者将不同的更改合并到同一行(或者必须在不同的分支中分散新行)到不同的路线)。呼

为了消除相同的合并冲突修复,我们尝试将合并的分支重新绑定到QC(可能基于主提交回去),但是它以某种方式复制了qc和master上的提交;我们很好地将提交重新应用于掌握并丢失qc上的提交,因为我们可以将它合并回qc(我们会在更新时将master合并到qc中)。

我们如何避免这些重复的提交和冲突,有没有更好的方法来管理它?

有人提出了一件事:git rebase --onto master qc branch这对于那些需要从qc主控以防止多余冲突修复的分支是否可行?

1 个答案:

答案 0 :(得分:0)

重新提供重复提交,因为 是什么?:它是git cherry-pick操作的自动化系列,而git cherry-pick是提交复印机。

每个对象的标识都是其哈希值:例如251654c5f6f256fe6e23c2c85f1a70594aae00d4。哈希值是被哈希对象内容的校验和。对于提交对象,内容为:

  • 提交作者的姓名和电子邮件;
  • 提交者的姓名和电子邮件;
  • 提交的顶级源树的标识(即与此提交关联的每个文件的快照,由树对象的ID 表示);
  • 父提交ID列表(更多提交对象哈希);和
  • 提交的日志消息。

通常情况下,你选择提交的原因是稍微修改一下版本 - 事实上,如果你做了一点一点的完全相同的副本你就得到了原始提交的ID返回,因为同一组输入位的散列是相同的值。但是,通过一个樱桃挑选的提交,您通常会有一个稍微不同的源树,并且几乎总是有不同的父ID。

考虑这一点(经过如此轻微的修改,以打败垃圾邮件 - 电子邮件扫描程序)示例提交:

tree 3b2ac3530e713fc93aa93525bed9623679f99173
parent d2628061aa3b38b9f5dbdcd9136711a5a4ac3a1a
author Chris Torek <chris.torek@somewhere.com> 1459821791 -0700
committer Chris Torek <chris.torek@somewhere.com> 1459821791 -0700

distributed: clarify GUID uniqueness

Add the phrase {Doppelg\"anger commit} in a side-note.
Git and Mercurial allow them as long as they never meet.

我可以通过首先针对其父提交执行git diff来复制此提交(以显示我更改的内容):

diff --git a/distributed.tex b/distributed.tex
index 40fb7fd..6d8854b 100644
--- a/distributed.tex
+++ b/distributed.tex
@@ -41,8 +41,18 @@ to discover and exchange commits
 whenever you direct the system to synchronize your clone
 with a peer.
 In order to make this work correctly,
-these GUIDs really must be globally unique
-(across all repositories).
+these GUIDs really must be globally unique.\sidenote
+{More specifically, they must be unique
+among all clones of a given repository,
+\emph{including forks that may rejoin in the future}.
+This is a somewhat weaker requirement than true global uniqueness.
+For instance, if Alice makes a commit,
+but then destroys it without ever sharing it with anyone else,
+the destroyed commit is allowed to have the same GUID
+as some future commit,
+or a commit in an unrelated repository.
+You can think of this as allowing Doppelg\"anger commits:
+they may share a GUID only as long as they never meet.}
 It would not do
 for Bob to create a \emph{different} commit (in \git)
 or changeset (in \mercurial)

现在我有了diff,我可以检查一些其他提交,将diff作为补丁应用,并从结果中重新提交,重新使用日志消息。我将获得一个新的提交,具有相同的日志消息和对文件distributed.tex的相同效果,但(可能)不同的tree和(肯定)不同的parent,以及新的提交时间邮票,因此是一个不同的哈希。

这是一个挑选:将提交与其父级进行比较(将其转换为变更集),将该更改应用于其他位置,并从结果中进行新的提交。假设我们为提交的 重复此操作:

... <- B3 <- B4 <- B5   <-- branch-X
  \
   F6 <- F7 <- F8       <-- feature-Y

我们假设我们将F6复制到F8。请拨打F6F6'的副本,将其与原始版本区分开来。将F6'的父级设为B5,将F7'的父级设为F6',将F8'的父级设为F7',以便我们得到:

                      F6' <- F7' <- F8'
                     /
... <- B3 <- B4 <- B5   <-- branch-X
  \
   F6 <- F7 <- F8       <-- feature-Y

现在让我们做最后一件事。让我们删除当前卡在提交feature-Y上的标签F8,然后将其粘贴到F8'上:

                      F6' <- F7' <- F8'   <-- feature-Y
                     /
... <- B3 <- B4 <- B5   <-- branch-X
  \
   F6 <- F7 <- F8       [abandoned]

呃瞧,我们刚刚重新安排了 - 即。复制了 - feature-Y上的一些提交。新副本现在位于分支feature-Y上(在复制过程中,它们位于 no 分支上,或者更确切地说,在您处于&#34;分离的HEAD&时的特殊匿名分支上#34;模式)原始副本......好吧,还在那里。

我在这里标记了[弃],但是如果有其他分支或标记标签可以让您找到提交F8,您仍然可以看到所有原始提交。 git rebase命令移动feature-Y标签,但不会查看是否有其他标签使提交保持可见。

编辑:如果通过合并提交可以看到某些复制并随后放弃的提交,则情况也是如此,例如:

                       F6' <- F7' <- F8'   <-- feature-Y
                      /
.... <- B3 <- B4 <- B5   <-- branch-X
\  \
 \  F6 <- F7 <- F8       [abandoned]
  \               \
   C2 <--- C3 <-- C4     <-- branch-C

此处branch-C使提交C2C4可见,但C4是合并提交,使F8可见。现在,当您浏览存储库时,F8(来自C4的{​​{1}})和branch-C(来自F8')都会显示。

这种事情控制着你应该或不应该变革的时间和原因。由于rebase 副本提交,你需要确定以下两件事之一:原件真的会被遗弃,或者原件保存是可以的别处。 [结束编辑。]

feature-Y为您自动化的另一件事是选择提交复制。为什么我们决定通过git rebase来复制F6?为什么要包括这三个并排除所有其他?这就是F8的论据进入的地方。让我们回到这个建议:

git rebase

这是git rebase --onto master qc branch 的完全指定形式。在这种情况下,最后一个参数git rebase会使branchgit rebase开始。也就是说,额外的参数只是传递给git checkout branch。在那之后,额外的参数不再使用,所以我们可以这样做:

git checkout

代替。

命令的git checkout branch && git rebase --onto master gc 部分指定副本的位置。更具体地说,我们将--onto commit复制到F6,其新父级为F6'。如果使用B5,则指定此目标提交。 (在这种情况下使用分支名称--onto,只意味着在该分支上使用提示提交。)

在我们的案例中,剩余的一个论点mastergc调用git rebase的内容。

如果我们指定<upstream>--onto参数将有两个角色:它会命名目标提交,它会提供<upstream>提交的标识,它应该专门复制(然后复制更多提交,基于该ID)。但是,当我们使用git rebase时,我们已经指定了目标提交,因此剩下的参数只剩下一个角色:指定提交以避免复制。

这个&#34;承诺避免复制&#34;事情的作用可能有点棘手,包裹你的头。我们指定了一个特定的提交,但是rebase使用git本身一直使用的技巧。当我们将git指向某个提交时,我们可以要求它查看提交的

--onto

或者我们可以要求它查看提交及其所有父提交(又名 ancestry ):

$ git rev-parse c96a
c96af44caf036cf9f04d77c6146086a4ee422ceb

$ git rev-list c96a c96af44caf036cf9f04d77c6146086a4ee422ceb bca8213e6fda6fdf92b3a5fbc4ee59f755e04a9c 86ac01b3e1d771033e93af93366ace1b586d7c74 bc3fa7a3571231e334f6f06e5610e04227ef1f0b 执行一次提交操作,而rev-parse默认执行祖先变种,尽管rev-list非常灵活,位于心脏或至少肝脏或脾脏 - 许多git命令)。

Git&#39; rev-list选择带有祖先的rebase参数来提交排除,同时选择当前分支(如果你给它,请在检查之后)一个额外的参数)与祖先提交包括。无论剩下什么,在排除排除集后,都是要复制的提交。

使用<upstream>表单从其双重职责中释放--onto,以便在选择哪些提交以避免复制时更具选择性。但是,你仍然会复制提交,而这一切都需要。特别是,如果您使用rebase来复制(然后忘记其他人正在使用的提交的原件),他们还必须根据原件重新定义他们所做的任何工作。