Git分支管理

目录

1.理解分支

2.创建分支

3.切换分支

4.合并分支

5.删除分支

6.合并冲突

7.分支管理策略

8.分支策略

9.bug分支

10.删除临时分⽀

11.小结


1.理解分支

本章开始介绍Git的杀⼿级功能之⼀(注意是之⼀,也就是后⾯还有之⼆,之三......):分⽀。分⽀就 是科幻电影⾥⾯的平⾏宇宙,当你正在电脑前努⼒学习C++的时候,另⼀个你正在另⼀个平⾏宇宙⾥ 努⼒学习JAVA。

如果两个平⾏宇宙互不⼲扰,那对现在的你也没啥影响。不过,在某个时间点,两个平⾏宇宙合并 了,结果,你既学会了C++⼜学会了JAVA!

在版本回退⾥,你已经知道,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀ 个分⽀。截⽌到⽬前,只有⼀条时间线,在Git⾥,这个分⽀叫主分⽀,即master分⽀。

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

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

通过查看当前的版本库,我们也能清晰的理出思路:

2.创建分支

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

  • 列出分支基本命令:
bash 复制代码
git branch

没有参数时,git branch 会列出你在本地的分支。

此例的意思就是,我们有一个叫做 master 的分支,并且该分支是当前分支。

接下来我们新建一个分支

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

并且也可以验证下HEAD⽬前是指向master 的。

⼀张图总结:

3.切换分支

那如何切换到dev分⽀下进⾏开发呢?使⽤ git checkout 命令即可完成切换,⽰例如下:

我们发现HEAD已经指向了dev,就表⽰我们已经成功的切换到了dev上!

接下来,在 dev 分⽀下修改ReadMe⽂件,新增⼀⾏内容,并进⾏⼀次提交操作:

现在,dev分⽀的⼯作完成,我们就可以切换回master分⽀:

切换回master分⽀后,发现ReadMe⽂件中新增的内容不⻅了!!!赶紧再切回dev看看:

在dev分⽀上,内容还在。为什么会出现这个现象呢?我们来看看dev分⽀和master分⽀指向,发 现两者指向的提交是不⼀样的:

看到这⾥就能明⽩了,因为我们是在dev分⽀上提交的,⽽master分⽀此刻的提交点并没有变,此时 的状态如图如下所⽰。

当切换到master分⽀之时,HEAD就指向了master,当然看不到提交了!

4.合并分支

git merge命令用来合并分支。

为了在master主分⽀上能看到新的提交,就需要将 dev 分⽀合并到master 分⽀,⽰例如下:

首先我们需要切换回master分支

接下来我们就合并dev分支

git merge 命令⽤于合并指定分⽀到当前分⽀。

合并后,master就能看到dev分⽀提交的内容 了。此时的状态如图如下所⽰。

Fast-forward 代表"快进模式",也就是直接把master指向dev的当前提交,所以合并速度⾮常快。 当然,也不是每次合并都能Fast-forward,我们后⾯会讲其他⽅式的合并。

5.删除分支

合并完成后,dev分⽀对于我们来说就没⽤了,那么dev分⽀就可以被删除掉,注意如果当前正处于某 分⽀下,就不能删除当前分⽀,如:

⽽可以在其他分⽀下删除当前分⽀,如:

此时的状态如图如下所⽰。

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

6.合并冲突

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

为了演⽰这问题,创建⼀个新的分⽀ dev1 ,并切换⾄⽬标分⽀,我们可以使⽤git checkout -b dev1 ⼀步完成创建并切换的动作,⽰例如下:

在 dev1 分⽀下修改 ReadMe ⽂件,更改⽂件内容如下,并进⾏⼀次提交,如:

切换⾄ master 分⽀,观察 ReadMe ⽂件内容:

我们发现,切回来之后,⽂件内容由变成了⽼的版本,这种现象很正常,我们现在也完全能理解。

此时在master分⽀上,我们对ReadMe⽂件再进⾏⼀次修改,并进⾏提交,如下:

现在, master 分⽀和 dev1 分⽀各⾃都分别有新的提交,变成了这样:

这种情况下,Git只能试图把各⾃的修改合并起来,但这种合并就可能会有冲突,如下所⽰:

发现ReadMe⽂件有冲突后,可以直接查看⽂件内容,要说的是Git会⽤>>>>>> ,=======,>>>>>>>来标记出不同分⽀的冲突内容,如下所⽰:

此时我们必须要⼿动调整冲突代码,并需要再次提交修正后的结果!!(再次提交很重要,切勿忘 记)

到这⾥冲突就解决完成,此时的状态变成了

⽤带参数的git log也可以看到分⽀的合并情况,具体⼤家可以⾃⾏搜索 git log 的⽤法:

在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看。

  • git log 命令用于查看 Git 仓库中提交历史记录。
  • git log 显示了从最新提交到最早提交的所有提交信息,包括提交的哈希值、作者、提交日期和提交消息等。

git log 命令的基本语法:

prettyprint 复制代码
git log [选项] [分支名/commit id]

常用的选项包括:

  • -p:显示提交的补丁(具体更改内容)。
  • --oneline:以简洁的一行格式显示提交信息。
  • --graph:以图形化方式显示分支和合并历史。
  • --decorate:显示分支和标签指向的提交。
  • --author=<作者>:只显示特定作者的提交。
  • --since=<时间>:只显示指定时间之后的提交。
  • --until=<时间>:只显示指定时间之前的提交。
  • --grep=<模式>:只显示包含指定模式的提交消息。
  • --no-merges:不显示合并提交。
  • --stat:显示简略统计信息,包括修改的文件和行数。
  • --abbrev-commit:使用短提交哈希值。
  • --pretty=<格式>:使用自定义的提交信息显示格式。

我们可以切换两个分支看看什么情况

最后,不要忘记dev1分⽀使⽤完毕后就可以删除了:

7.分支管理策略

通常合并分⽀时,如果可能,Git会采⽤ Fast forward 模式。还记得如果我们采⽤ Fast forward 模式之后,形成的合并结果是什么呢?回顾⼀下

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

但在合并冲突部分,我们也看到通过解决冲突问题,会再进⾏⼀次新的提交,得到的最终状态为:

那么这就不是 Fast forward 模式了,这样的好处是,从分⽀历史上就可以看出分⽀信息。

例如我 们现在已经删除了在合并冲突部分创建的 dev1 分⽀,但依旧能看到master其实是由其他分⽀合并 得到:

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

Git 支持我们强制禁用从分支历史上看出分支信息。

Fast forward 模式 下,Git 会在合并时直接将分支指针向前移动,而不会生成一个新的合并提交。如果你希望在合并时强制生成一个新的合并提交,可以使用 --no-ff 选项。

下⾯我们实战⼀下--no-ff ⽅式的 git merge 。⾸先,创建新的分⽀dev2,并切换到新的分支

修改 ReadMe ⽂件,并提交⼀个新的 commit :

切回 master 分⽀,开始合并:

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

合并之后,查看分支历史

可以看到,不使⽤ Fast forward 模式,merge后就像这样:

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

8.分支策略

在实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理: ⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活;

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

你和你的⼩伙伴们每个⼈都在dev分⽀上⼲活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就 可以了。

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

9.bug分支

假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有bug,需要 解决。

在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀ 删除。 可现在 dev2 的代码在⼯作区中开发了⼀半,还⽆法提交,怎么办?

例如,我们先看看Readme文件

就在这个时候,我发现我们在master分支里面少加了一句话。这怎么办?

别着急,我们先来认识一个命令 git stash

git stash(git储藏)可用于以下情形:

  • 发现有一个类是多余的,想删掉它又担心以后需要查看它的代码,想保存它但又不想增加一个脏的提交。这时就可以考虑git stash
  • 使用git的时候,我们往往使用分支(branch)解决任务切换问题,例如,我们往往会建一个自己的分支去修改和调试代码, 如果别人或者自己发现原有的分支上有个不得不修改的bug ,我们往往会把完成一半的代码commit提交到本地仓库,然后切换分支去修改bug,改好之后再切换回来。这样的话往往log上会有大量不必要的记录。实如果我们不想提交完成一半或者不完善的代码,但是却不得不去修改一个紧急Bug,那么使用git stash就可以将你当前未提交到本地(和服务器)的代码推入到Git的栈中,这时候你的工作区间和上一次提交的内容是完全一样的 ,所以你可以放心的修Bug,等到修完Bug,提交到服务器上后,再使用git stash apply将以前一半的工作应用回来。
  • 经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是git stash命令。储藏(stash)可以获取你工作目录的中间状态------也就是你修改过的被追踪的文件和暂存的变更------并将它保存到一个未完结变更的堆栈中,随时可以重新应用。

git stash会把所有未提交的修改(包括暂存的和非暂存的)都保存起来,用于后续恢复当前工作目录。

比如下面的中间状态,通过git stash命令推送一个新的储藏,当前的工作目录就干净了。

⽤ git status 查看⼯作区,就是⼲净的(除⾮有没有被Git管理的⽂件),因此可以放⼼地创建分 ⽀来修复bug。

储藏 dev2 ⼯作区之后,由于我们要基于master分⽀修复bug,所以需要切回 master 分⽀,再新 建临时分⽀来修复bug,⽰例如下:

接下来我们就创建新分支,修复我们的bug

我们重新提交一下

修复完成后,切换到master 分⽀,并完成合并,最后删除 fix_bug 分⽀:

⾄此,bug的修复⼯作已经做完了,我们还要继续回到dev2 分⽀进⾏开发。切换回 dev2 分⽀:

⼯作区是⼲净的,刚才的⼯作现场存到哪去了?

查看现有stash,可以使用git stash list命令

在使用git stash apply命令时可以通过名字指定使用哪个stash,默认使用最近的stash(即stash@{0})

⼯作现场还在,Git把stash内容存在某个地⽅了,但是需要恢复⼀下,如何恢复现场呢?我们可以使 ⽤ git stash pop 命令,恢复的同时会把stash也删了,⽰例如下:

可以通过git stash pop命令恢复之前缓存的工作目录,这个指令将缓存堆栈中的第一个stash删除,并将对应修改应用到当前的工作目录下

再次查看的时候,我们已经发现已经没有现场可以恢复了

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

你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令 git stash apply stash@{0} ,这部分请同学们⾃⾏使⽤。

恢复完代码之后我们便可以继续完成开发,开发完成后便可以进⾏提交,例如:

**但我们注意到了,修复bug的内容,并没有在 dev2 上显⽰。**此时的状态图为:

Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的master 分⽀的提交的,所以我们 在 dev2 中当然看不⻅修复bug的相关代码。

我们的最终⽬的是要让master 合并 dev2 分⽀的,那么正常情况下我们切回 master分支合并即可,但这样其实是有⼀定⻛险的。

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

此时的状态为:

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

对应的实操演⽰如下,要说明的是,以下演⽰的merge操作,没有使⽤--no-ff ,但上述的图⽰是 禁⽤ Fast forward 了模式后得出的,主要是为了⽅便解释问题。

dev 合并 master

发⽣冲突

解决冲突并重新提交

切回 master

master 合并 dev2-- ⽆需解决冲突!!

删除dev2 分⽀

10.删除临时分⽀

软件开发中,总有⽆穷⽆尽的新的功能要不断添加进来。

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

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

此 时新功能叫停,我们就切回master分支准备删除dev3分支

我们发现删除不了,那我们只能使用git branch -D命令

11.小结

分⽀在实际中有什么⽤呢?假设你准备开发⼀个新功能,但是需要两周才能完成,第⼀周你写了50% 的代码,如果⽴刻提交,由于代码还没写完,不完整的代码库会导致别⼈不能⼲活了。如果等代码全 部写完再⼀次提交,⼜存在丢失每天进度的巨⼤⻛险。

现在有了分⽀,就不⽤怕了。你创建了⼀个属于你⾃⼰的分⽀,别⼈看不到,还继续在原来的分⽀上 正常⼯作,⽽你在⾃⼰的分⽀上⼲活,想提交就提交,直到开发完毕后,再⼀次性合并到原来的分⽀ 上,这样,既安全,⼜不影响别⼈⼯作。 并且Git⽆论创建、切换和删除分⽀,Git在1秒钟之内就能完成!⽆论你的版本库是1个⽂件还是1万个⽂件。

相关推荐
德育处主任6 小时前
聚沙成塔,三步成书:GitBook极简入门教程
前端·git·电子书
m0_635647486 小时前
git管理github上的repository
git·github
Jiude6 小时前
基于开源项目开发公司项目,如何同步开源仓库的最新更新(以vben为例)
git·开源·github
PAK向日葵7 小时前
【软件工程】如何使用Git Rebase同步团队开发进度
git·面试
枫叶落雨2229 小时前
git checkout C1解释
git
Dontla10 小时前
git stash介绍(临时保存当前工作目录中尚未提交的修改)
git
黎相思11 小时前
Git多人协作
git
一只名叫Me的猫12 小时前
Git 常用命令 - 服务器用
git
黎相思12 小时前
Git基本操作
git
Auv开心1 天前
【git stash切换】
经验分享·git