简体   繁体   English

GIT合并不适用于多个分支

[英]GIT merging does not work with multiple branches

(a) Created folder GIT_MERGE_TEST1 followed by 'git init' (a)创建文件夹GIT_MERGE_TEST1,后跟“ git init”

(b) Created a new file 'a.txt' (and only 1 file) added and commited to 'master' (b)创建一个新文件“ a.txt”(只有1个文件)并提交给“ master”

(c) Created branch ' git checkout -b feature1 master ' and modified the file 'a.txt' (c)创建分支' git checkout -b feature1 master '并修改文件'a.txt'

(d) Created branch ' git checkout -b feature2 master ' and modified the same file 'a.txt' (d)创建分支“ git checkout -b feature2 master ”,并修改相同的文件“ a.txt”

Then tried merging 然后尝试合并

(e) 'git checkout master' followed by 'git merge --no-ff feature2 ' was successful and has the contents of 'Master' + 'Feature2' (e)成功执行“ git checkout master”,然后执行“ git merge --no-ff feature2 ”,并且内容为“ Master” +“ Feature2”

But, 'git merge --no-ff feature1 ' says 'Already up-to-date' 但是,“ git merge --no-ff feature1 ”表示“已经是最新的”

How can I have the changes of both the files ? 如何更改两个文件? And I am curious to know why it did not complain about merge conflict ? 我很好奇,为什么不抱怨合并冲突呢?

You will only get a merge conflict if git cannot determine which feature branch should be contributing to the final output for the whole document, and it's up to the human to make the choice in this case. 如果git无法确定哪个功能分支应为整个文档的最终输出做出贡献,则只会发生合并冲突,在这种情况下,由人决定是什么。

Here's an example flow that you can follow to see the effect: 您可以按照以下示例流程查看效果:

$ git init
Initialized empty Git repository in /home/markf/so/.git/
$ vi a.txt
$ git add .
$ git commit -m '1'
[master (root-commit) d92b23b] 1
 1 file changed, 1 insertion(+)
 create mode 100644 a.txt
$ git hist
* d92b23b 2015-08-29 | 1 (HEAD, master) [mark.fisher]

$ git checkout -b f1 master
Switched to a new branch 'f1'
$ vi a.txt
$ git add .
$ git commit -m '2 on f1'
[f1 1db4fed] 2 on f1
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git checkout -b f2 master
Switched to a new branch 'f2'
$ git hist
* d92b23b 2015-08-29 | 1 (HEAD, master, f2) [mark.fisher]

$ vi a.txt
$ git add .
$ git commit -m '3 on f2'
[f2 807e4a7] 3 on f2
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git hist
* 807e4a7 2015-08-29 | 3 on f2 (HEAD, f2) [mark.fisher]
* d92b23b 2015-08-29 | 1 (master) [mark.fisher]

$ git checkout master
Switched to branch 'master'

$ git merge --no-ff f2
Merge made by the 'recursive' strategy.
 a.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git hist
*   d193d0a 2015-08-29 | Merge branch 'f2' (HEAD, master) [mark.fisher]
|\
| * 807e4a7 2015-08-29 | 3 on f2 (f2) [mark.fisher]
|/
* d92b23b 2015-08-29 | 1 [mark.fisher]

$ git merge --no-ff f1
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   a.txt

In order to force a merge conflict, at each edit, the file was changed to contain only the single line "1", "2", and "3" at each commit point. 为了强制进行合并冲突,在每次编辑时,文件被更改为在每个提交点仅包含单行“ 1”,“ 2”和“ 3”。

At this point, if you edit a.txt you will see markers from git telling you it couldn't merge those sections of the file (the chevrons >>>>> and <<<<< show the changed from each side of the merge conflict). 此时,如果您编辑a.txt,您将在git中看到标记,告诉您它无法合并文件的这些部分(人字形>>>>><<<<<显示了合并冲突)。

git hist is an alias: git hist是一个别名:

hist = !sh -c 'git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short -${1:-20} ${2:-HEAD}' -

git conflicts are a normal thing, they just indicate changes to common sections of a file, and someone has to guide git into deciding how the common change should look, and then add that change and commit it as part of the merge commit. git冲突是很正常的事情,它们只是指示文件公共部分的更改,因此有人必须引导git决定公共更改的外观,然后添加该更改并将其提交为合并提交的一部分。

Alternatively, if you're sure that one feature is absolutely correct, you can instead use a strategy to force the merge. 另外,如果您确定某个功能绝对正确,则可以使用一种策略来强制合并。 See these docs. 请参阅这些文档。

$ git reset --hard master
HEAD is now at d193d0a Merge branch 'f2'

$ git st
On branch master
nothing to commit, working directory clean

$ git merge --no-ff f1 -s ours
Merge made by the 'ours' strategy.

$ git hist
*   689a6f5 2015-08-29 | Merge branch 'f1' (HEAD, master) [mark.fisher]
|\
| * 1db4fed 2015-08-29 | 2 on f1 (f1) [mark.fisher]
* |   d193d0a 2015-08-29 | Merge branch 'f2' [mark.fisher]
|\ \
| |/
|/|
| * 807e4a7 2015-08-29 | 3 on f2 (f2) [mark.fisher]
|/
* d92b23b 2015-08-29 | 1 [mark.fisher]

By using an "ours" strategy, it forces the file to stay as the same value in current master (ie. the one in feature2). 通过使用“我们的”策略,它会强制文件在当前主文件中保持相同的值(即Feature2中的文件)。 This is also dangerous if you use it blindly, as it will ignore changes from the other side of the merge for sections that are in conflict. 如果您盲目使用它,这也很危险,因为对于冲突的部分,它将忽略合并另一侧的更改。 I have never ever run this myself in a real situation, and have always manually resolved the conflict (just edit the file, tidy it up by removing the chevrons, fix it so both features are as you want them and add it back into git and continue the merge). 我从来没有在真实情况下亲自运行过,并且总是手动解决了冲突 (只需编辑文件,通过删除人字形来整理文件,对其进行修复,以使这两个功能都如您所愿并将其重新添加到git和继续合并)。

You will want to experiment with this, in my case, the file only has a single line, so there's no way I can truely merge both features. 您将要对此进行试验,在我的情况下,文件只有一行,因此我无法真正合并这两个功能。 Normally if there's no conflicting section, there will be no conflict and git can proceed fine as the 2 roots of the feature branches give it enough information to understand how to merge the non-overlapping changes. 通常,如果没有冲突的部分,就不会有冲突,并且git可以进行得很好,因为功能分支的2个根提供了足够的信息来了解如何合并不重叠的更改。 See below for an example. 参见以下示例。

When git stops and tells you there's a conflict (as in my example above), you either have to force it with a strategy, or have someone review the changes and manually resolve the conflict. 当git停止并告诉您存在冲突时(如上述示例所示),您必须采用策略强制实施,或者让某人查看更改并手动解决冲突。 If this is a code change (for example) you probably don't want to use the strategy and do want to review why both sides were changing the common sections, and then run tests etc. 例如,如果这是代码更改,则您可能不想使用该策略,并且想查看为什么双方都更改了公共部分,然后运行测试等。

Just to show that git isn't completely insane, if you started with a file like this: 只是为了表明git并不是完全疯狂,如果您从这样的文件开始:

This is a common file
The top section is in both features and won't change.
The bottom section also will not change.

# This section should be changed by feature 1:

# This section should be changed by feature 2:

# This is the common bottom section
Hello, I am at the bottom.

and then only put changes in each feature branch where indicated in the file, eg: 然后仅在文件中指示的每个功能分支中进行更改,例如:

feature 1 edit: 功能1编辑:

...
# This section should be changed by feature 1:
This is a change from feature 1

# This section should be changed by feature 2:

# This is the common bottom section
Hello, I am at the bottom.

feature 2 edit: 功能2编辑:

...
# This section should be changed by feature 1:

# This section should be changed by feature 2:
This is a change from feature 2

# This is the common bottom section
Hello, I am at the bottom.

then you will get no merge conflict after doing both merges. 那么您将不会发生合并冲突。 As I mention above, because each feature branch is rooted in the same original commit, git can work out that each feature contributed to the file separately and the changes were not overlapping, and thus merges them easily. 正如我上面提到的,由于每个功能分支都植根于同一原始提交中,因此git可以算出每个功能分别对文件做出了贡献,并且更改没有重叠,因此可以轻松地合并它们。

It is only where git cannot sensibly determine what to put in because the changes are overlapping that you get the merge conflict. 只有在git无法明智地确定要放入什么内容(因为更改重叠)的地方,您才会发生合并冲突。 At this point you have to turn to the person who made the changes and say 'sort this out'. 此时,您必须求助进行更改的人员,然后说“将其分类”。

By the way, the --no-ff flag just forces a new commit object. 顺便说一句,-- --no-ff标志只是强制一个新的提交对象。 You don't need it in the first merge that you do, as master can simply skip ahead. 在您进行的第一次合并中,您不需要它,因为master可以简单地跳过。 You only use that flag if you want to keep the history of the feature changes and have it merge back into master with a new commit object. 仅当您要保留功能更改的历史记录并使用新的提交对象将其合并回master时才使用该标志。 It will not help you when you have merge conflicts. 合并冲突对您没有帮助。 You are going to have to work those ones out yourself. 您将必须自己解决这些问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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