一、分支介绍

分支是git的特性之一,它使得代码可以有多中不同的方向和代码路线,协作过程中彼此之间互不影响,大大增加了代码库的灵活性。

一般来说,项目的开发模型为:给定主分支master用于统筹所有代码,其他的功能拆散在子分支上开发,最后都合并到master。例如一个用于用户登录功能的代码库,用户A开启分支完成账户注册,用户B开启分支完成用户授权,两者在开发期间互不影响,开发完成后合并到主分支上合并完成总功能。

中间蓝色的表示主分支,上下两条表示子分支,子分支在初始时分离,最后都合并于主分支。

git中和分支相关的操作使用branch命令完成,最简单的用法就是git branch,它用于查看当前所在分支,加上-v选项显示详细信息。

显示的分支中默认只显示本地分支,如需显示远程分支要加上-a选项。

一个要注意的是:远程分支和本地分支即使名字相同也不是一个分支,彼此独立,git远程仓库相关可以参考git remote用法

一个大型项目往往会有许多分支,例如openssl的分支:

[ma@ma openssl]$ git branch -va
* master                                     2de108d Save and restore the Windows error around TlsGetValue.
# ... 省略
  remotes/origin/OpenSSL_0_9_6-stable        645a865 Fixes so alerts are sent properly in s3_pkt.c
  remotes/origin/OpenSSL_0_9_7-stable        9cbf440 Fix incorrect command for assember file generation on IA64
  remotes/origin/OpenSSL_0_9_8-stable        7474341 Prepare for 0.9.8zi-dev
  remotes/origin/OpenSSL_0_9_8fg-stable      bfa33c7 Release OpenSSL 0.9.8g with various fixes to issues introduced with 0.9.8f
  remotes/origin/OpenSSL_1_0_0-stable        2700723 ms/uplink-x86.pl: make it work.
  remotes/origin/OpenSSL_1_0_1-stable        4675a56 apps/speed.c: Fix crash when config loading fails
  remotes/origin/OpenSSL_1_0_2-stable        d8908c3 Fix a bogus warning about an uninitialised var
  remotes/origin/OpenSSL_1_1_0-stable        6d3cfd1 Skip CN DNS name constraint checks when not needed
  remotes/origin/SSLeay                      dfeab06 Import of old SSLeay release: SSLeay 0.9.1b (unreleased)
  remotes/origin/master                      2de108d Save and restore the Windows error around TlsGetValue.
  remotes/origin/tls1.3-draft-18             669c623 Update PR#3925
  remotes/origin/tls1.3-draft-19             d4d9864 Update PR#3925

我们还可以通过git log --graph命令以图形化形式来查看分支演变:

最左边的两条线即显示了一个分支从创建到合并的过程。

二、创建分支

创建分支命令:git branch 分支名,例如git branch feature-login-auth-maqian。同时还可以使用git checkout -b 分支名创建分支,checkout用于切换分支,加上-b选项后会先创建该分支。

首先先从github上拉取一个代码库:

[work@localhost git]$ git clone git@github.com:maqianos/gitstudy.git
Cloning into ''gitstudy''...
[work@localhost git]$ cd gitstudy/
> ll
total 8
-rw-r--r--. 1 work root 17 May 24 16:02 master.md
-rw-r--r--. 1 work root 39 May 24 17:38 README.md

此时代码的分支信息为:

> git branch # 当前分支
* master
> git branch -a # 所有分支
* master # 本地分支
  remotes/origin/master # 远程分支

创建分支:

> git branch feature-login-auth-maqian # 创建分支
> git branch -a # 查看当前所有分支
  feature-login-auth-maqian
* master
  remotes/origin/master
> git checkout feature-login-auth-maqian # 切换到分支
Switched to branch ''feature-login-auth-maqian''
> git branch # 查看当前本地所有分支
* feature-login-auth-maqian
  master

三、合并分支

在子分支生成修改并提交:

> touch feature-login-auth-maqian.md
> git status -s
?? feature-login-auth-maqian.md
> git add feature-login-auth-maqian.md 
> git commit -m ''[ADD] featre: auth''

推送到远程分支:

# 注意写上分支名,默认是master,不要推到master上去了
> git push origin feature-login-auth-maqian
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 337 bytes | 6.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:maqianos/gitstudy.git
 * [new branch]      feature-login-auth-maqian -> feature-login-auth-maqian

子分支推到远程分支后,切换到主分支合并它:

> git checkout master # 切换到主分支
Switched to branch ''master''
Your branch is up to date with ''origin/master''.
> git fetch # 获取更新,由于分支是在本地推送过去的,所以本地就是最新
> ll # 没合并之前没有子分支创建的文件
total 8
-rw-r--r--. 1 work root 17 May 24 16:02 master.md
-rw-r--r--. 1 work root 39 May 24 17:38 README.md
> git merge feature-login-auth-maqian # 合并分支
Updating 0fc1fe3..3871204
Fast-forward
 feature-login-auth-maqian.md | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 feature-login-auth-maqian.md
> ll # 合并后出现子分支的文件
total 8
-rw-r--r--. 1 work root  0 May 24 17:56 feature-login-auth-maqian.md # **
-rw-r--r--. 1 work root 17 May 24 16:02 master.md
-rw-r--r--. 1 work root 39 May 24 17:38 README.md

四、解决冲突

上面的合并是一种最理想的合并,即A分支中的修改在B分支中没有被修改(两个分支修改的内容不重复),对于这种情况,git能自动识别出来并自动合并内容。但是对于两个不同分支同时修改了代码的同一行,合并时就会出现冲突。因为git无法判定哪个修改是有效的,此时需要手动解决冲突。

feature-login-auth-maqian分支中对代码进行修改:

> git co feature-login-auth-maqian # 切换分支
Switched to branch ''feature-login-auth-maqian''
> echo "HelloWorld-feature" > feature-login-auth-maqian.md # 添加更改
## 提交代码 
> git add *
> git commit -m ''[UPDATE] auth''
[feature-login-auth-maqian 8d49ce2] [UPDATE] auth
 1 file changed, 1 insertion(+)
> git push origin feature-login-auth-maqian # 提交到远程分支
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 357 bytes | 357.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:maqianos/gitstudy.git
   3871204..8d49ce2  feature-login-auth-maqian -> feature-login-auth-maqian

切换到master也更改代码:

> git co master
Switched to branch ''master''
Your branch is ahead of ''origin/master'' by 1 commit.
  (use "git push" to publish your local commits)
> git fetch
> echo "HelloWorld-master" > feature-login-auth-maqian.md 
> git add *
> git commit -m ''[UPDATE] atuh''
[master aac14dd] [UPDATE] atuh
 1 file changed, 1 insertion(+)

合并代码:

> git merge origin/feature-login-auth-maqian
Auto-merging feature-login-auth-maqian.md
CONFLICT (content): Merge conflict in feature-login-auth-maqian.md
Automatic merge failed; fix conflicts and then commit the result.

此时就提示两个文件有冲突了,因为两个文件都修改了同一处代码,git无法判断以哪个为准,所以合并失败。

看一下代码文件:

<<<<<<< HEAD
HelloWorld-master
=======
HelloWorld-feature
>>>>>>> origin/feature-login-auth-maqian

一个有趣的现象是,当我正在使用vscode编辑这篇文章的时候,我把上面这段冲突的代码复制进来之后,vscode自动帮我处理了成了下面的样子:

简单明了的演示免去了我一顿口舌。

所以现在要做的就是删掉无用代码,然后选择想要的版本手动更新:

# 修改后的代码
> cat feature-login-auth-maqian.md 
HelloWorld-master
HelloWorld-feature

重复之前的步骤add commit push即可解决冲突。

最后修改:2018 年 12 月 16 日
喜欢就给我点赞吧