git协同开发的分支讲解

这是一篇写于18年初的文章,发布在我的博客上。不过早已不维护了,就拿来丰富一下我的掘金账号。希望这篇文章能给你带来一些帮助。本文主要讲解了协同开发时应该注意是事项,如何正确理解git分支,如何合并分支管理分支

关于分支的介绍

在Git您可以自由地建立分支。但是,要先确定运用规则才可以有效地利用分支。

这里我们会介绍两种分支 (“Merge分支”和 “Topic分支” ) 的运用规则。

Merge分支

Merge分支是为了可以随时release(发布)而创建的分支,它还能作为Topic分支的源分支使用。保持分支稳定的状态是很重要的。如果要进行更改,通常先创建Topic分支。

细说,Merge分支作为源头分支,通常它就是我们在开发中的master分支,同时我们在开发的过程中不断会有新的功能加入,bug的修复等,为了能让master分支时刻保持稳定,我们通常会新建其他分支进行开发最后完成时再将它合并到master分支上(这里我们略过测试分支,因为不一定会有,有的话也是同理所以不加垒诉),关于这点,如果你用图形化工具如Sourcetree,你是可以很直观地看到master是十分线性的。

Topic分支

Topic(主题)分支是为了开发新功能或修复bug等任务而建立的分支。若要同时进行多个的任务,请创建多个的Topic分支。

Topic分支是从稳定的Merge分支创建的。完成作业后,要把Topic分支合并回Merge分支。(再次重复了一遍)

这里补充说明一下stash

还未提交的修改内容以及新添加的文件,留在索引区域或工作树的情况下切换到其他的分支时,修改内容会从原来的分支移动到目标分支。

但是如果在checkout的目标分支中相同的文件也有修改,checkout会失败的。这时要么先提交修改内容,要么用stash暂时保存修改内容后再checkout。

stash是临时保存文件修改内容的区域。stash可以暂时保存工作树和索引里还没提交的修改内容,您可以事后再取出暂存的修改,应用到原先的分支或其他的分支上。

用代码的形式讲解一下:

首先假设我reserve分支,此时我更改了reserve分支上的两个文件,如图:

status(reserve).jpeg

现在,我们通过diff看看更改了些什么:

diff(reserve).jpeg

此刻,我们切换到master分支:

checkout(master).jpeg

这时,我们看到原本干净的master分支多次了这两个改动;我们可以再在cityPlan.js中做一些小的改动,改完之后再通过git checkout reserve切会reserve分支。你会发现reserve分支上原本的改动被master分支上最新的改动覆盖了。

reserve(checkout).jpeg

为了解决这一问题:我们可以通stash来保存当前分支的更改,也可以给当前的更改命名git stash save 'blablabla', 如果保存了多个stash,可以通过git stash list查看, 可以通过git stash apply stash@{n}来选择某次保存的更改进行开发。默认git stash apply选择的是最后一次的保存;git stash drop是删除的是stash@{0}位子上的保存(也就是最新的保存)。git stash pop是选中最新的保存的同时将其在stash list中删除。而git stash clear可以一次性清空stash栈

stash(all).jpeg

**画重点:当我修改了a.js,这时我stash将这次的修改存储,可能我现在不想提交代码但是我想要拉取代码或者修改存储前的代码,当你想要当前的拉去或者修改同你存储的代码进行合并,这时你必须git add .将这些修改放入暂存区,然后再git stash pop完成合并。如果直接git stash pop会告诉你无法使用

error: 
Your local changes to the following files would be overwritten by merge:
	xxxx/xxxx/xxx/xxx/xxx.xx
Please commit your changes or stash them before you merge.
复制代码

并且很友好的提示你在合并之前必须先提交当前的更改或者是暂存

Git强大的地方也体现在他有好的警告和提示,大部分情况下你多是可以通过提示解决出现的问题

分支的合并

完成作业后的topic分支,最后要合并回merge(master)分支。合并分支有2种方法:使用merge或rebase。使用这2种方法,合并后分支的历史记录会有很大的差别。

merge

使用merge可以合并多个历史记录的流程。

如图所示,bugfix分支是一个以master分支为基础分出来的新分支

bugfixBranch.png

这时将bugfix分支合并到master分支时,若当master在此期间没有被更改过,那么git会做这样一个操作:把master分支的位置移动到bugfix的最新分支上。这样的合并我们称之为fast-forward(快进)合并。

mergeFast-forward.png

另一种情况:当master分支在此期间被更改了(并且没有更改回分出去时的版本),那么git会做这样的一个操作:合并会产生一个提交,master分支的HEAD会移动到该提交上。

mergeNofast-forward.png

mergeCommit.png

注:执行合并时,如果设定了non fast-forward选项,即使在能够fast-forward合并的情况下也会生成新的提交并合并。执行non fast-forward后,分支会维持原状。那么要查明在这个分支里的操作就很容易了。如图所示:

canFastButNon.png

rebase

同样的,还是从master分支分出来的:

mergeNofast-forward.png

我们使用rebase进行合并的话,如图所示:

rebase.png

首先,当我们rebase bugfix分支到master分支的时候,bugfix分支的提交历史都会添加在master分支的后面,如图所示:

rebaseing.png

rebase之后,master的HEAD位置不会改变,因此,要合并master分支和bugfix分支,即是将master的HEAD移动到bugfix的HEAD上面

rebaseresult.png

结论

merge和rebase都是合并分支,但是他们的各自的特点不同,但是结果相同。

  • merge

    一次性合并,历史记录简单。是对比原有提交和当前提交的差异,将新的内容反映进去,有冲突的内容自行更改。(同git pull一个原理,git pull会自动合并代码,有些同学并不知道这个知识点,所以在这里提一下)

  • rebase

    一步一步合并,历史记录复杂。它会将每一次的提交都做一次合并,这样有利于你查看每一次的更改情况编写每一次冲突的解决方案。

因此我们在协同开发的时候,一般操作如下:

在topic(主题)分支要经常更新master(主)分支上的最新代码,以便同步当前分支最新状态,此时我们应该使用rebase。以master作为当前分支的基石,如果当前这个主题分支是你一个人开发的时候,这时是不会产生冲突的。(注:主题分支永远是领先于master分支的)

当我们要将主题分支合并到master分支的时候,我们使用merge(注:此时的主题分支是领先于master分支的)

这里我写一个我常用的工作流程:


// 当前处在reserve分支 提交你的更改并切换到master分支上
git commit -m 'xxxxxx'

git checkout master

// 获取最新的主分支代码 git pull addressName master

// 再回到功能分支上 并且把最新的主分支rebase进去 若有冲突在此时解决
git checkout reserve

git rebase master

// 这里可能会用到的命令:冲突解决完之后,使用git add <file-name> 来标记冲突已解决,执行此命令继续:
git rebase --continue
如果中间遇到某个补丁不需要应用,可以用下面命令忽略:
git rebase --skip
如果想回到rebase执行之前的状态,可以执行:
git rebase --abort

// 再切换到主分支进行合并 提交即可
git checkout master

git merge reserve

git push addressName master

复制代码

这样做的好处是,远程主干上的历史永远是线性的。每个人在本地分支解决冲突,不会在主干上产生冲突。

结束

我认为以上所述在平时的开发中是几乎都可以应对的了,关于回退版本之类的我在此前的git操作基础中是有的,可以翻阅查看。若以上有描述不清或者描述错误的请指出,我会对它再做出新的修改。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享