繁体   English   中英

如何判断壁球之后git分支是否已完全合并

[英]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 ,我们需要从DB的连接线(应该是箭头,但箭头字体不一定总是在每种浏览器上都正常工作):

A---D
 \ /
  B

但是我们没有。

下一个:

 $ git merge --squash another-branch 

这次合并操作包括将提交A (合并基数)与提交D ,以查看我们所做的更改,然后将提交A与提交Canother-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

请注意,新提交EC没有连接。 使用名称master ,Git从提交E开始,返回到D ,然后回到A 提交A 没有父级-毕竟这是我们做过的第一个提交-因此操作到此为止。 在此过程中找不到提交BC

为什么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-branchanother-branch请求都是“安全的”,因为从提交E开始,Git可以返回到提交D C D出发,Git可以返回到提交A B 因此,提交BC在分支master ,分别在new-branchanother-branch上。 删除名称 new-branch是安全的,因为提交Bmaster保护。 删除名称 another-branch是安全的,因为commit Cmaster保护。

承诺就是历史

从根本上讲,使用git merge --squash是告诉Git的一种方式: 我将丢弃一些提交/历史记录。 如果我们有:

...--A--B--C--D--E   <-- branch1 (HEAD)
            \
             F--G--H   <-- branch2

我们运行git merge --squash branch2 ,我们就当前分支 commit branch1是从DIFF相结合的结果CE -什么我们做了branch1 -with的差异从CH -什么他们branch2做了。 成功进行此新提交后:

...--A--B--C--D--E--FGH   <-- branch1 (HEAD)
            \
             F--G--H   <-- branch2

branch2 唯一明智的事情是删除它。 Git不会立即删除它,因为我们可能会对它的某些提交有其他计划-例如,也许我们想在其他分支中将GH樱桃拣选为新的提交-但最终我们应该杀死它。 但是我们新的FGH组合提交不能记住提交H的哈希,因此删除名称branch2 丢失提交FGH ; 因此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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM