前面介绍了一些关于git的知识,然后下面重点介绍一下git分支
分支
分支的主要应用场景是“假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。”
git处理分支的方式非常轻量,不像其它版本控制系统一样需要完全创建一个源代码目录副本,它只是为你创建了一个可以移动的新的指针,然后又有一个HEAD指针指向当前分支。
“截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。”
创建分支
git checkout -b dev
创建dev分支,并切换到了dev分支
该命令可分解为git branch dev
和git checkout dev
或者使用git switch -c dev
,切换使用git switch dev
git branch
可以用来查看当前所在分支和所有的分支
在dev分支上进行操作,看看master分支啥情况:
- 修改test1.txt;
git add .
和git commit -m "dev"
- 切换回主分支
git checkout master
- 发现test1.txt没有任何变化
我觉得git官方上画的图和解释的比较清楚:
创建testing分支并切换到testing分支时:
testing分支有commit操作时:
切换回主分支后:
指针所指的正是我们的commit快照,都有一个commitID(sha1算法产生的)
合并分支
现在我们把dev分支上的工作合并到主分支上:git merge dev
:
1 | Updating 4b194ea..535f59d |
采用的是Fast-Forward方式,即此时将master指向dev的当前提交,所以合并速度非常快。
合并如何出现冲突?
我们经常会遇见合并不成功,出现冲突
一般是指经过了下列操作:
- 切换到dev分支
git switch dev
,修改test1.txt的第一行内容为12345; - 执行add和commit;
- 切回到主分支,修改test1.txt的第一行内容为678910;
- 执行add和commit
此时分支结构变为了下图:
这种情况下我们进行合并git merge dev
:
1 | Auto-merging test1.txt |
出现合并冲突了,无法自动合并了,git status
也可以查看更多信息:
1 | On branch master |
此时test1.txt变成了下列内容:
标出了不同分支的内容,此时我们将主分支的内容改为12345,再add和commit
然后合并分支发现可以了
现在分支结构变为了:
使用git log也可以查看到分支的合并情况:git log --graph --pretty=oneline --abbrev-commit
不使用FAST-FORWARD方式合并
我们之前讲过了自动合并使用的是FAST-FORWARD方式,此时将master指向dev的当前提交,所以合并速度非常快。
如下图所示:
但是这样会存在一个问题,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。git merge --no-ff -m "merge with no-ff" dev
,但是我刚才试了试,发现只有第一个文件的合并采用的Fast forward模式,后来都是没采用,如下图所示分支结构为:
git push推送的是哪一个分支?
现在我们本地有两个分支主分支和dev分支,现在要推送至远程仓库里,就要使用git push命令,其实我们之前所使用的git push命令默认都是在主分支,然后默认也是推送给仓库里的主分支上的
现在进行细化:
如果想推送某一分支到远程仓库的某一分支:
- 切换到对应分支,如
git checkout dev
- 推送:
git push origin dev
当然该dev分支可以不推送至远程仓库,自己玩也行
多人协作
注意此时当别人clone这个远程库时,只能看到主分支,并不能看到dev分支,如果想要在dev分支上工作的话,需要git checkout -b dev origin/dev
现在我的主分支上还没有push,如果别人在主分支上新建了一个test5.txt,然后他add、commit和push(成功push)了,那我这端的主分支如果push会有什么样的效果呢?
报错了:
1 | hint: Updates were rejected because the remote contains work that you do |
那更不用提有冲突的push了,解决办法就是要使用git pull
但是如果别人push的是test1.txt,并且我也在改text1,并且修改内容不同,我也想push,会咋样呢?
此时别人将test1.txt改为了12345,push上去了,然后我将test1.txt改为了12356,也想push咋办呢?
我先git pull
1 | Auto-merging test1.txt |
冲突了,如何解决呢?那就现在本地解决好了冲突后再add、commit和push就可以了,然后git pull就没问题了
我们发现在别人那里查看日志也发现里面含有全部的版本日志,包括分支合并等。