Git 压缩提交到功能分支上,并可以';I don’我现在没有一个干净的归并

Git 压缩提交到功能分支上,并可以';I don’我现在没有一个干净的归并,git,squash,git-squash,Git,Squash,Git Squash,好的,我遇到了一点麻烦,因为我挤压了一堆提交,我想知道是否有办法从中恢复过来。这就是发生的事情 我们从这里开始: D (mybranch) / A--B--C (master) 这两个分支机构都开展了工作: D--E--F (mybranch) / A--B--C--G--H (master) D--E--F--H'--I--J--K (mybranch) / \ A--B--C--G--H--L--M--N--O (master) 合并了从mast

好的,我遇到了一点麻烦,因为我挤压了一堆提交,我想知道是否有办法从中恢复过来。这就是发生的事情

我们从这里开始:

  D (mybranch)
 /
A--B--C (master)
这两个分支机构都开展了工作:

  D--E--F (mybranch)
 /
A--B--C--G--H (master)
  D--E--F--H'--I--J--K (mybranch)
 /         \   
A--B--C--G--H--L--M--N--O (master)
合并了从
master
mybranch
的更改(不幸的是,此处被挤压,因此B、C、G和H在
mybranch
上被合并为一个提交H'):

两个分支机构都开展了工作:

  D--E--F (mybranch)
 /
A--B--C--G--H (master)
  D--E--F--H'--I--J--K (mybranch)
 /         \   
A--B--C--G--H--L--M--N--O (master)
现在我想把从
mybranch
master
的更改合并回去,我收到了大量的冲突,说相同的文件都被这两个修改了

关于我现在可以尝试做些什么,从
mybranch
master
进行干净的合并,有什么建议吗

更新1

这是git日志的输出

>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

我怀疑历史并非你所想象的那样,从
master
mybranch
的变更合并在某种程度上没有正确完成

最初的合并是痛苦的,有很多冲突和修正吗?如果不是,我就把它扔掉,从头开始

git checkout -b mybranch_test F
git rebase --onto F H' mybranch_test
不需要等待,您只需执行git checkout myrbanch;git rebase——交互式F并删除
H'
commit

这应该很容易测试,git可以免费尝试这样的东西,所以试试吧

这一切都是基于这样一个假设,即
H'
合并没有引入导致冲突的重大更改,这可能是真的,也可能不是真的。

挤压合并根本不是合并,因此此绘图在几个重要方面是错误的:

  D--E--F--H'--I--J--K (mybranch)
 /         \
A--B--C--G--H--L--M--N--O (master)
。。。但幸运的是,它给了我我们需要知道的一切,让我知道如何尽可能轻松地处理这件事

首先,您说
H'
是从master到
mybranch
的挤压合并。
\
可能应该是
/
(我们希望“以后”提交位于“以前”提交的右侧),但它实际上根本不应该表示合并,并且可能应该以不同的名称命名

因此,以下是我将如何重新绘制图形片段(尽我所能正确地处理),在使用之前,您需要仔细检查所有这些内容:

然后从
pick
列表中明确删除commit
BCGH'
。这将要求Git选择每个提交
D
E
F
I
J
K
(按照该顺序,除非您也重新排序
选择
行):

请注意,
tempbranch
没有来自
master
的提交的
BCGH'
副本,并且在其他方面基本上与我们在master的提示上重新设置时得到的相同。2制作此特定副本的目的是获取与此新提交相关联的源代码树
K'
,因为现在我们可以运行:

$ git merge master
要在不受
BCGH'
干扰的情况下进行新的(尽管是临时的)合并提交
T

  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
$ git checkout mybranch
$ git merge master
这会因冲突而失败,因此现在让我们通过丢弃整个合并结果并用临时合并
T
中的树替换它来解决所有冲突。请注意,您必须位于git树的顶层,以便
引用所有内容:

$ git rm -rf .
$ git checkout tempbranch -- .
第一步丢弃整个工作树(和索引/临时区域内容),第二步从
tempbranch
的tipmost commit创建一个全新的工作树(和索引内容),即commit
T

现在您可以提交结果了(当然,尽管首先仔细检查是明智的,但您可以在分支
tempbrack
上完成这一操作,然后再进行此操作)。一旦您提交,您将获得以下信息:

  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
剩下的是Git使用临时分支进行的合并,该分支省略了commit
BCGH'

更多选项,以及关于如何和为什么做任何事情的注释 还有其他方法可以实现这一点,例如从commit
F
开始创建一个新分支,从
master
到这个新分支进行真正的合并(而不是挤压“合并”),然后通过
K
选择
I
,从
master
执行另一个真正的合并

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

  • 如果你更喜欢这种方法
  • 如果对你来说更容易;和/或
  • 如果其他人有这些承诺,而你不想让其他人做更多的工作
最后,提交给您两件事:一个状态(一个工作树,加上元数据,如提交作者、日期和日志消息)和一个历史(在此提交之前提交了什么?)。其理念是尽可能多地做出承诺,以提供足够的状态和历史,使合作发展变得有意义和可行,而不是提供太多的状态和历史,从而模糊意义和阻碍合作发展


1“合并”的引号是因为挤压合并不是合并。合并是具有两个或多个父级的提交,这些挤压“合并”提交不会记录第二个父级:它们会丢弃密钥信息,这就是为什么如果您对它们不太小心,它们会在以后变得如此麻烦的原因


2我在这里的意思是,就承诺而言,这与我们重新设定基准时所希望的是一样的。当然,就相关的源代码树而言,它是不同的,因为它不包含在
B
C
G
H
L
M
N
O
中完成的任何工作。从
O
开始的重基从完成所有工作的源树开始。

您确定
H
-
H'
链接吗?它真的存在吗?以什么形式存在?你能执行
g吗
$ git checkout mybranch
$ git merge master
$ git rm -rf .
$ git checkout 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
$ git branch -D tempbranch