【问题标题】:Git merging - What happens to the merged branch?Git 合并 - 合并的分支会发生什么?
【发布时间】:2024-01-08 23:41:01
【问题描述】:

我有一个关于 git 合并的问题。假设我的存储库中有两个分支(本地和远程):master 和 test。当我在测试分支上工作时,主分支被其他人更新了。在终端中,我写道:

git checkout master
git pull origin master

这会用最近添加的东西更新我的主分支,对吧?然后,我完成了我在测试分支中所做的事情。
如果我去终端写:

git checkout master
git merge test
git push origin master

这会将我的测试分支合并到我的主分支中,然后将更改推送到 github 正确(假设没有冲突)?我的问题是:测试分支会发生什么?它是否保持与合并前相同的方式?还是测试和主分支都变得相同?我现在应该这样做来更新测试分支吗?

git checkout test
git pull origin master
git push origin test

提前致谢。

【问题讨论】:

  • 它保持不变,除非你将 master 合并到 test git checkout test git merge master...
  • @n00dl3 如果我在将 test 合并到 master 时发生冲突,我在将新 master 合并到 test 时是否也会发生冲突?

标签: git github merge branch


【解决方案1】:

如果我去终端写:

git checkout master
git merge test
git push origin master

这会将我的测试分支合并到我的主分支中,然后将更改推送到 github 正确(假设没有冲突)?我的问题是:测试分支会发生什么?

什么都没有。

请记住,分支 names 只是(单个)提交的名称。为了绘制它们,我喜欢将提交本身绘制为圆形 o 节点,或者当我们需要讨论特定提交时,用大写的单个字母将它们连接起来:

...--o--o--o--o      <-- master
         \       
          o--o--o    <-- test

每个提交“指向”它的父提交——因此,如果我们给每个提交一个字母名称,并画出所有中间箭头,我们会得到:

...<-A<-B<-C<-D      <-- master
         \
          E<-F<-G    <-- test

分支名称mastertest 实际上包含两个分支的tip 的原始哈希ID。也就是说,如果您检查文件 .git/refs/heads/master1,您会在其中找到一个丑陋的 40 字符散列,a139fc7... 或其他任何内容。

实际上,master 指向提交Dtest 指向G。 commit D 指向 commit C,commit C 又指向B,以此类推;并提交G 指向F,它又指向E,又指向B(在这里用纯文本绘制箭头太棘手了,因为一些好的箭头绘制字体只适用于一些机器)。

当您在某个分支上并进行 new 提交时,Git 进行此提交的方式是将其父设置的新提交写入当前分支提示,然后一次新提交安全地在存储库中,用新提交的 ID 重写分支 name 文件。这使得分支名称指向新的提示。新 ID 无处可去,因此 other 分支名称不会发生任何变化。

一个合并提交有 两个 父母,所以当你 git merge test 并且它工作时,你会得到这个:

...--o--o--o--o---o  <-- master
         \       /
          o--o--o    <-- test

请注意,test 根本没有移动,但 master 已经移动了——并且新的合并提交指向两个不同的早期提交:master 的旧分支提示和(未更改的)提示test.


1没有保证该文件将来会存在,或保留在此位置或具有此格式,但现在,从今天的 Git 版本到 2.10,您通常会拥有该文件.

【讨论】:

  • 那么在这种情况下最好的方法是什么?删除分支test,然后新建一个?还是将主更改也拉到测试中?
  • 这取决于想用test做什么(或继续做,或不再做)。如果您的test 名称不在遥控器上(如果您从不推送它并且一开始就没有从那里获取它,那么就没有您用来与其他人协调的origin/test),决定权完全在你。否则,请与它的其他用户协商,以确定你们都喜欢什么。
  • @torek 因此,假设测试分支是本地的(从未被推送),在合并之后,当您推送更改时,测试分支也会被推送以维护 2 父级的引用节点?如果我删除它会发生什么?
  • 同样,如果您不指定名称,则默认为 当前分支。因此,如果您运行git checkout master; git merge test; git push,那么您现在正在运行git push origin master,因为您的当前分支master。所以您要求origin 将他们的master 设置为与您的master 相同。您的 master 标识了您刚刚进行的合并提交,因此这将创建或更新他们的 master,假设他们无论如何都不会拒绝您的请求。
  • @JohnnyBeltran:嗯,some 推荐这种变基直线技巧。其他人则发誓始终使用并保持合并。我认为应该使用对您和您的团队最有效的方法。 :-)