(a)创建文件夹GIT_MERGE_TEST1后跟' git init'
(b)创建了一个新文件' a.txt' (并且只有1个文件)添加并提交给' master'
(c)创建分支' git checkout -b feature1 master '并修改了文件' a.txt'
(d)创建分支' git checkout -b feature2 master '并修改了相同的文件' a.txt'
然后尝试合并
(e)' git checkout master'然后是&g; git merge --no-ff feature2 '取得了成功,并拥有“大师”的内容。 +' Feature2'
但是,' git merge --no-ff feature1 '说'已经是最新的'
如何更改这两个文件?我很想知道它为什么不抱怨合并冲突?
答案 0 :(得分:1)
如果git无法确定哪个功能分支应该为整个文档的最终输出做出贡献,那么只会出现合并冲突,在这种情况下由人来决定。
以下是您可以遵循以查看效果的示例流程:
$ 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
为了强制合并冲突,在每次编辑时,文件都被更改为在每个提交点只包含单行“1”,“2”和“3”。
此时,如果您编辑a.txt,您会看到来自git的标记,告诉您它无法合并文件的这些部分(V形符号>>>>>
和<<<<<
显示每个部分的更改合并冲突的一面)。
git hist是一个别名:
hist = !sh -c 'git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short -${1:-20} ${2:-HEAD}' -
git冲突是正常的事情,它们只是指示对文件的公共部分的更改,并且有人必须指导git来决定常见更改的外观,然后添加该更改并将其作为合并提交的一部分提交
或者,如果您确定某个功能绝对正确,则可以使用策略强制合并。 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]
通过使用“我们的”策略,它强制文件在当前主服务器中保持相同的值(即feature2中的那个)。如果你盲目地使用它,这也是危险的,因为它将忽略合并另一侧对冲突部分的更改。 我从来没有在真实的情况下自己运行,并且总是手动解决冲突(只需编辑文件,通过删除V形文件整理它,修复它,以便两个功能都符合您的要求并将其添加回git并继续合并)。
你会想要试验一下,在我的例子中,文件只有一行,所以我无法真正合并这两个功能。通常,如果没有冲突部分,则不会发生冲突,并且git可以正常进行,因为功能分支的2个根提供了足够的信息来理解如何合并非重叠的更改。请参阅下面的示例。
当git停止并告诉你存在冲突时(如上面的示例所示),您必须强制执行策略,或让某人查看更改并手动解决冲突。如果这是代码更改(例如),您可能不想使用该策略,并且想要查看为什么双方都在更改公共部分,然后运行测试等。
只是为了表明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.
然后仅在文件中指示的每个要素分支中进行更改,例如:
功能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.
功能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.
然后在完成两个合并后,您将不会遇到合并冲突。正如我在上面提到的,因为每个特征分支都植根于同一个原始提交中,所以git可以计算出每个特征分别对文件做出贡献并且更改没有重叠,因此很容易合并它们。
只有git无法合理地确定要放入什么内容,因为更改是重叠的,您会收到合并冲突。此时,您必须转向进行更改的人并说出“将其排除”。
顺便说一句,--no-ff
标志只强制一个新的提交对象。您在第一次合并时不需要它,因为主人可以直接跳过。如果要保留功能更改的历史记录并将其与新提交对象合并回主服务器,则只使用该标志。当您发生合并冲突时,它将无法帮助您。你将不得不自己解决这些问题。