分支操作

分支(Branch)是Git中的一项重要功能,它允许你从主线分支(通常被称为master)开发的历史记录中创建新的开发路径。分支操作可以帮助你同时进行多个功能的开发,而代码不会互相干扰。这篇笔记我们介绍Git本地仓库中分支的使用。

查看分支

我们可以使用以下命令查看当前版本库中有哪些分支。

git branch

如下图所示,我们可以看到我们的仓库中有masterdev两个分支,其中*表示当前所在的分支。

创建和切换分支

创建一个分支需要基于一个已有的分支,假如我们当前位于master分支,下面命令基于当前分支创建一个新分支。

git branch test

如果我们想要切换到新创建的分支,可以使用以下命令。

git checkout test

分支切换完成后,我们可以看到以下提示。

删除分支

如果我们不再需要某个分支,可以使用以下命令删除它。

git branch -d test

有时,我们删除分支时可能看到类似如下的提示。

出现这个提示是因为要删除的分支包含了未合并到当前分支的提交,Git提示我们是否要强制删除这个分支。一般来说,如果我们确认所有需要的提交已合并,此时可以使用-D参数来强制删除。

merge 合并分支

合并分支

假设我们现在位于dev分支,我们对仓库内容进行了修改并提交,此时我们想要将dev分支合并到master分支,可以使用以下命令。

git checkout master && git merge dev

合并需要我们首先切换到目标分支,然后再执行合并操作。合并完成后,我们可以看到以下提示。

冲突处理

如果两个分支同时对一个文件做了有冲突修改(改动了同一行),则合并分支后,我们需要手动将冲突解决。下面是一个合并分支时发生冲突的例子。

此时使用git status命令查看工作区状态,我们可以看到Git提示我们手动对冲突进行处理。

我们可以使用Vim等编辑器查看文件的内容,Git帮我们将文件内容修改为了如下状态,其中<<<<<<< HEAD=======之间的部分是当前分支修改的内容,而=======>>>>>>> dev之间是dev分支修改的内容,这两次修改位于不同分支,它们改动了同一行,是冲突的,当合并分支时,我们必须手动解决冲突。

HiHiHi~
<<<<<<< HEAD
HoHoHo!
=======
HoHoHo?
>>>>>>> dev
Hi, Tom.
Hello, world!

我们编辑文件,并将其修改为我们想要的形式,例如下面。

HiHiHi~
HoHoHo!?
Hi, Tom.
Hello, world!

修改完成后,我们可以再次提交,这样冲突就顺利解决了。

git add --all && git commit -m "合并dev分支解决README.md文件的冲突"

此外,我们可以发现,Git处理冲突时会在冲突行添加一些标记,这可能无意间破坏了我们的代码。实际开发中,我们通常不直接使用命令行和Vim处理冲突,大多数集成开发环境(IDE)都提供了图形化的冲突解决工具,直接使用这些工具更加方便,不过我们还是要了解这些图形化工具底层究竟做了什么。

注意:同一个文件添加了不同的行,通常并不会引起冲突,Git能够自动处理这种情况。

rebase 变基

变基其实也是一种“分支合并”操作,但它和传统的分支合并不同,它是基于指定的分支基础将一组提交“移动”过去,简单来说就是将一个分支的提交应用到另一个分支上而不会创建新的提交,这和后面介绍的摘樱桃操作类似。由于变基本质上是提交的搬运而不是分支的合并,因此不会产生分支的合并记录,也不会在版本历史中体现出分叉的分支,变基合并后的分支仍是线性的。

下面例子中,我们从dev分支通过变基“合并”到master分支。

git rebase dev

如果没有冲突,输出例子如下。

如果存在冲突,冲突处理的方式和分支合并类似,只是提交冲突解决的方式和分支合并稍有不同。假设我们的冲突文件为README.md,我们需要将变更添加到暂存区,然后执行git rebase --continue命令。

git add README.md && git rebase --continue

当然,我们可以看到rebase其实就是起到类似于“美化”提交历史、提升提交历史可读性的作用,实际开发中如果你没有强迫症这种优化也不是特别必要,我们一般采用merge合并即可。

GitFlow工作流程

对于单人开发的小型项目,单分支模型其实已经足够应付了,但企业级的大型软件项目通常需要更复杂的分支管理策略,GitFlow就是其中一种。GitFlow是一种Git分支管理的参考模型,它基于Git的分支功能来组织和管理代码,并为不同的开发活动定义了清晰的分支策略。

GitFlow中,包含以下几种分支类型:

生产分支(master):仓库的主分支,只包含稳定的生产环境代码,对应于当前生产环境线上运行的软件版本。master分支通常只允许合并,不允许直接提交修改。

开发分支(dev):各种功能开发完成后都首先合并到dev分支进行集成测试,因此也叫集成分支。

发布分支(release):当软件发布新版本时,版本内上线的feature分支会逐一合并到release分支,然后统一将release分支合并到master分支。

功能分支(feature):feature分支通常对应于一个研发任务或一个程序员,feature开发完成后合并到dev分支进行测试,上线前合并到release分支。

热修复分支(hotfix):如果生产环境出现严重Bug需要紧急修复,此时需要基于master分支创建一个hotfix分支进行修复,修复完成后将hotfix分支合并到master分支和dev分支。

当然,这里并不是说我们的项目必须严格按照GitFlow工作流程来开发,GitFlow只是提供了一种参考,我们实际开发中,还是需要根据实际情况灵活调整,以满足我们的管理需要。

下面我们以例子形式介绍GitFlow工作流程。

假设某互联网公司开发了一个网络商城项目,程序员汤姆刚刚加入项目组,现在他将负责开发新功能“优惠券”。

  1. 汤姆首先克隆项目代码库,此时代码库主分支已被拉取到本地,汤姆将基于该分支创建自己的功能分支feature_tom_coupon
  2. 汤姆编写代码,每一次提交都提交到feature_tom_coupon分支上,最终功能基本开发完成。
  3. 汤姆合并feature_tom_coupon分支到dev分支上,持续集成系统被触发,并自动部署dev分支的代码到测试服务器上,汤姆通知测试人员进行测试。
  4. 测试人员发现了几个Bug,汤姆继续在feature_tom_coupon分支上修改,修改完成后合并到dev分支,并再次部署。
  5. 功能上线日期临近,汤姆将feature_tom_coupon分支合并到release_201801分支,201801版本上线的其它功能代码也从其他同事的功能分支上陆续合并上来。
  6. 所有人合并代码完成后,研发小组长对代码进行评审,然后将release_201801分支合并到master分支,并通知实施人员201801版本代码已准备好。
  7. 上线当天,实施人员编译master分支代码并部署到生产环境服务器,测试人员进行生产环境测试。
  8. 第二天,客户投诉“优惠券”功能存在严重Bug,一夜未睡的汤姆立刻再次投入修复工作,他基于master分支创建了一个hotfix_tom_coupon分支,并迅速编写代码。
  9. 汤姆修复完成后将hotfix_tom_coupon分支合并到dev分支,并通知测试人员对开发环境进行测试。
  10. 测试完成后,汤姆将hotfix_tom_coupon分支合并到master分支,并通知实施人员部署生产环境代码,以及通知测试人员继续连夜测试生产环境。
  11. 第三天,系统看似运行稳定,但汤姆则已经投入到下一个功能的研发工作中...
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap