这里我们假设一个场景:
- 我们有一个稳定的分支(
master)。 - 目前我们正在另一个分支(
dev)开发一个新的版本。 - 这个时候发现了一个bug需要紧急修复。
此时我们肯定不能舍弃dev分支的修改,也不能合并它的修改(因为该分支没有开发完成),这个时候比较好的做法是:
- 切换回
master分支,并新建一个分支。 - 在这个分支上进行修复,提交。
- 修复完成后,将这个分支合并到
master分支。
分支创建
首先我们创建一个开发分支(dev),并切换过去:
# 这个命令是创建并切换分支的合并命令
git checkout -b dev
此时分支情况:
dev分支完成了一次提交:这个时候dev分支领先
master分支一个提交了:
master分支,并创建新的分支(hotfix)来修复bug:
# 切换会master分支
git checkout master
# 创建并切换到hotfix分支
git checkout -b hotfix
# 修复bug并提交
# 省略修复过程
git commit -a -m 'fixed the bug'
此时我们位于hotfix分支,并领先master分支一个提交:
hotfix分支合并回master分支:
# 切换回master分支
git checkout master
# 合并hotfix分支修改
git merge hotfix
master分支上已经修复了bug,我们应该删除hotfix分支,因为它现在和master分支完全一样
git branch -d hotfix
git checkout dev
此时我们的dev分支和master分支已经分叉,因为master分支包含了hotfix分支的提交,而dev分支没有,你可以使用git merge master将 master 分支合并入 dev 分支,或者你也可以等到 dev 分支完成其使命,再将其合并回 master 分支。
合并分支
前面简单了用到了git merge命令,由于hotfix分支和master分支,节点没有分叉,所以合并只是移动了一下分支指向,现在dev分支和master分支有分叉节点,合并的情况稍微复杂一些:
# 在dev分支完成了一个功能,并提交
# 省略修复过程
git commit -a -m 'finished the title'
# 切换回master分支
git checkout master
# 合并dev分支开发的功能
git merge dev
合并成功后,会有一个合并提交,这里git的合并会计算两个分支的共同祖先以及两个分支的末端,来做一个简单的三方合并,最终的结果如图所示(执行命令git log --oneline --decorate --graph --all):
dev分支了,理由和hotfix分支删除一样,master分支已经包含了完整的dev分支内容
git branch -d dev
冲突分支合并
有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们,在合并它们的时候就会产生合并冲突。
我们创建一个conflict分支,并在该分支修改一个文件:
git checkout -b conflict
# 省略修改过程,请修改任一文件并提交
git checkout master
# 修改同一个文件,然后合并修改
git merge conflict
此时,我们可以看见,两个分支修改的文件出现了冲突,如下显示:
这里我们可以看到
HEAD到=====是当前分支的修改,也就是master分支,而======到>>>>> confilct是conflict分支的修改。这里我们需要确认保留哪些内容,你可以只保留master分支,也可以只保留confilct分支,甚至两个分支都保留,但是,请一定把git标记的冲突符号去掉。最终,合并完成:
分支管理
显示所有分支(*代表当前分支):
git branch
显示所有合并到当前分支的分支:
git branch --merged
显示所有未合并到当前分支的分支:
git branch --no-merged
删除分支:
git branch -d testing
由于testing分支没有合并到当前分支,也就是master分支,所以无法直接删除。可以通过git branch -D testing强制删除。
这里有一点需要注意,git判断是否完全合并是基于你当前所在的分支。用上面的情况来说,现在我们在
master分支,testing分支没有合并进来,所以无法删除。此时可以删除dev和conflict。如果我们切换到testing分支,此时已经另外三个分支都没有合并到testing分支,所以无法直接删除任何一个分支。