Git如何合并处理同时提交? [英] How do Git merges handle simultaneous commits?

查看:179
本文介绍了Git如何合并处理同时提交?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个包含两个分支的回购协议,每个分支都有独立的提交:

 分支提交
----- - -----------

final:egi
/ \
master:abcdfh-?

上图中的字母非常重要:即master和final正在开发中同时,并且必须保留两个分支中的提交。

将master合并为final,然后合并回到主人?或者将直接从final合并到master中保留之前的提交?



我知道可能会出现合并冲突。我更担心的是,我们不会丢失任何将final合并到它后面的master代码。

解决方案


将master合并到final是否更好(更安全),然后将它合并回master?或者直接从final合并到master保留之前的提交?

后者:直接合并到master从final保留之前的提交。

git与SVN等其他版本控制系统不同。对于不熟悉的情况,SVN会像桶一样对待分支 - 分支/桶是固定的(稳定),您必须小心移动桶之间的提交。在SVN中,在将'final'分支'重新集成'(伪合并)回'master'之前,你必须合并(复制)任何最近的'master'提交到'final'。 '重新整合'有效地将'最终'的提示复制到'主'的提示上,从而有效地用'最终'提示的确切副本取代'主'。你可能会失去'主'中任何未被合并(复制)到'最终'的提交。

像我说的,git是不同的。在git中,我喜欢将存储库树(提交)视为稳定的,而不是将它移动的分支 - 将分支想象为提交中挂起的小标签/装饰。



我将绘制你的树有点不同 - 事实上,我将在创建'i'之前绘制它:

  final 
|
e - g
/
a - b - c
\
d - f - h
|
master

现在让我们提交'i':

  final 
|
e - g - i
/
a - b - c
\
d - f - h
|
master

只有两件事发生了变化。 (1)暂时忽略分支装饰,我们看到新的提交'i'是从它的父提交'g'创建的,并且(2)最后的装饰从提交'g'移动到'i'。



让我们将final与master合并 - 也就是说,让我们更新master,使其包含来自final的更改:

  final 
|
e - g - i
/ \
a - b - c j
\ / |
d - f - h |
|
master

现在'master'分支装饰移动了。 '最后'分支装修继续存在。 'j'commit是一个由2个父母创建的合并提交:'h'和'i'。

但是如果我们将master合并到final中,那会怎样呢? ,更新了最终版,以便它包含来自主人的更改:

  final 
|
e - g - i |
/ \ |
a - b - c j
\ /
d - f - h
|
master

现在'最终'移动,'主'保持原位。请注意,合并是一个真正的合并 - 两个分支的更改均为提交'j'。 'j'是相同的,不管哪个分支合并到哪个分支中 - 唯一的区别是哪个分支装饰被移动。 (而那些分支装饰品很容易移动。)为了完整性,让我们将其他分支合并回第一个分支(合并成谁并不重要首先 - 只要我们这次在另一个方向合并)。请注意,只有装饰才会移动 - 不需要新的提交(在git行话中,它是'快速转发'),因为'j'已经包含两个分支的两组更改:

  final 
|
e - g - i |
/ \ |
a - b - c j
\ / |
d - f - h |
|
master

事实上,我们在几天后看看这棵树(我删除了'最终'分支 - 我完成了它):

  e  -  g  -  i 
/ \
a - b - cj - k - l - m
\\ / / |
d - f - h |
|
master

好的,你能从树中看出哪个分支最初是主这最初是'最终':egi或dfh?它有什么关系?



在git中,合并是真正的合并。没有桶,你不必像SVN那样在桶/分支之间移动提交。只有你正在发展的树,分支(装饰品)将你的地点加入书签。

Given a repo with two branches, each with independent commits:

Branch  Commits
------  -----------

final:        e-g-i
             /     \
master: a-b-c-d-f-h-?

The letters in the chart above are significant: ie, "master" and "final" were under development simultaneously, and commits in both branches must be retained.

Is it better (safer) to merge "master" into "final", then merge that back into "master"? Or will merging directly into "master" from "final" retain the commits there previously?

I understand that merge conflicts will likely arise. I'm much more concerned that we don't lose any of the code committed to "master" after merging "final" into it.

解决方案

Is it better (safer) to merge "master" into "final", then merge that back into "master"? Or will merging directly into "master" from "final" retain the commits there previously?

The latter: merging directly into "master" from "final" retain(s) the commits there previously.

git is different than other version control systems like SVN. For the unfamiliar, SVN treats branches like "buckets" - the branches/buckets are fixed (stable) and you had to be careful about moving commits between buckets. In SVN, you had to merge (copy) any recent 'master' commits into 'final' before you 'reintegrate' (pseudo-merge) the 'final' branch back into 'master'. 'Reintegration' effectively copies the tip of 'final' onto the tip of 'master', effectively replacing 'master' with an exact copy of the tip of 'final'. You could lose any commits in 'master' that weren't merged (copied) over to 'final' first.

Like I said, git is different. In git, I like to think of the repository tree (the commits) as stable and rather its the "branches" that move - think of branches as little labels/decorations that hang off of commits.

I'm going to draw your tree a little differently - in fact, I will draw it before commit 'i' was created:

              final
                |
            e - g
          /
a - b - c 
          \
            d - f - h
                    |
                  master

Now let's commit 'i':

                  final
                    |
            e - g - i
          /
a - b - c 
          \
            d - f - h
                    |
                  master

Only 2 things changed. (1) Ignoring the branch "decorations" for the moment, we see new commit 'i' was created from its parent commit 'g', and (2) the final "decoration" moved from commit 'g' to 'i'.

Let's merge final into master - that is, let's update master so that it includes the changes from final:

                  final
                    |
            e - g - i
          /           \
a - b - c              j
          \           /|
            d - f - h  |
                       |
                     master

Now the 'master' branch decoration moved. The 'final' branch decoration stayed put. The 'j' commit is a merge commit created from 2 parents: 'h' and 'i'.

But what if we had merged master into final instead - that is, updated final so that it includes the changes from master:

                     final
                       |
            e - g - i  |
          /           \|
a - b - c              j
          \           /
            d - f - h
                    |
                  master

Now 'final' moved and 'master' stayed in place. Note that the merge is a true merge - the changes from both branches are in commit 'j'. 'j' is the same no matter which branch merged into which - the only difference is which branch "decoration" got moved. (And those branch "decorations" are easily moved around.)

For completeness, let's merge the other branch back into the first branch (doesn't matter who merged into who first - as long as we merge in the other direction this time). Note that only the decoration moves - no new commit was necessary (in git jargon, it was 'fast-forwarded') because 'j' already contained both sets of changes from both branches:

                     final
                       |
            e - g - i  |
          /           \|
a - b - c              j
          \           /|
            d - f - h  |
                       |
                     master

In fact, let's look at the tree a few days later (I deleted 'final' branch - I was done with it):

            e - g - i
          /           \
a - b - c              j - k - l - m
          \           /            |
            d - f - h              |
                                   |
                                 master

Okay, can you tell from the tree which branch was originally 'master' vs which was originally 'final': e-g-i or d-f-h? Does it matter?

In git, merge are true merges. There are no "buckets" and you don't have to move commits between "buckets"/branches like you do for SVN. There's only the "tree" that you are evolving and the branches ("decorations") are bookmarking your place(s) in it.

这篇关于Git如何合并处理同时提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆