【Git】 -- Part2 -- 分支管理

1. 分支

在 Git 中,分支(Branch)是用于在项目中创建独立开发线路的机制。分支使得开发者可以在不影响主干(main 或 master)的情况下进行实验、开发新功能或修复 Bug。

举个例子:
分⽀就好像是科幻电影⾥⾯的平⾏宇宙,当你正在电脑前努⼒学习 C++ 的时候,另⼀个你正在另⼀个平⾏宇宙⾥ 努⼒学习 Python。

如果两个平⾏宇宙互不⼲扰,那对现在的你也没啥影响。不过,在某个时间点,两个平⾏宇宙合并了,结果,你既学会了 C++ ⼜学会了 Python!
image.png
现实世界,在Git分支对应得就是主分支,而平行时间,在Git里面对应得就是新创建得另一个分支。

在Git中,每进行一次提交(commit操作),Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。如果只有一条分支,在Git里,这个分支就是主分支,即master分支。

image.png

而HEAD,HEAD 严格来说不是指向提交,⽽是指向master,master才是指向提交的,所以,HEAD 指向的就是当前分⽀。

每次提交,master分⽀都会向前移动⼀步,这样,随着你不断提交,master分⽀的线也越来越⻓,⽽ HEAD只要⼀直指向master分⽀即可指向当前分⽀
image.png

1.1 创建分支

Git ⽀持我们查看或创建其他分⽀,在这⾥我们来创建第⼀个⾃⼰的分⽀ dev ,对应的命令为:

git branch 分支名

使用示例

  • 创建dev分支
git branch dev

image.png
然后使用git branch可以查看所有分支。

image.png
当我们创建新的分⽀后,Git 新建了⼀个指针叫 dev, * 表⽰当前 HEAD 指向的分⽀是 master分⽀。另外,可以通过⽬录结构发现,新的 dev分⽀和 master 指向同⼀个提交。

image.png
图解:

image.png

1.2 切换分支

使用 git checkout 分支名 命令切换到指定分支。

使用示例

比如切换到dev分支。

git checkout dev

image.png
切换到dev分支后,就可以看到*在dev分支前,表明当前分支是dev分支。

切换分支后,HEAD就指向到切换得分支下面了。
image.png
可以使用cat .git/HEAD进行验证

image.png

切换分支后,在dev分支下进行操作,比如新建一个文件test.txt,然后向其进行随便写入一些东西。

写入完成后,在dev分支下面进行一次提交操作

git add .
git commit -m "dev commit tset"

image.png
提交完成后,切换到master分支下面

git checkout master

image.png
切换到master分支后,就发现test.txt文件不存在了。 然后继续切回到dev分支下,发现,在dev分支下,test.txt文件还存在的。

image.png
出现这个现象的原因就是:我们是在dev分⽀上提交的,⽽master分⽀此刻的提交点并没有变。
使用命令可以查看他们的指向是不同的:

image.png
图解如下:

image.png
当切换到 master 分⽀之时,HEAD 就指向了 master,自然就看不到test.txt文件了。

1.3 合并分支

为了在 master 主分⽀上能看到新的提交,就需要将 dev 分⽀合并到 master 分⽀。
使用git merge⽤于合并指定分⽀到当前分⽀。

使用案例

将dev分支合并到master分支下。

  1. 必须切换到master分支下进行合并
  2. 使用git merge dev将dev分支合并到master分支下。

image.png
此时 就能在master分支下看到test.txt文件了。

Fast-forward 代表“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度⾮常快。

image.png
图解:

image.png

1.4 删除分支

合并完成后, dev 分⽀对于我们来说就没⽤了, 那么dev分⽀就可以被删除掉。

注意:不能在dev分支下删除dev分支,也就是不能自杀。

删除分支的命令
git branch -d 分支名

使用案例

  • 删除dev分支
git branch -d dev

image.png
删除后的图解:

image.png

因为创建、合并和删除分⽀⾮常快,所以Git官方建议使⽤分⽀完成某个任务,合并后再删掉分⽀,这和 直接在master分⽀上⼯作效果是⼀样的,但过程更安全。

2. 冲突

可是,在实际分⽀合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。

下面就演示一下这种场景:
先创建一个测试分支dev
使用git checkout -b dev创建切换分支。这个命令就是切换到dev分支,如果分支不存在,就创建。

image.png
在dev分支下,修改test.txt文件。向test.txt文件写入一行新文本modify by dev

image.png
在dev分支下进行提交。(先add添加,在使用commit进行提交)

image.png

切换到master分支下。

image.png
在master分支下,查看test.txt文件中的内容,此时是没有更新的。

在master分支下,也对test.txt文件中进行修改如下:

image.png

修改完成后,在master分支下进行提交。

image.png
现在,master和dev分支下都分别有了自己新的提交。图示如下:

image.png
在这种情况下,Git只能试图把各⾃的修改合并起来,但这种合并就可能会产生合并冲突。

在master分支下合并dev分支,下面这种情况就出现了合并冲突。
image.png
此时 查看test.txt文件中的内容就会看到,git会用指定的字符<<<<<<<,=======, >>>>>>> 来标记不同分支出现冲突的内容。如下:

image.png

2.1 合并冲突

当发生合并冲突的时候,就需要我们手动调整冲突的代码,保留需要的一部分,删除不需要的一部分。然后再次进行提交调整后的代码。(必须要再次提交)

image.png
此时,图示状态如下:

image.png
使用git log也能查看分支合并的情况。

git log --graph --pretty=oneline --abbrev-commit

image.png
合并完了,dev分支也就不用了,删除即可。使用git branch -d dev删除dev分支即可。

image.png

3. 分支管理策略

在合并分支的时候,Git一般会采用Fast forward模式,直接把master指向dev的当前提交。如果采用Fast forwrad模式后,形成的合并结果如下:

image.png
在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提 交到底是 merge 进来的还是正常提交的。

但在合并冲突部分,我们也看到通过解决冲突问题,会再进行⼀次新的提交,得到的最终状态为:
image.png
那么这就不是 Fast forward 模式了,这样的好处是,从分⽀历史上就可以看出分⽀信息。

Git ⽀持我们强制禁⽤ Fast forward 模式,那么就会在 merge 时⽣成⼀个新的 commit ,这样, 从分⽀历史上就可以看出分⽀信息。

使用示例 - 非Fast forward模式进行合并

1、创建一个新的dev分支,切换到新分支下。
git checkout -b dev

image.png

2、修改test.cc,并提交⼀个新的 commit

image.png
3、切换到master分支,开始合并。

image.png

–no-ff 参数,表⽰禁⽤ Fast forward 模式。禁⽤ Fast forward 模式后合并会创建 ⼀个新的 commit ,所以加上 -m 参数,把描述写进去。

4、合并后,查看历史分支日志

image.png
这样,在合并分支的时候,加上 --no-ff 参数就可以⽤普通模式合并,合并后的历史有分⽀,能看出来曾 经做过合并,⽽ Fast Forward 合并就看不出来曾经做过合并。

3.1 分支策略

在实际开发中,应该按照以下⼏个基本原则进⾏分⽀管理:

  • ⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活;
  • ⼲活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布 时,再把dev分⽀合并到master上,在master分⽀发布1.0版本
  • 团队里每个⼈都在dev分⽀上⼲活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就 可以了。
  • 团队合作的分支看起来就像下图一样:

image.png

4. Bug分支

假如我们现在正在 dev 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有 bug,需要解决。在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。

可现在 dev分支的代码在⼯作区中开发了⼀半,还⽆法提交。比如下面这种情况:

image.png

针对这种情况,Git 提供了git stash命令。可以将工作区的信息进行储藏,,被储藏的内容可以在将来某个时间恢复出来。比如在dev分支下,将当前的工作区进行储藏。

image.png

储藏之后,查看工作区的状态就是干净的了。

image.png

储藏dev分支后,就要对master分支下的bug进行修复了。所以需要切回到master分支下。在创建临时分支修复bug。

image.png
修复完bug后,在dev分支下 重新add commit。

image.png
然后切换到master分支下,完成合并。最后删除bug分支即可。

image.png

至此,bug修复的工作已经完成,继续回到dev分支下进行开发。首先切换到dev分支下。
由于修复bug之前,将dev分支下的工作区代码进行储藏了,现在就要对其进行恢复了。

image.png
使⽤ git stash pop 命令进行恢复,恢复的同时会把 stash 也删了。

image.png

这样,dev分支下的工作区就之前的写的代码就被恢复了。

image.png

恢复现场也可以采⽤ git stash apply 恢复,但是恢复后,stash内容并不删除,需要⽤ git stash drop 来删除。

也可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令 git stash apply stash@{0}。

恢复完代码后,就可以继续完成开发了,开发完成后进行提交即可。

image.png
但是,在dev分支下,修复bug的内容,并没有在dev分支下显示,此时的状态图如下:

image.png
现在要切换到master分支下合并dev分支。正常情况下,切回到master分支下,直接合并即可。但这样其实是有⼀定⻛险的。

是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法 保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单, 有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。 此时的状态为:

image.png

解决这个问题的⼀个好的建议就是:最好在⾃⼰的分⽀上合并下 master ,再让 master 去合并 dev ,这样做的⽬的是有冲突可以在本地分⽀解决并进⾏测试,⽽不影响 master 。此时的状态为:

image.png
dev分支下合并master,就算合并有问题,也可以在dev分支下进行多次修改测试,不会影响master分支下的代码。

然后再去master分支下去合并dev分支。此时冲突在dev分支下已经解决了,在master分支下进行合并就无需解决冲突了~。

image.png
实操如下:

image.png

image.png

5. 删除临时分支

添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新功能,最好新建⼀个分⽀,我们可以将其称之为 feature 分⽀,在上⾯开发,完成后,合并,最后,删除该 feature 分⽀。

可是,如果我们今天正在某个 feature 分⽀上开发了⼀半,被产品经理突然叫停,说是要停⽌新功能的开发。虽然⽩⼲了,但是这个 feature 分⽀还是必须就地销毁,留着⽆⽤了。这时使⽤传统 的 git branch -d命令删除分⽀的⽅法是不⾏的。

比如:在新的feature分支下开发新功能。

image.png
此时新功能被叫停,切回master分支准备删除feature分支。

image.png

根据提示也可以看到,要使用-D选项进行删除。

image.png

6. 总结

⽀在实际中有什么⽤呢?

  • 你准备开发⼀个新功能,但是需要两周才能完成,第⼀周你写了50% 的代码,如果⽴刻提交,由于代码还没写完,不完整的代码库会导致别⼈不能⼲活了。
  • 如果等代码全部写完再⼀次提交,⼜存在丢失每天进度的巨⼤⻛险。
  • 现在有了分⽀,就不⽤怕了。你创建了⼀个属于你⾃⼰的分⽀,别⼈看不到,还继续在原来的分⽀上正常⼯作,⽽你在⾃⼰的分⽀上⼲活,想提交就提交,直到开发完毕后,再⼀次性合并到原来的分⽀ 上,这样,既安全,⼜不影响别⼈⼯作。
  • 并且 Git ⽆论创建、切换和删除分⽀,Git在1秒钟之内就能完成!⽆论你的版本库是1个⽂件还是1万个⽂件。
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++下等马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值