@[TOC]
一、引言
上一篇文章Git 系列 1:提交修改到远程仓库——详尽版 中的最后一部分,提到了分支合并的知识。这次,我们就来详细的聊一聊有关分支管理的知识。
二、分支的实质
在经过3次提交后,分支图如下:对于上图,我们可以这么解释:
- 黑色圆角矩形分别指的是提交记录C1,C2,C3
- 除了第一次提交,每个提交记录可以有一个或多个指向上一次提交的指针
- 蓝色方框指的是master 分支
- master 分支指向最后一个提交记录
那么master 分支究竟是什么呢?它可不可指向其他提交记录?
2.1 实质
实质上,master 就是一个指针,指向最后一个提交记录;它是随着commit 提交的变化而变化的。当我们再次提交时,master 分支就会立即指向这个提交记录,如下图所示:
2.2 存放位置
Git 仓库的所有分支文件都存放在
.git/refs/heads
文件夹中,其中一个文件就是一个分支。

我们来看一下master 文件中的内容:

可以看到,master 文件中存放的是一串字符,事实上,这串字符就是最后一次提交记录的sha-1 值。

两相对比,我们可以得出这么一个结论:master 分支是一个指针,指向的就是最后一次提交。
正因为如此,Git可以瞬间创建分支,并且成本极低。因为只需要新建一个文件,并且修改一段字符串,如此一来,效率岂能不高。
三、分支管理
3.1 查看本地所有分支
通过 git branch 命令可以得到当前仓库中存在的所有分支列表;当然,查看 .git/refs/heads 文件夹也是个选择。
git branch
运行结果:

可以看到,在 gitTest 仓库中共有两个分支:A 和 master 分支。其中,呈现绿色并且有 * 号在前的master 分支就是当前我们正处于的分支。如果不切换分支,那么,我们的所有操作都是基于master 分支进行。
3.2 创建新的分支
3.2.1 基于当前分支创建分支
这是比较常见的操作,可以通过 git branch branchName 命令执行。
例如,我想基于master 分支创建newBranch 分支,只需要输入以下命令
git branch newBranch
运行效果如下:

因为是基于master 分支创建分支,所有newBranch 分支将与master 分支一样指向最后一次提交。
3.2.2 基于指定commit 提交创建分支
通过命令 git branch branchName commitSha-1 命令可以创建一个基于sha-1 值为 commitSha-1的提交的分支。
例如,我想创建一个基于提交 4ca463ed9fc89210e2e0fa62ac412cd3d65c904d 的分支newB ,只需要输入以下命令
git branch newB 4ca4
注:对于sha-1值,有限的几位字符完全可以唯一标识指定内容,没有必要完整给出。
运行结果如下:
可以看到,newB 分支已经创建成功,并且在对应的commit 后也已经将该分支标识了出来。
查看该分支的提交历史
git log --pretty=oneline
运行结果如下:
可以看到,因为newB 分支是基于4ca4 提交创建的分支,因此该分支只有 4ca4 及之前的提交。
3.2.3 基于储藏创建分支
这个知识点将在以后提到,具体的命令与基于commit 创建分支相似。
3.3 删除分支
通过命令 git branch -d branchName 命令可以删除指定的分支。
例如,我想删掉 newBranch 分支,只需要输入以下命令:
git branch -d newBranch
如果一个分支未进行合并,Git 可能会阻止对它的删除,不过也可以强制删除,命令如下:
git branch -D newBranch
使用该命令,将强制删除分支newBranch,无论其是否被合并。
3.4 切换分支
通过命令 git checkout branchName 命令可以切换到对应分支。
例如,我想切换当前分支到newB 分支上,只需要输入以下命令:
git checkout newB
运行结果如下:

3.5 创建并切换分支
使用命令 git checkout -b branchName 命令可以创建一个新的分支并切换到对应分支上。
例如,我想创建并切换到 newCC 分支上,只需要输入以下命令:
git checkout -b newCC
运行结果如下:

事实上,我们也可以使用git switch 命令来代替 git checkout 命令。
git switch -c newCC
使用gti switch -c branchName 命令也可以做到创建并切换分支的效果。
3.6 合并分支
3.6.1 不禁用Fast forward模式
在上篇文章Git 系列 1:提交修改到远程仓库——详尽版 中,我们已经了解了什么是Fast forward 模式,在这里就不再做介绍了。
通过git merge branchName 命令可以将对应分支合并到当前分支中。
例如,我的当前分支是newCC ,我想将A 分支合并到newCC 中,只需要输入以下命令:
git merge A
运行结果如下:

因为newCC 分支是新创建的,还没有产生提交,因此,本次合并为快速向前合并。
3.6.2 禁用Fast forward模式
通过命令 git merge --no-ff branchName 命令可以禁用Fast forward 模式。
例如,我当前分支为newB ,我想将A 分支合并到newCC 中,只需要输入以下命令:
git merge --no-ff A
使用该命令将进入类vim 的编辑模式,主要是输入提交信息。
通过git merge --no-ff -m "message" --no-ff branchName 命令可以在禁用Fast forward 模式的同时添加提交信息。
git merge --no-ff -m "merge with no-ff" --no-ff A
3.7 撒销合并
通过git reset --hard HEAD 命令可以回到合并前的版本。
git reset --hard HEAD
3.8 其他操作
对于分支,其实还有好多命令可以学习。在这里,就再列举两个。
3.8.1 分支重命名
通过命令git branch -m oldName newName 可以修改对应分支的名字。
例如,我想把A 分支修改为xi ,只需要输入以下命令:
git branch -m A xi
运行结果如下:

可以看到,A 分支已经不见了,取而代之的是xi 分支。
3.8.2 查看远程分支
通过命令git branch --remote 可以查看远程仓库的所有分支。
git branch --remote
运行结果如下:

可以看到远程仓库中并没有我们刚刚创建的分支。
3.9 推送本地分支到远程
通过git push origin branchName 命令可以将本地分支推送到远程仓库。
例如,我想推送newB 分支到远程仓库,只需要输入以下命令:
git push origin newB
运行结果如下:
可以看到,远程仓库中已经拥有newB 分支了。
3.10 分支的分类
当在实际应用开发中,特别是比较复杂的项目,Git不可能只存在一个分支。比如主分支存放当前线上稳定版代码,还有正在进行测试的非稳定版本分支,或者还有正在开发新功能的分支。
开发建议Git 有如下分支(不是固定,仅供参考):
(1)master(2)develop(3)hotfix(4)release(5)feature
3.10.1 master分支
此分支通常用来存放项目的稳定版本,主要特点如下:
(1).内容来源主要是分支合并过来,不推荐开发者直接commit提交。
(2).由于master分支可以是稳定版本,可以随时上线,所以通常版本标签都是打在master分支各个提交之上。
3.10.2 develop分支
develop开发分支通常和feature特征分支配合使用,它是所有feature特征分支的基础。当在feature分支中测试完新开发的功能后,可以将其合并到develop分支。
3.10.3 hotfix分支
当出现紧急问题,比如master线上分支出现代码问题,可以在此分支中进行修补,修补之后然后再合并到master分支。
特别说明:在合并到master主分支的同事,还要合并一份到develop分支,否则之后将develop合并到master时候,可能会导致修复的问题复现。
3.10.4 release分支
当develop分支开发到自认为足够稳定的状态,将此分支合并到release分支(在此分支进行上线前的最后测试)。最后测试完成后,再合并到master分支和develop分支。合并到master分支是非常好理解的,因为要上线运行。合并到develop是因为release分支后续可能还会发现问题,所以要将与develop分支同步,以防止以后develop再合并到release分支出现问题。
3.10.5 feature分支
此分支作用其在介绍develop分支的时候已经涉及,在feature进行新功能的开发,开发完成后再合并到develop。
最后,再给大家推荐一个学习git 命令的网站:
Git Community Book 中文版
至此,本文结束。我是陈冰安,一个Java学习者。欢迎关注我的公众号【暗星涌动】,愿与你一同进步。
网友评论