Git 分支管理

分支创建与合并

master分支

创建Git仓库之后,会有一个默认的分支叫主分支,即master分支,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

每次提交,master分支都会向前移动一步,随着不断提交,master分支的线也越来越长。

创建新分支

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

Git创建一个分支很快,因为只需要增加一个 dev 指针,再改变一下 HEAD的指向即可,工作区的文件都没有任何变化!

在新分支上进行开发

从现在开始,对工作区的修改和提交就是针对 dev 分支了,比如新提交一次后,dev 指针往前移动一步,而master 指针不变:

合并分支

假如我们在dev上的工作完成了,就可以把dev合并到master上。最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

Git合并分支也很快,只需要修改指针,工作区内容也不变。

删除分支

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

git branch 				# 查看本地所有分支,当前所在的分支使用* 表示
git branch    <name>	       # 创建分支
git checkout  <name>            # 切换分支
git checkout -b <name>         # 创建并切换分支
git merge <name>                 # 合并某个分支到当前的分支
git branch -d <name>	     # 删除分支

分支合并冲突

所谓的分支合并冲突指的是,在两个分支上对同一个文件进行的修改在合并时发生冲突的情况,无法合并。

解决冲突的办法就是手动将冲突文件修改为我们最终希望的情况,之后再提交并合并。

例如:

  • 新建分支feature1:

    git checkout  -b feature1
    

    feature1分支上 readme.txt文件中修改为feature1 branch add line1,之后依次执行:

    git add readme.txt
    git commit -m "feature1 branch add"
    
  • 切换到master分支:

    git checkout  master
    

    此时,可以看到如下的信息:

    Your branch is ahead of 'origin/master' by 1 commit.
      (use "git push" to publish your local commits)
    

    Git还会自动提示我们当前master分支比远程的master分支要超前1个提交。

    master分支上把readme.txt文件的修改为:master branch add line1,然后执行:

    git add readme.txt
    git commit -m "master branch add"
    

    现在,master分支和feature1分支各自都分别有新的提交,变成了这样:

    这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突:

    git merge feature1
    

    则会出现提示:

    Auto-merging readme.txt
    CONFLICT (content): Merge conflict in readme.txt
    Automatic merge failed; fix conflicts and then commit the result.
    

    这意味着无法完成自动合并,此时使用git status 也可以看到发生冲突的文件,例如:

此时查看文件readme.txt,内容如下所示:

Git用<<<<<<<=======>>>>>>> 标记出不同分支的内容,此时就需要我们进行手动修改,将这个文件中的内容改为我们最终想要的样子,例如:confict fixed line1

之后执行:

git add  readme.txt
git commit -m "conflict fixed"

master分支和feature1分支变成了下图所示:

使用git log --graph可以查看分支合并的情况。

分支管理策略

主分支Master

代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布。

Git主分支的名字,默认叫做 Master。它是自动建立的,版本库初始化以后,默认就是在主分支在进行开发。

开发分支Develop

主分支只用来分布重大版本,而日常开发应该在另一条分支上完成。我们把开发用的分支,叫做Develop

如果想正式对外发布,就在Master分支上,对Develop分支进行合并。

团队合作的分支看起来就像这样:

每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

临时性分支

MasterDevelop分支可以称为常设分支,除了常设分支之外,还有一些临时性分支:

  • 功能 feature 分支
  • 预发布 release 分支
    • 修补 bugfixbug 分支

这三种分支都属于临时性需要,使用完以后,应该删除,使得代码库的常设分支始终只有MasterDevelop

功能分支

功能分支是为了开发某种特定功能,从Develop分支上面分出来的。开发完成后,要再并入Develop

功能分支的名字,可以采用feature-*的形式命名。

如果正在开发的功能突然不需要了,那么需要将当前的Feature分支删除掉,此时因为新的功能分支并没有合并过,于是删除时应该强行删除:

git branch -D <name>			# 强行丢弃一个没有被合并过的分支

预发布分支

预发布分支是指发布正式版本之前(即合并到Master分支之前),我们可能需要有一个预发布的版本进行测试。

预发布分支是从Develop分支上面分出来的,预发布结束以后,必须合并进DevelopMaster分支。它的命名,可以采用release-*的形式。

修补bug分支

软件正式发布以后,难免会出现bug。这时就需要创建一个分支,进行bug修补。

修补bug分支是从Master分支上面分出来的。修补结束以后,再合并进MasterDevelop分支。它的命名,可以采用fixbug-*的形式。

假设现在正在Develop分支上进行开发,开发工作没有完成,突然间接到修复bug的任务。

  • 需要将Develop分支的现场进行保存:

    git stash 				# 保存当前的工作现场,以便以后恢复现场后继续工作
    
    
  • 确认是在哪个分支上修复bug,假设是在Master上修复bug,那么首先要切换到Master分支上,再从Master创建临时分支:

    git checkout master						# 切换到master分支
    git checkout -b fixbug-404				# 从master分支上创建临时分支fixbug-404
    
    
  • 修复bug,修复完成之后,到Master分支上进行合并,合并完成后删除fixbug-404分支:

    git checkout master									 # 切换到master分支
    git merge --no-ff -m "merged bug fix 404" fixbug-404 # 合并fixbug-404分支到master分支
    git branch -d fixbug-404							 # 删除fixbug-404分支
    
    
  • bug修复完成后,我们回Develop分支继续干活:

    git checkout develop			# 切换到develop分支							
    
    

    此时,我们希望能够恢复到原来的保存到现场环境,在原来的基础上继续开展工作,恢复现场环境的方式有两种:

    git stash apply         # 恢复stash环境
    git stash drop			# 将stash内容删除
    
    

    另一种方式是:

    git stash pop         # 恢复stash环境的同时把stash内容删除
    
    

    假设我们保存了多个现场环境,那么我们首先,应该看一下有哪些stash环境:

    git stash list				# 查看保存了哪些stash环境
    
    

    然后,恢复到指定的stash环境:

    git stash apply stash_id   # 恢复到指定的stash环境
    
    
  • master分支上修复了bug后,我们要想一想,develop分支是早期从master分支分出来的,所以,这个bug其实在当前develop分支上也存在,那么此时如何复制fixbug-404提交的修改,Git专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支:

    git checout develop             # 切换到develop分支
    git cherry-pick commit_id    	# 将指定提交的修改复制到当前的分支
    
    

多人协作

查看远程仓库信息

当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin
查看远程库的信息:

git remote			# 查看远程库信息
git remote -v       # 查看远程库的详细信息

例如:

上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

推送分支

推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

git push origin master        # 将本地的master分支推送到远程库中的master分支
git push origin dev           # 将本地的dev分支推送到远程库中的dev分支

但是,并不是一定要把本地分支往远程推送:

  • master分支是主分支,因此要时刻与远程同步;
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,皆有你定。

抓取分支

多人协作时,大家都会往masterdev分支上推送各自的修改。

当在不同目录或者另一台电脑上执行git clone的时候,默认只能看到本地的master分支。

当另一个人要在dev分支上开发,就必须创建远程origindev分支到本地:

git checkout -b dev origin/dev     # 根据远程的dev分支创建本地的dev分支

现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:

如果别人已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:

git push origin dev				# 将dev分支推送到远程仓库

有可能会造成推送失败,因为别人的最新提交和你试图推送的提交有冲突,解决办法是将远程最新的origin/dev抓取下来,然后,在本地合并,解决冲突,再推送:

git pull

如果出现:

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

原因是没有指定本地dev分支与远程origin/dev分支的链接,可以根据提示,设置devorigin/dev的链接:

git branch --set-upstream-to=origin/dev dev    # 设置本地dev与远程dev分支的链接

再次执行git pull,手动修改冲突,修改完成之后进行推送:git push origin dev

所以当多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。

posted @ 2019-08-25 19:02  youngliu91  阅读(102)  评论(0)    收藏  举报