分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了 50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

但 Git 的分支是与众不同的,无论创建、切换和删除分支,Git 在 1 秒钟之内就能完成

关于分支可以看看这篇文章:实际项目中如何使用 Git 做分支管理

创建与合并分支

每次提交,Git 都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在 Git 里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

HEAD 指向当前分支, 当前分支是 master 则指向 master,是别的则指向别的。

一开始的时候,master分支是一条线,Git 用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

image-20200314170748516

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

当我们创建新的分支,例如dev时,Git 新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

image-20200314160149952

Gi t 创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

image-20200314162733687

所以 Git 合并分支也很快!就改改指针,工作区内容也不变!

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

image-20200314163042838

Git 鼓励大量使用分支:

查看分支:git branch

创建分支:git branch

切换分支:git switchgit checkout

创建+切换分支:git switch -cgit checkout -b

合并某分支到当前分支:git merge

删除分支:git branch -d

解决冲突

当 Git 无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。其中, git merge <brachname> 的结果或者 git status 的结果会搞所我们冲突的文件。

我们查看该文件,Git 用<<<<<<<=======>>>>>>>标记出不同分支的内容,我们修改冲突,然后提交。

解决冲突就是把 Git 合并失败的文件手动编辑为我们希望的内容,再提交。

git log --graph命令可以看到分支合并图。

分支管理策略

通常,合并分支时,如果可能,Git 会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git 就会在 merge 时生成一个新的 commit,这样,从分支历史上就可以看出分支信息。

--no-ff方式的git merge

git merge --no-ff -m "merge with no-ff" dev

image-20200314171437733

分支策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如 1.0 版本发布时,再把dev分支合并到master上,在master分支发布 1.0 版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

所以,团队合作的分支看起来就像这样:

image-20200314172118805

小结

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。