![](/img/trans.png)
[英]Git - how to merge additional branch changes after branch has been 'merge --squash'ed
[英]How to tell if git branch has been fully merged after squash
将分支与--squash
合并时,git似乎不再能够确定分支是否已完全合并。 如何使用现有的git命令快速检查这一点?
要重现,请创建一个新的git存储库:
$ mkdir tmp
$ cd tmp
$ git init
$ echo "bla" > ans
$ git add .
$ git commit -m "First commit"
使用提交创建分支new-branch
:
$ git checkout -b new-branch
$ echo "blabla" >> ans
$ echo "blupp" > zwa
$ git add .
$ git commit -m "Commit on new-branch"
使用提交创建another-branch
:
$ git checkout master
$ git checkout -b another-branch
$ echo "test" >> ans
$ echo "three" > dra
$ git add .
$ git commit -m "Commit on another-branch"
合并:
$ git checkout master
$ git merge --squash new-branch
$ git commit -m "Squash new-branch"
$ git merge --squash another-branch
$ git mergetool
$ git commit -m "Squash another-branch"
$ git clean -f
两个分支都已合并。 我现在应该可以删除它们,对不对? 抱歉不行:
$ git branch -d new-branch
> error: The branch 'new-branch' is not fully merged.
> If you are sure you want to delete it, run 'git branch -D new-branch'.
$ git branch -d another-branch
> error: The branch 'another-branch' is not fully merged.
> If you are sure you want to delete it, run 'git branch -D another-branch'.
我可以使用选项-D
,但是通常其他人会合并我的东西,并且我想检查合并是否成功。 尝试使用git diff
:
$ git diff new-branch
$ git diff ..new-branch
$ git diff ...new-branch
$ git diff new-branch..
$ git diff new-branch...
上面所有的语句都产生一个非空的差异。 另一尝试:
$ git branch --merged
> * master
这两个分支未出现在合并分支的列表中,因此这也不起作用。
如何判断分支机构是否已合并?
您无法得到想要的东西。 您可能会得到几件可能不够好的东西。 特别是,如果您使用纯git merge
(如果需要,则使用--no-ff
),Git会记录提交 。 Git实际上并不关心文件,因为它与commit有关。 Git也不是非常在乎分支 :它仍然是关于commit的 。
使用您的示例,创建一个新的空存储库并在此时停止:
$ git commit -m "First commit"
您现在有了一个仅包含一次提交的存储库。 那个提交有一个很大的难看的哈希ID,但是我只用字母A
来代替它。 现在,存储库有一个命名分支master
,它保存此提交A
的哈希ID,因此我们可以像这样绘制它:
A <-- master (HEAD)
现在,我们运行您的第二系列命令:
$ git checkout -b new-branch
至此,我们有:
A <-- new-branch (HEAD), master
$ echo "blabla" >> ans $ echo "blupp" > zwa $ git add . $ git commit -m "Commit on new-branch"
这将创建新的提交B
,将名称new-branch
向前拖动:
A <-- master
\
B <-- new-branch (HEAD)
现在,我们使用您的第三系列命令(我将略微减少一些):
$ git checkout -b another-branch master
这将切换回提交A
,创建指向它的新分支名称,将HEAD
附加到新分支,并为我们提供:
A <-- another-branch (HEAD), master
\
B <-- new-branch
$ echo "test" >> ans $ echo "three" > dra $ git add . $ git commit -m "Commit on another-branch"
这将创建第三个提交C
,将名称another-branch
向前拖动到它:
C <-- another-branch (HEAD)
/
A <-- master
\
B <-- new-branch
现在我们来讨论两个merge
命令。 我们从开始:
$ git checkout master
这会将提交A
的内容提取到索引/临时区域和您的工作树中,并将名称HEAD
附加到名称master
:
C <-- another-branch
/
A <-- master (HEAD)
\
B <-- new-branch
$ git merge --squash new-branch
这会执行合并操作,其中包括将提交A
与提交A
(这没有表现出任何差异),然后将提交A
与提交B
(显示出一些差异)。 在这两个差异中发现的更改将合并在一起-不会发生任何冲突,因为一组更改是“什么都不做”-并且Git停止进行新的提交,因此我们需要:
$ git commit -m "Squash new-branch"
确实会进行新的提交。 我称这个为D
:
C <-- another-branch
/
A---D <-- master (HEAD)
\
B <-- new-branch
注意,提交D
与提交B
没有向后连接; 它仅记住现有提交A
的哈希ID。 您曾经使用过:
git merge --no-ff new-branch
要创建D
,我们需要从D
到B
的连接线(应该是箭头,但箭头字体不一定总是在每种浏览器上都正常工作):
A---D
\ /
B
但是我们没有。
下一个:
$ git merge --squash another-branch
这次合并操作包括将提交A
(合并基数)与提交D
,以查看我们所做的更改,然后将提交A
与提交C
( another-branch
的尖端提交),以查看它们的更改。 合并实际上是冲突的-我们都更改了文件ans
,并在文件末尾邻接了ans
行-因此大多数合并形式都将因冲突而在此处停止。 因此,您需要:
$ git mergetool
解决冲突,尽管我们可以使用以下命令在Shell中进行操作:
$ cat << END > ans
bla
blabla
test
END
$ git add ans
(您可以在END
之前的here-document部分中用所需的任何内容代替合并结果)。 这里的最后一步是提交合并。 由于这是一个挤压合并,而不是真正的合并,因此即使我们使用 commit C
进行合并,我们也没有向后链接到commit C
:
$ git commit -m "Squash another-branch"
这将产生新的commit / snapshot E
,因此我们来画一下:
C <-- another-branch
/
A---D--E <-- master (HEAD)
\
B <-- new-branch
请注意,新提交E
与C
没有连接。 使用名称master
,Git从提交E
开始,返回到D
,然后回到A
提交A
没有父级-毕竟这是我们做过的第一个提交-因此操作到此为止。 在此过程中找不到提交B
和C
git branch -d
失败 如果我们不使用git mergetool
,则不需要git clean
来清理其垃圾文件,因此我将跳过它并继续执行以下操作:
$ git branch -d new-branch > error: The branch 'new-branch' is not fully merged. > If you are sure you want to delete it, run 'git branch -D new-branch'.
这告诉您的是,从提交E
现在所在的位置)无法找到提交B
确实如此; 从E
到根的步行过程中,我们不会找到B
实际上,名称new-branch
是我们必须找到提交B
的唯一方法。 (请记住, B
代表一些我们永远无法猜到的随机哈希值ID。)如果确实删除名称new-branch
,则将丢失提交B
由于Git完全是关于提交的,因此丢失提交将是不好的。 Git不会丢弃名称,因此会丢失提交,除非您强行执行。
提交C
, 只能通过名称another-branch
。 git branch -d
命令将拒绝删除它,因为提交C
不是当前提交E
的祖先。
如果我们第一次使用常规的git merge
---- --no-ff
,因为否则Git会用快进而不是合并来作弊-此时,我们将有这张图:
C___ <-- another-branch
/ \
A---D--E <-- master (HEAD)
\ /
B <-- new-branch
现在,每个删除名称new-branch
和another-branch
请求都是“安全的”,因为从提交E
开始,Git可以返回到提交D
和 C
从D
出发,Git可以返回到提交A
和 B
因此,提交B
和C
在分支master
,分别在new-branch
和another-branch
上。 删除名称 new-branch
是安全的,因为提交B
受master
保护。 删除名称 another-branch
是安全的,因为commit C
受master
保护。
从根本上讲,使用git merge --squash
是告诉Git的一种方式: 我将丢弃一些提交/历史记录。 如果我们有:
...--A--B--C--D--E <-- branch1 (HEAD)
\
F--G--H <-- branch2
我们运行git merge --squash branch2
,我们就当前分支的 commit branch1
是从DIFF相结合的结果C
到E
-什么我们做了branch1
-with的差异从C
到H
-什么他们在branch2
做了。 成功进行此新提交后:
...--A--B--C--D--E--FGH <-- branch1 (HEAD)
\
F--G--H <-- branch2
与branch2
唯一明智的事情是删除它。 Git不会立即删除它,因为我们可能会对它的某些提交有其他计划-例如,也许我们想在其他分支中将G
或H
樱桃拣选为新的提交-但最终我们应该杀死它。 但是我们新的FGH
组合提交不能记住提交H
的哈希,因此删除名称branch2
将丢失提交F
, G
和H
; 因此git branch
要求我们强制执行此删除操作。
需要注意的是,如果有一些额外的承诺超出了 H
,发现,能够通过一些其他的名字:
...--A--B--C--D--E--FGH <-- branch1 (HEAD)
\
F--G--H <-- branch2
\
I--J <-- branch3
这个附加名称将使提交J
保持活动状态,并且J
将使I
保持H
,保持H
保持G
保持F
在这里, git branch -d branch2
仍然会从branch1
失败— commit H
不是commit FGH
的祖先—但是从branch3
运行时将成功。
随着时间的推移,关于何时必须强制删除分支名称的确切定义有所发展。 Git过去仅使用当前提交( HEAD
)和分支提示来确定删除是否安全。 现在,如果分支有一个上游设置,它还将考虑分支的上游设置。 如果分支提示提交是分支上游的提示提交的祖先,而不是当前提交的祖先,则Git现在将删除警告并删除分支。 提交是安全的-至少在当前情况下,它们受到上游名称的保护-但Git不确定您确实打算这样做,因此它会打印警告,其中包括存储在分支名称中的哈希ID,允许您使用该哈希ID还原分支名称。
您的分支已成功合并。 您收到以下消息错误:分支“ new-branch”未完全合并。 因为代码尚未推送到远程分支。 请在该git branch -d new-branch命令正常运行后推送代码。
-d选项代表--delete,仅当您已经将其推送并与远程分支合并后,它才会删除本地分支。 -D选项代表--delete --force,它将删除分支而不管其推送和合并状态如何,因此请谨慎使用该分支!
您只能使用以下命令打印合并的分支:
git branch --merged
因此,当您在master分支上时,如果在那里看到分支,则表示该分支已合并。
之所以看不到它,是因为那是“-壁球”的作用。 它根本不合并,包括更改,然后您提交。 令人困惑,但实际上没有合并。 一切都会发生,就像您在另一个分支中键入恰好类似的更改一样。
值得一提的是,“ mergetool”仍然有效。 我不知道
现在,它可以完美地与“ diff”一起使用,但是问题在于您包括了两个分支,并且在它上面有一个冲突。 所以你不会得到结果。
我也理解您正在寻找答案,我的建议是将您的master分支克隆到其他位置,对这些分支进行真正的合并,然后在实际的工作库和克隆之间进行区分。
那有意义吗? 然后您将确定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.