Git系列Git分支管理

Posted 一宿君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Git系列Git分支管理相关的知识,希望对你有一定的参考价值。

一、什么是分支?

几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。有人把Git的分支模型称为必杀技特性。而正是因为它,将Git从版本控制系统家族中区分出来了。

二、分支管理的基本命令

创建分支:

$ git branch dev  #创建分支

切换分支:

$ git checkout dev  #切换至dev分支

当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的新分支工作目录的内容, 所以多个分支不需要多个目录,仍然保持与主分支master一致即可。

简化创建和切换分支:

$ git checkout -b dev   #表示创建dev分支,并立即切换至dev分支;如果存在dev,则直接切换

我们注意到切换分支使用git checkout <branch>,而前面讲过的撤销修改则是git checkout -- <file>,同一个命令,有两种作用,确实有点令人迷惑。

实际上,创建和切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:

$ git branch dev  #创建dev分支
$ git switch dev   #switch切换至dev分支
$ git switch -c dev  #也可以一步到位,-c代表create创建

列出本地所有分支:

$ git branch  #列出所有本地分支			
* dev       #星标代表是当前分支
  master 

列出远程仓库的所有分支:

$ git branch -r  #列出远程仓库的所有分支
  origin/HEAD -> origin/master
  origin/master

列出所有本地分支和远程分支:

$ git branch -a   #显示本地和远程的所有分支
* dev             #星标代表是当前分支
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

删除分支:

$ git branch -d (branchname)   #删除指定分支

合并分支内容:

$ git merge dev    #意思是在当前分支下,合并分支dev的内容

三、分支作用演示与

在前面我们已经学习了版本回退,也就是在每次提交的时候,Git都会把它们串成一条时间线,这条时间线就是一个分支。截至目前,只有一条时间线,在Git里这个分支叫做主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,HEAD指向的就是当前分支(HEAD指向的也就是最新提交的那个分支)。

3.1、HEAD与master指向

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点,如下图所示:

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

3.2、新建dev分支

当我们新建一个dev分支时,也就睡Git新建了一个指针叫dev,指向master相同的提交,我们切换至新建的dev分支上,HEAD指针会自动从master指向dev,就表示当前分支在dev上:

$ git checkout -b dev    #新建dev分支,并立即切换至dev
Switched to a new branch 'dev'


Git创建分支很快,因为除了增加一个dev指针,就改了下HEAD的指向,工作区的文件没有任何变化!!!

我们上述已经切换至新的分支dev了,其实我们可以理解为,dev分支就是克隆的master主分支,当前dev分支中的所有文件内容都和master主分支一模一样,因为master主分支是一个本地仓库的模板,一般我们不允许直接在master主分支进行操作修改,后续我们也都是新建分支进行操作,经过测试调优,最终合并到本地的master主分支,然后再由master主分支推送到远程仓库的master主分支:

先看下master分支和dev分支的内容是否一致:

itwbs@matebook13-mini MINGW64 /d/gitspace/learngit (master)   #master主分支下查看
$ ls
readme.txt  test.txt  #内容一致

itwbs@matebook13-mini MINGW64 /d/gitspace/learngit (dev)   #dev分支下查看
$ ls
readme.txt  test.txt  #内容一致

**切换至dev分支,从现在开始,对工作区的修改和提交就是针对dev分支了,比如我们新建一个文件test2.txt,然后提交至本地仓库,查看dev指针走向: **

$ touch test2.txt  #新建test2.txt文件

$ ls
readme.txt  test.txt  test2.txt

$ git add test2.txt   #添加到暂存区

$ git commit -m "dev new add test2.txt"   #提交到dev本地仓库中
[dev 4229aad] dev new add test2.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test2.txt

3.3、合并dev分支

假如我们在dev分支上的工作完成了,切换至master主分支,查看文件:

$ ls
readme.txt  test.txt    #发现没有dev分支建的test2.txt文件

这个时候,如果我们想要在master主分支也要有dev分支的内容,那就在当前master主分支合并dev分支,如下:

$ git merge dev   #在当前master主分支合并dev分支
Updating b1fe536..4229aad
Fast-forward
 test2.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test2.txt
 
 $ ls    #再次查看就有了test2.txt文件了
readme.txt  test.txt  test2.txt

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。

Git是怎么合并的呢?其实很好理解,就是直接把master主分支的指针指向了dev分支的当前最新提交,就完成了合并,如下图:

可以看出合并分支也是非常快的,就改了改指针,工作内容也不变!

3.4、合并后,删除dev分支

合并完分支后,就可以放心的删除dev分支了,删除dev分支就是把dev指针的指向给删除掉,然后就只剩下master分支了,而且HEAD又重新指向了master主分支,如下图:

$ git branch  #查看本地仓库所有分支
  dev
* master   #星标代表是当前指向master注分支

$ git branch -d dev   #删除dev分支
Deleted branch dev (was 4229aad).

$ git branch   #然后dev分支就么了
* master

3.5、解决合并冲突

合并分支往往不是一帆风顺的,也会存在冲突!!!

新建feature分支:

$ git switch -c feature    #新建feature分支,并立即切换
Switched to a new branch 'feature'

向test2.txt文件新添加内容:

$ vim test2.txt  #编辑test2.txt文件,添加如下内容
Create a new branch is quick AND simple.

提交到本地Git仓库:

$ git add test2.txt   #添加暂存区
warning: LF will be replaced by CRLF in test2.txt.
The file will have its original line endings in your working directory

$ git commit -m "feature commit test2.txt"    #提交到本地仓库
[feature ebc5a6f] feature commit test2.txt
 1 file changed, 1 insertion(+)

这个时候我们切换到master主分支:

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

可以看出,Git告诉我们我们当前本地仓库中的master主分支,超前远程仓库的master主分支一个提交。

在master分支中,向test2.txt文件也添加一行内容

$ vim test2.txt  #编辑

$ cat test2.txt  #查看内容
Creating a new branch is quick & simple.

也提交到本地仓库:

$ git add test2.txt   #添加到暂存区
warning: LF will be replaced by CRLF in test2.txt.
The file will have its original line endings in your working directory

$ git commit -m "master commit test2.txt update & simple"   #提交到本地仓库
[master 53a6882] master commit test2.txt update & simple
 1 file changed, 1 insertion(+)

仔细看哈,目前连个分支都有了新的提交commit,如下图:

这个时候我们在master主分支把feature分支合并了,看会出现啥情况:

$ git merge feature   #合并feature分支
Auto-merging test2.txt
CONFLICT (content): Merge conflict in test2.txt
Automatic merge failed; fix conflicts and then commit the result.

可以看出test2.txt文件 发生冲突了,查看当前状态git status

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   test2.txt

no changes added to commit (use "git add" and/or "git commit -a")

可以看出原因是test2.txt文件both两者都修改了,然后合并的时候就导致HEAD不知道该指向谁了,然后就冲突了!!!

此时我们查看test2.txt文件的内容:

$ cat test2.txt  #查看内容
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Create a new branch is quick AND simple.
>>>>>>> feature

那啥,如果发生冲突,Git会自动帮我们在冲突文件中记录是哪些操作导致的冲突,上述表达的很明显了,就是由于HEAD最新指向的master主分支,修改了内容为Creating a new branch is quick & simple.,而feature分支修改内容为Create a new branch is quick AND simple.

Git用<<<<<<<=======>>>>>>>记录不同分支的不同操作,此时我们为了结局冲突,可以手动编辑test2.txt文件,为如下内容(其实也就是我们希望看到的最终合并版本),然后再做一次提交:

$ vim test2.txt  #重新编辑test2.txt文件为我们想要的最终合并结果

$ cat test2.txt
Creating a new branch is quick & simple.   #master主分支做的修改
Create a new branch is quick AND simple.   #feature分支做的修改

$ git add test2.txt  #再次添加到暂存区

$ git commit -m "conflict fixed"   #再次提交到本地仓库
[master 29e8de2] conflict fixed


真的解决了吗?可以查看当前状态:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

没毛病,真解决了,而且Git还告诉你,当前本地仓库的master主分支比远程仓库的master超前了4个commit,提示你将本地仓库最新版本推送到远程并合并。

而且还可以使用命令查看分支的合并情况:

$ git log --graph --pretty=oneline --abbrev-commit
*   29e8de2 (HEAD -> master) conflict fixed
|\\
| * ebc5a6f (feature) feature commit test2.txt
* | 53a6882 master commit test2.txt update & simple
|/
* 4229aad dev new add test2.txt
* b1fe536 (origin/master, origin/HEAD) update test.txt.
* cd180c8 update test.txt.
* 1d07bf6 add new test.txt
* 89789d5 Git tracks changes of files
* bf9deee git tracks changes
* 4f489e7 append GPL
* 0931364 wrote a readme file

没办法就是那么强大!!!
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。

小结:

  • Git鼓励大量使用分支:
  • 查看分支:git branch
  • 创建分支:git branch <name>
  • 切换分支:git checkout <name>或者git switch <name>
  • 创建+切换分支:git checkout -b <name>或者git switch -c <name>
  • 删除分支:git branch -d <name>
  • 合并某分支到当前分支:git merge <name>
  • 查看分支合并图:git log --graph

以上是关于Git系列Git分支管理的主要内容,如果未能解决你的问题,请参考以下文章

Git系列Git分支管理

Git系列四之分支管理

Git每天1分钟系列——Git建仓

Git 系列教程(13)- 分支管理

Git学习系列-Git基本概念

Git每天1分钟系列——(手把手教会为止)Git项目分支搭建