赞
踩
目录
上一章我也提到了git的重要性,并把git的一些基本概念和一些基础操作讲清楚了,但依然存在着上一章没有解决的问题,例如add到暂存区后,然后再commit,这个commit具体到哪呢?这些都是如何操作的呢?本章将详细讲解关于git的分支管理。
下一章将讲述git远程仓库等相关内容。
本章开始介绍Git的杀⼿级功能之⼀:分支。分⽀就好像科幻电影⾥⾯的平行宇宙,当你正在电脑前努⼒学习C++的时候,另⼀个平⾏宇宙里的你⾥努⼒学习JAVA。然后最后所有宇宙的你合并到一起,造就了一个即会C++又会JAVA的你。(当然以上我都是我瞎编的,主要理解意思).
又或者这样的例子,你们村里举办武林大会,赢的人可以获得黄金万两并且抱得美人归。假设武林大会还有3个月开始,此时有两个人:你和你的对手,你们基本功差不多,需要在这三个月里努力修行,获得更多技能以赢得比赛。
假设第一个月你们都是在练习基本功,一个月过去了,你们都将基本功修行的差不多,能力不相上下.
第二个月你在山上偶然帮助了一个老头,却没想到该老头是个武林大师,听闻了你的经过后,点化了你。于是你学会了一门新技能:分身术。这个分身术不是普通的分身,在分身期间该分身所学习的技能,在与你重新合并的时候,都会转化为你所有。 于是你在第二个月,你本体学习降龙十八掌,分身学习辟邪剑法,等第二个月结束后,分身合体,你同时掌握了这两种技能。而你的对手却只会了降龙十八掌.
第三个月你们参见比赛,不出意外,你凭借多学的一门技术轻松战胜了对手。
如下:
以上你本体学习的所有内容称之为主线(master主分支),你的分身学习的 称之为支线.
这是上一章那个图片:
上一章我们也说了,这里不做过多赘述,就是HEAD指针指向了master,而master指向了master主分支上最新一次的提交,如下:
而有分支的提交如下:
具体是如何做的,以及会有一些什么问题,请继续向下看.
刚才一直在说HEAD指针,它指向了master,而master又指向了master主分支上最新一次的提交.
同时也说明1.HEAD指针指向的分支就是我们正在工作的分支。
2.而且HEAD可以指向其他分支,代表此时在该分支上工作。
如当我们创建一个分支时,假设分支名为dev-1,当我们切到该分支上时,HEAD指针便不再指向master,而是指向dev-1,而dev-1指向了dev-1分支上的最新一次提交。
那如何创建一个分支呢?
命令如下:
git branch [分支名]
该命令可以创建一个分支。
同时,我们可以使用下面的命令查看当前所有的分支。
git branch
如下:
其中 * 代表当前所处的分支。可以看到我已经创建了一个名为dev-1的分支。
注意:dev分支是基于当前分支最新一次提交的版本上创建的。
此时我们再查看一下.git中refs/heads下两个分支的内容:
可以发现两者的commit id是完全相同的,即我创建的dev-1分支是在当前master主分支上最新一次提交的基础上创建的.
如下:(图中的分支名是dev,我写的是dev-1,不一样,但不影响,只是名字不同)
我们虽然刚才创建了dev-1分支,但是我们通过git branch发现,我们当前所处的分支还是在master分支上:
我们该如何切换到dev-1分支呢?
使用命令:
git checkout [分支名]
即可切换到制定分支。
此时我们发现已经切换到dev-1分支上,并且HEAD指针已经指向了dev-1,说明我此时已经在dev-1上开始工作了, 所以此时的分支关系如下:
当我们切换到dev-1分支上后,我们先对ReadMe文件进行修改:添加一行"test on dev-1"
然后我们退出保存,然后add 到暂存区,并且commit提交:
此时我们再切换回到master主分支上,再次查看ReadMe内容:
我们发现,我们在dev-1分支上添加的那一行不存在,这是什么原因呢?
我们再来看一下刚创建dev-1分支完成时的状态:
此时master和dev-1重合,因为是刚创建,dev-1指向master最新一次提交。
当在dev-1分支上添加一行内容,并且add 和commit后,此时状态成为了这样:
此时master主分支已经落后于dev-1分支的一个提交了,所以master之所以看不到新添加的一行,是因为master分支还没有更新,即还没有与dev-1分支进行合并。
所以此时我们需要切换到主分支上,然后合并dev-1分支,分支合并命令如下:
git merge [分支名]
该命令会使指定分支 合并到当前分支。
合并完成后,新增加的一行我们也就能看到了:
Fast-forward 代表“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度⾮常快。
当然,也不是每次合并都能 Fast-forward,也会其他⽅式的合并,这里不再多说。
此时的状态如下:
合并完成后, dev 分⽀对于我们来说就没⽤了,那么dev分⽀就可以被删除掉,注意如果当前正处于某分⽀下,就不能删除当前分⽀。
使用如下命令删除分支:
git branch -d [分支名]
可以发现dev-1分支已经被删除掉了。
因为创建、合并和删除分⽀⾮常快,所以Git⿎励你使⽤分⽀完成某个任务,合并后再删掉分⽀,这和直接在master分⽀上⼯作效果是⼀样的,但过程更安全。
可是,在实际分⽀合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。
冲突主要是发生在这样的场景:在当前master主分支上 新建了一个dev分支,然后dev分支commit提交后,master主分支此时并没有直接合并,而是也对dev分支上修改的文件 也做了修改,此时master主分支再合并,就会出现问题,因为git也不知道是保留dev分支上的修改还是master主分支上的修改。所以需要我们手动解决冲突。
下面做一个演示:
教大家一个命令,可以直接创建并且切换到该新建的分支:
git checkout -b [分支名]
切换到新分支dev1上上之后,我添加了如下一行:
在commit提交后,我切回到master主分支上,此时由于我还没有合并,所以刚才添加的那一行并没有显示,我也在相同的位置添加上如下一行:
此时我commit后,再在master分支上,再进行合并,便会出现下面的合并冲突问题:
此时我们打开冲突的文件:
蓝色框,即HEAD指针指向的分支上(当前分支)的修改是modify on master
粉色框,即dev分支上的修改是 modify on dev1
我们此时有三种选择:
1.保留HEAD的更改
2.保留dev1的更改
3.保留HEAD和dev1的更改.
此时我决定只保留HEAD的更改,于是我把出HEAD指向的那一行以外的内容全部删除,如下:
退出保存后,我们再次add和commit提交,(再次提交很重要,切勿忘记)冲突便成功解决了:
此时我们分支的状态如下:
假设我们现在正在dev2分支上进行开发,还没有开发完成,突然发现master主分支上有bug需要解决。在Git中,每个bug都可以通过在master分支上开一个临时分支进行解决,修复后,合并分支,再将临时分支删除。
因此我们需要先回到master分支上,开一个bug分支然后解决完后,再回到dev2分支进行工作,但问题是我现在dev2还没有开发完,如果直接切回master,那内容就会丢失 ,所以我们需要现将dev2工作区中的内容保存起来。
Git 提供了 git stash 命令,可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时
间恢复出来.
同样拿一个示例演示:
在dev2分支下,我在ReadMe文件中,加入以下一行代码:
此时由于master分支上出现了bug,我需要将当前dev2分支上的内容保存起来,然后切回到master分支:
然后我在开一个分支用来修复bug,假设在ReadMe文件中该行少了三个叹号:
然后修复完成后,我们add并commit提交,切换到master分支,与该分支进行合并:
此时master分支上的bug修复完毕了,我们需要继续回到dev2分支上工作。
切换到dev2分支上后,首先需要恢复我们上次工作区的修改变动,
使用
git stash pop
恢复的同时会把 stash 也删了.
可以发现ReadMe内容恢复了,但是修复bug后的内容,并没有在dev2中显示,此时的状态图为:
Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们在 dev2 中当然看不见修复bug的相关代码。
当我们完成dev2的开发工作时,我们add并commit提交后,
我们此时能切回到master分支然后直接合并吗?
答案是可以,但是是有风险的,这是因为dev2和master在合并分⽀时可能会有冲突,而代码冲突需要我们手动解决(在 master 上解决)。我们无法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能几十上百行,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。得不偿失,如果这么做,此时的状态图如下:
解决这个问题的⼀个好的建议就是:最好在自己的分支上合并下 master ,再让 master 去合并
dev ,这样做的⽬的是有冲突可以在本地分支解决并进行测试,而不影响 master 。此时的状态
为:
对应的代码:
对应代码:
这样不仅在开发dev2期间修复了bug,最后也顺利的完成了dev2的开发工作并合并到master分支中,一切便大功告成了。
我们刚才说了一个删除分支的命令
git branch -d [分支名]
这个删除有一个前提条件,就是在你已经提交并且已经别master分支合并之后,才能删除,如果没有被合并,则不可以被删除。
那么我就是想删除这个分支强制删除,确定这个分支上的内容已经彻底没用了,不用合并了,那么我们只需要把-d 改成 -D即可:
git branch -D [分支名]
演示一下:
这样便完成了强制删除某个分支。一般用于开发某个需求时,突然这个需求被抛弃需要删除这个分支,便使用到了这个功能.
git分支管理的内容到此就结束了,如果有疑问或者不懂地方,欢迎评论留下哦~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。