1

好的,所以我通过压缩一堆提交遇到了一些麻烦,并且想知道是否有办法从中恢复。这是发生的事情,

我们从这里开始:

  D (mybranch)
 /
A--B--C (master)

两个分支都完成了工作:

  D--E--F (mybranch)
 /
A--B--C--G--H (master)

合并从masterto的更改mybranch(不幸的是,这里被压扁了,所以 B、C、G 和 H 被合并到一个单一的提交 H' on 中mybranch):

  D--E--F--H' (mybranch)
 /         \   
A--B--C--G--H--L--M (master)

两个分支都完成了工作:

  D--E--F--H'--I--J--K (mybranch)
 /         \   
A--B--C--G--H--L--M--N--O (master)

现在我想合并从mybranchto的更改,master并且遇到大量冲突,说两者都修改了相同的文件。

关于我现在可以尝试做什么以从mybranchto进行干净合并的任何建议master

更新 1

这是输出git log

>git log --pretty=raw -n 1 d25ae411 (this is H')
commit d25ae411ffff9c59570437b50bfb89df7720af90
tree 3ffbb07a722fe70a66c64b257bb4a8c81235a027
parent aed6b526524db5c05bdb2518db18cf5ecfd8ef9d

>git log --pretty=raw -n 1 69c01f42 (this is H)
commit 69c01f42e73dad9f504c084de58b6a57f0d8506d
tree 323d506718f99d523fdd9529d8b6114a01657025
parent 7065134c416f7ecc6cf66c30ea5e019c625c9c19
parent 8170ca5ce1ce46df6b9f04d80cfad63b6f082b66
4

2 回答 2

1

“壁球合并”根本不是合并,所以这张图在几个重要方面是错误的:

  D--E--F--H'--I--J--K (mybranch)
 /         \
A--B--C--G--H--L--M--N--O (master)

...但幸运的是,它为我提供了我们需要知道的一切,让我知道如何尽可能轻松地处理这个问题。

首先,您说这H'master合并 mybranch. \可能应该是(我们希望“/稍后”提交位于“早期”提交的右侧),但它实际上根本不应该表示合并,并且可能应该以不同的方式命名。

所以,这就是我将如何重新绘制图形片段(无论如何我都可以正确地管理 -在使用它之前,需要仔细检查所有这些):

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master

此处命名的提交是提交BCGH'的壁球“合并” 1B--C--G--H,您已将其称为H'。它是原始四个提交中所有工作的副本

使用变基,省略壁球

您现在可能想要mybranch基于master. 这可能是最简单和最好的方法,尽管它确实意味着“重写历史”(假装您在 commit 之后开始工作O)。为此,请使用交互式变基:

$ git checkout mybranch
$ git rebase -i master

然后专门BCGH'pick列表中删除提交。这将要求 Git 挑选每个提交D, E, F, I, J, 和K(除非您还重新排序这些pick行):

  D--E--F----BCGH'--I--J--K   [will be abandoned]
 /
A--B--C--G--H----L--M--N--O   <-- master
                           \
                            D'-E'-F'-I'-J'-K'   <-- mybranch

使用合并,让 Git 完成工作

或者,如果您真的想合并,请创建一个的(但临时的)分支,从 commit 开始A,您可以在其中挑选相同的六个提交:

$ git checkout -b tempbranch mybranch~7  # this should start from A
$ git cherry-pick mybranch~7..mybranch~4 # pick D, E, and F
$ git cherry-pick mybranch~3..mybranch   # pick I, J, and K

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master
 \
  D'--E'--F'--I'--J'--K'      <-- tempbranch

请注意,tempbranch它没有BCGH'来自 的提交的副本,master否则与我们重新定位到 master 的尖端时得到的基本相同。2 制作此特定副本的目的是获取与此新提交关联的源代码树K',因为现在我们可以运行:

$ git merge master

进行新的(尽管是临时的)合并提交T,不受以下因素的干扰BCGH'

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master
 \                         \
  D'--E'--F'--I'--J'--K'----T   <-- tempbranch

如果我们从into进行真正的合并,这个新的合并提交T具有我们想要获得的源代码树。因此,现在让我们开始该合并,由于 commit 导致合并冲突失败:mastermybranchBCGH'

$ git checkout mybranch
$ git merge master

这会因冲突而失败,所以现在让我们通过丢弃整个合并结果并将其替换为临时合并的树来解决所有冲突T。请注意,您必须在此处的 git 树的顶层,以便.引用所有内容:

$ git rm -rf .
$ git checkout tempbranch -- .

第一步丢弃整个工作树(和索引/暂存区内容),第二步从最尖端的提交(tempbranch即 commit )创建一个全新的工作树(和索引内容) T

现在您可以提交结果了(尽管首先仔细检查它是明智的——当然,tempbranch您甚至可以在到达这里之前在分支上执行此操作)。提交后,您将拥有:

  D--E--F----BCGH'--I--J--K-P   <-- mybranch
 /                         /
A--B--C--G--H----L--M--N--O     <-- master
 \                         \
  D'--E'--F'--I'--J'--K'----T   <-- tempbranch

哪里P是正确的合并,使用来自T. 现在可以安全地tempbranch完全删除:

$ git branch -D tempbranch

剩下的就是 Git 使用省略了 commit 的临时分支进行的合并BCGH'

更多选项,以及关于如何以及为什么做任何事情的注释

还有其他方法可以解决这个问题,例如从 commit 开始创建一个新分支F,从这个新分支中进行真正的合并master(而不是壁球“合并”),然后挑选樱桃并I从.Kmaster

与任何其他方法相比,使用任何一种方法的唯一充分理由是:

  • 如果你更喜欢这种方法;
  • 如果对您来说更容易;和/或
  • 如果其他人有其中的一些提交,而您不想让其他人做更多的工作。

最后,提交给你两件事:状态(工作树,加上提交作者、日期和日志消息等元数据)和历史记录(在此提交之前有哪些提交?)。这个想法是根据需要进行尽可能多的提交,以提供足够的状态和历史来有意义并启用合作开发,而不会提供太多的状态和历史来模糊意义和禁用合作开发。


1 “合并”周围的引号是因为,壁球合并不是合并。合并是具有两个或多个父级的提交,并且这些壁球“合并”提交不记录第二个父级:它们丢弃关键信息,这就是为什么如果您对它们不太小心,它们会变得如此麻烦的原因。

2我在这里的意思是,在提交方面,如果我们要变基,我们想要的结果是一样的。当然,就相关的源代码树而言,它是不同的,因为它不包含在BCGHLMN或中完成的任何工作OO从完成所有工作的源树开始的变基。

于 2016-05-02T19:14:43.557 回答
0

我怀疑不知何故,历史不是你想象的那样,并且从masterinto的变化的合并mybranch不知何故没有正确完成。

最初的合并是否因大量冲突和修复而痛苦?如果没有,我会摆脱它并从头开始

git checkout -b mybranch_test F
git rebase --onto F H' mybranch_test

不用等待,您可以执行 agit checkout myrbanch; git rebase --interactive F并删除H'提交。

这应该很容易测试,并且使用 git 尝试这样的东西是免费的,所以试一试。

这一切都是基于这样的假设,即H'合并没有引入重大的引发冲突的变化,这可能是真的,也可能不是。

于 2016-05-02T15:28:20.287 回答