分支是什么呢?
团队开发的过程中,每个人都会有一个不同于别人的分支,各自都在自己的分支上编写代码,等到需要的时候,再把各分支合并起来,这样既安全也不会相互影响。
一、创建与合并分支
在上一节中,我们在本地创建了一个Git仓库,但只有一个分支,就是 master 分支,它是主分支,HEAD指向 master ,master指向当前提交,所以,HEAD指向的就是当前分支。
每次提交,master都会向前移动一步,随着不断的提交,这条分支线会越来越长
当我们创建了新的分支,比如叫 myBranch ,git就会新建一个指针叫 myBranch,指向 master 相同的提交,在把HEAD指向 myBranch,就表示当前分支在 myBranch 上。
从现在开始,对工作区的修改和提交都是针对 myBranch 分支了,如果我们修改后再提交一次,myBranch指针就会向前移动一步,而master指针不变
当我们在myBranch分支上的工作完成后,就可以把myBranch合并到master,也就是把master指针移动到myBranch的当前提交。
当合并完成后,我们就可以删除掉myBranch分支,也就是把myBranch指针删除掉,然后我们就只剩下master分支了
OK,我们现在通过实际的例子来说明上面分支的使用。我们先看看当前分支:
$ git branch //查看分支
可以看到,目前我们只有一个master主分支,我们来创建一个bra分支:
$ git checkout -b bra
git checkout 命令加上-b参数,表示创建分支并切换,它相当于下面的两个命令:
$ git branch dev //创建分支
$ git checkout dev //切换到创建的分支
我们再次查看下当前分支情况
我们可以看到有两个分支,分别是master和bra,当前在bra分支上。
git branch命令会列出所有分支,当前分支前面会标注一个 * 号,现在我们在bra分支上对index.html做一些修改
保存退出后,我们进行提交
现在我们在bra分支上的工作完成,切换到master分支:
$ git checkout master
我们发现,刚才添加的第三个P标签不见了,这是因为刚才的提交时在bra分支上,而master分支此刻的提交点没有变化
现在我们可以使用 git merge 命令来将bra分支上的更改合并到master分支上:
$ git merge bra
然后我们再次查看index.html的内容
OK,在bra分支上添加的第三个P标签回来了,而当前我们是在master主分支上。大家可能注意到了在我们合并时,出现了 'Fast-forward',它告诉我们这次合并是'快进模式',也就是将master指针直接指向bra分支的提交,所以速度很快,当然除了这种模式,还有其他模式。
合并完成后,我们就可以删除bra分支了
$ git branch -d bra
然后我们再次查看分支情况:
现在只剩下master分支了。GIT鼓励我们使用分支来进行开发,下面我们来总结下上面使用过的命令:
查看分支: git branch
创建分支: git branch "branch name"
切换分支: git checkout "branch name"
创建并切换分支: git checkout -b "branch name"
合并某分支到当前分支: git merge "branch name"
删除分支: git branch -d "branch name"
二、 解决冲突
有时候我们在进行分支合并时,会遇到各种各样的问题,下面我们用实例来说明下。
我们先创建一个新的分支fea,在这个分支上对index.html再添加一个p标签,然后在这个分支上提交。
$ git checkout -b fea //创建并切换到fea分支
//对index.html做出修改
$ git add index.html //提交
$ git commit -m "modifyed and commit on fea branch"
切换到master分支上
$ git checkout master
上面的代码还提示我们当前的master分支比远程的master还要多2个提交,可以使用 git push 命令推送本地的提交
接下来,我们在master分支上对index.html做出修改,并提交修改
现在,master分支和fea分支都有了各自的提交
这个时候,git是无法进行快速合并的,只能把各自的修改合并起来,但这种合并可能会造成冲突。下面我们尝试着合并一下
看到了吗? Automatic merge failed,合并失败了。git告诉我们文件有冲突,必须手动解决,我们用 git status 来看下,也提示有问题
查看文件内容,也有提示
我们进入index.html进行修改,保存退出后,提交。
最后,我们删除fea分支
当git无法自动合并分支时,就必须手动去解决问题,再进行合并。我们还可以使用 git log --graph 来查看分支合并图
三、分支管理
上面我们了解了合并分支,git会使用 Fast forward 模式,在这种模式下合并,删除分支后,会丢失分支信息,所以我们强制禁用 Fast forward模式,在合并分支的时候使用 --on--ff
现在我们新建并切换到dev分支上
修改index.html文件并提交
切换到master分支
OK,关键在这里,我们合并dev分支, 使用--no--ff参数,表示禁用 Fast forward
$ git merge --no-ff -m "merge with no-ff" dev
合并后,我们使用git log 查看分支历史
在实际的开发中,master分支是主分支,是非常稳定的,仅仅只能用来发布新的版本,平时不能在它上面工作。
在一个项目开始的时候,我们可以在git上新建一个dev分支,那么如果团队有3个人,分别是A,B,C,那么他们都分别会有自己的分支,大家都在自己的分支上干活,完成之后都提交到dev分支上,但这是不稳定的,经过多次的测试,发现bug,修改,再次合并到dev分支,经过很多次的迭代,版本稳定了,OK,现在可以把dev分支合并到master上进行发布了。
四、BUG分支
我们在工作时会遇到各种各样的BUG,有时候,有些bug需要立刻修复,但是你手上的任务还没有完成,怎么办?这时,Git为我们提供了 stash 功能,它可以将我们当前分支上的任务存储起来,放在另外一个地方,我们就可以放心的切换到有bug的分支去进行修复。
当前有如下的情景,我在dev分支上工作,写了一些代码,但并没有提交
这时,有任务来了,需要去Fix一个编号为88的bug,我们可以在master分支上创建一个临时的分支来修复这个bug,OK,我们利用 stash 功能将当前的工作保存起来。
我们在利用 status 来查看下当前工作区状态
我们看到当前在dev分支上,而且工作区是干净的,而刚刚我们在dev分支上做的工作并没有提交。
好了,我们现在需要去master分支上创建一个fix88分支来修复bug,先切换到master分支
创建fix88分支来修复bug
我们进入index.html修复bug,并提交
切换到master分支,合并修改,并删除fix88分支
修复bug后的index.html内容如下,我们在最后一个p标签里,把原来的内容加上了一个span标签,并添加了另外一个span标签,插入了一些说明的内容。
然后我们再来看看当前的分支状态和工作区状态
切换到我们原来的工作分支dev上,并查看工作区状态
工作区是干净的,下面我们使用 git stash list 命令来查看下刚刚我们隐藏的工作场景
OK,我们来恢复我们在dev分支上的工作场景 ,这里有两个方法可以来恢复
一是使用 git stash apply,这个方法恢复之后,并不会删除stash里的内容,还需要使用 git stash drop来删除 stash里的内容
二是使用 git stash pop ,这个方法恢复之后,会直接删除stash里的内容
可以看到工作场景恢复了,我们再来看看stash里的内容,git stash list
没有了。
我们还可以多次使用stash,最后需要恢复的时候,使用下面的命令:
git stash apply stash@{0}
修复bug可能是我们会长期做的事,它会随时出现,而bug需要立刻解决,这时,我们就需要把现有的手上的工作stash下,然后创建一个新的分支去修复bug,提交合并后删除这个分支,最后再使用 git stash pop 来恢复我们的工作场景。
五、Feature分支
我们在开发的过程中,可能随时会接到新的任务,为整个工程添加新的功能,这时,我们最好的做法就是新建一个feature分支,在这个分支上开发,合并,最后删除该分支
假设有这样一个场景,我们接到了Boss的一个任务,要在当前工程上开发一个新的功能,命名为feature-new01,ok, let's go work...
创建新功能分支feature-new01
在当前新功能分支上,我们对index.html添加一个新的东西
提交修改
切换回dev分支,并准备进行合并。(新功能合并到dev工作分支上)
这时,Boss说新能取消,不再开发,所以我们必须删除,如果我们使用 git branch -d feature-new01 ,这时git会提示我们,这个分支的内容还没有被合并,不能删除,所以,我们需要使用 git branch -D feature-new01 来强行删除这个分支。
如果团队需要在现有工程上开发新的功能,请新建一个分支进行,完成后,提交,并切换回团队工作分支(不是master),进行合并,如果在合并之前需要删除,使用 git branch -D <branch name>来强行删除,如果已合并,请参考前面的版本回退。
六、多人协作
当我们从远程仓库克隆项目时,实际上是把本地master分支和远程master分支对应起来了,远程仓库的默认名称是 origin ,要查看远程仓库的信息,使用 git remote
或者我们可以使用 git remote -v 来显示更详细的信息
推送分支,就是把该分支上的所有本地提交都推送到远程仓库,推送时,需要指定本地分支,比如我们需要推送master分支,使用 git push origin master
如果要推送其他分支,如dev,则可以使用 git push origin dev
但不是所有的本地分支都需要推送到远程仓库
master分支是主分支,它是需要推送到远程的。
dev分支作为开发分支,也是需要推送到远程分支的。
处理bug的某些分支,因为处理完成之后会被删除,所以就么有必要了,除非团队需要,比如可以查看那些人在什么时候处理了哪些bug
新功能的开发分支,如feature分支,视自己的团队情况而定。
所以,我们自己在本地的分支,是否推送,完全取决于我们自己,某些分支完全就可以放在自己的本地电脑上玩。
多人团队开发时,团队成员都会往master和dev分支上推送自己的修改,下面我们来模拟一个2人的团队开发,我在自己的Mac上的虚拟机中装了一个Ubuntu,我们在这里来模拟。
在Ubuntu上装好git,然后从github上克隆gitTest项目。(注意:在这之前必须把当前机器的SSH Key添加到github)。
创建用户
当前,我们在远程仓库中有两个分支,分别是mastet主分支和dev开发分支,但其他开发成员从远程克隆项目下来之后,会发现只有master分支,看刚才我们在Ubuntu上克隆的项目
我们看到只有一个master分支,如果团队成员lz需要在dev分支上进行开发,那么必须创建远程的dev分支到本地,可以使用 git checkout -b dev origin/dev 命令创建
现在,团队成员lz就可以在dev分支上进行开发,并提交,push到远程。我们来试试
修改完成,最后一行的div是团队成员lz在本地dev分支上添加的。我们保存退出并提交,最后push到远程仓库
OK,现在团队成员lz对index.html做了添加并推送到了远程,当另外一个成员也对这个文件做了修改,并推送,是一个怎么样的情况呢?我们来试试
呀,提示推送失败了,原因是刚才lz已经对index.html文件做除了修改并推送到了dev分支,我再提交推送就会出现冲突,这时我们需要先把最新的修改pull下来到我的本地,合并修改后再推送
pull也失败了,原因是我们需要将本地dev和远程的origin/dev建立链接
再次pull
成功了,我们打开inex.html看看
看到了吗?刚才成员lz的代码和我刚才写入的代码都在里面了,而且git也给我们做出了提示,如果现在合并会起冲突,我们需要手动调整代码,然后再提交推送
通常情况下,在团队协作开发中,我们可以先推送自己的修改,使用 git push origin <branch name>
如果推送失败,说明远程的分支比本地更新,我们需要使用 git pull 来合并
如果 git pull 提示 “no tracking information”, 说明我们本地的分支没有和远程进行关联,我们需要使用
git branch --set-upstream-to=origin/dev dev 来进行关联,之后再次使用 git pull
如果存在冲突,在本地解决冲突的代码,最后 git push origin <branch name>。
来源:oschina
链接:https://my.oschina.net/u/2399867/blog/650685