分支合并与合并冲突
1. 分支合并
快速合并
关于合并这块,文字描述起来可能没有示例+示图的方式效果好,下面我就已示例+示图的方式讲解分支合并。
场景:
创建本地仓库,添加
README.md
并提交$ git init git_branch $ cd git_branch $ echo "AAAA" >> README.md $ git add README.md $ git commit -m "init README.md"
创建
dev
分支,并切换到dev
分支$ git checkout -b dev
在
dev
分支上修改README.md
文件多次,并进行多次提交$ echo "bbbb" >> README.md $ git commit -a -m "update README.md add bbbb on dev branch" $ echo "cccc" >> README.md $ git commit -a -m "update README.md add cccc on dev branch" $ echo "dddd" >> README.md $ git commit -a -m "update README.md add dddd on dev branch"
切换到
master
分支,查看README.md
文件,看是否有在dev
分支上的修改$ git checkout master $ cat README.md AAAA # 没有在 dev 分支上添加的 bbbb cccc dddd
合并
dev
分支到master
分支,并查看历史提交$ git merge dev -m "merge dev to master" # 此时处于 master 分支 Updating 0ec51c7..75e171d Fast-forward (no commit created; -m option ignored) # Fast-forward 快速合并标识 README.md | 3 +++ 1 file changed, 3 insertions(+) $ git log --oneline --graph # 注意提交纪录的次数,以及左侧的 * 号 * 75e171d update README.md add dddd on dev branch * 059eabc update README.md add cccc on dev branch * f09db33 update README.md add bbbb on dev branch * 0ec51c7 init README.md
普通合并
普通合并和快速合并基本一样的,唯一的区别是在合并的时候添加
--no-ff
参数,表示禁用快速合并。因为普通合并与快速合并的示例几乎是一样的,唯一的区别在第 5 步,所以在讲述普通合并的时候, 前 4 步的操作就不在此赘述。
合并
dev
分支到master
分支,并查看历史提交$ git merge dev --no-ff -m "merge dev to master no-ff" Merge made by the 'recursive' strategy. README.md | 3 +++ 1 file changed, 3 insertions(+) $ git log --oneline --graph # 注意提交历史次数,以及左侧的 * 号 * 191b379 merge dev to master with no-ff |\ | * 75e171d update README.md add dddd on dev branch | * 059eabc update README.md add cccc on dev branch | * f09db33 update README.md add bbbb on dev branch |/ * 0ec51c7 init README.md
由以上两个日志比较可以发现,普通合并是将合并作为一次提交,而快速合并只是移动了一下
HEAD
指针,并不能分辨出有分支合并的迹象。看如下两图,再理解一下快速合并和普通合并的区别。
2. 合并冲突
在项目开发过程中,发生冲突是非常常见的事情,冲突步仅仅在分支合并中出现,在同一分支由于不同的人同时修改同一个文件的同一个位置,这样就容易出现冲突。下面就以分支合并出现的冲突为示例,演示一下冲突出现的情况以及解决冲突的过程。示例场景还是接着上面的示例继续。
在
master
分支,修改README.md
文件,如下面代码:$ git checkout master $ echo "This is master add" >> README.md $ git commit -a -m "master update content and commit" $ cat README.md AAAA bbbb cccc dddd This is master add
切换到
dev
分支上,修改README.md
文件,如下代码:$ git checkout dev $ echo "This is dev add" >> README.md $ git commit -a -m "dev update content and commit" $ cat README.md AAAA bbbb cccc dddd This is dev add
切换到
master
分支,将dev
合并到master
分支$ git checkout master $ git merge dev --no-ff -m "merge dev to master with no-ff" Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.
如上操作出现冲突,此时查看
README.md
$ git status # 查看出现冲突时的状态 On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) # 使用 add 命令标识解决冲突 both modified: README.md no changes added to commit (use "git add" and/or "git commit -a") $ cat README.md # 查看 README.md 的内容 AAAA bbbb cccc dddd <<<<<<< HEAD This is master add ======= # 发生冲突的分界线,上面属于一个分支,下面属于另一个分支 This is dev add >>>>>>> dev
修改
README.md
文件,标记已解决冲突,并提交,查看历史提交$ cat README.md # 查看修改后的文件 AAAA bbbb cccc dddd This is master and dev add $ git add README.md $ git commit -m "resolve conflict" $ git log --oneline --graph # 查看提交历史 * 8b3a448 resolve conflict |\ | * 9f539cc dev update content and commit * | cd20de2 master update content and commit * | 2312324 merge dev to master with no-ff |\ \ | |/ | * 75e171d update README.md add dddd on dev branch | * 059eabc update README.md add cccc on dev branch | * f09db33 update README.md add bbbb on dev branch |/ * 0ec51c7 init README.md