【Git】分支管理

本篇博客的环境为 Ubuntu/linux

前言

在 Git 中,分支(branch)是一个独立的开发线路。允许在不影响主线(通常是mainmaster分支)的情况下进行修改和开发
主线就是实际发布的版本,但一个项目可能需要更新迭代,开发新功能或者维护修bug,所以肯定会基于主线进行修改,但又不可能让用户使用还在开发的,不完全的版本,分支就可以解决这样并发开发的问题,当分支完成开发后,再合并到主线中。
.git目录结构中,HEAD指向当前分支,而master指向主分支的最近一次提交的commit id

分支可以理解为一条时间线,每一次提交都是一个时间点
在这里插入图片描述
如图,随着不断地提交,master分支都会向前移动一步,分支的线也会越来越长,而HEAD指向master分支,即当前分支

分支基础操作

创建分支

创建分支的命令为:

git branch [分支名]

查看有哪些本地分支

git branch

示例:

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch
* master
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch dev
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch
  dev
* master

*的表示当前处于该分支,即HEAD指向的分支
新创建的分支都是基于当前的master分支

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ ls .git/refs/heads/
dev  master
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat .git/refs/heads/*
eac56023195eaf5a3dad49e7d60f93cd2c4e6f6e
eac56023195eaf5a3dad49e7d60f93cd2c4e6f6e

可以看到devmaster都指向最新一次提交的commit id
在这里插入图片描述

切换分支

切换分支命令如下:

git checkout [分支名]
git checkout -b [分支名] #创建分支并切换

示例:

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout dev
Switched to branch 'dev'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch
* dev
  master
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat .git/HEAD 
ref: refs/heads/dev

可以看到HEAD已经指向了dev分支
在这里插入图片描述


接下来在dev分支下进行修改,并提交

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ vim ReadMe 
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
i am coding
i am coding
i am coding
coding on dev branch
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git add .
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git commit -m "md ReadMe:coding on dev branch"
[dev c8acfad] md ReadMe:coding on dev branch
 1 file changed, 1 insertion(+)
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout master 
Switched to branch 'master'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
i am coding
i am coding
i am coding

我们会发现,在dev分支上提交的内容无法在master分支上观察到,这是因为二者指向的提交已经不一样了

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat .git/refs/heads/dev
c8acfad3696bb5a7dd1a1cd11a2facb9e6bd4bda
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat .git/refs/heads/master 
eac56023195eaf5a3dad49e7d60f93cd2c4e6f6e

在这里插入图片描述
因为matser还指向原先的提交点,所以查看的也是之前的版本

合并分支

dev分支完成开发后,就需要将内容合并到master分支上,合并的命令如下:

git merge [分支]

使用该命令,就是将指定分支的提交内容合并到当前分支
示例:

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout master
Already on 'master'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git merge dev
Updating eac5602..c8acfad
Fast-forward
 ReadMe | 1 +
 1 file changed, 1 insertion(+)
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
i am coding
i am coding
i am coding
coding on dev branch

Fast-forward代表快进模式,也就是直接把master指向dev的当前提交,所以合并速度很快,还有其他模式的合并方式,后续讲解
在这里插入图片描述

删除分支

当一个分支完成开发,master分支也将其内容合并后,该分支的任务就完成了,那么可以将该分支删除,减少分支数,便于管理。
注意如果处于某分支下,是不能删除当前分支的
删除分支的命令如下:

git branch -d [分支名]
git branch -D [分支名] #强制删除

示例:

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch -d dev
Deleted branch dev (was c8acfad).
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch
* master

此时状态图如下:
在这里插入图片描述
因为创建、合并和删除分支都很快,所以 Git 鼓励使用使用分支完成某个任务,并合并后删除分支,这和直接在master分支上工作效果一样,但过程更安全

可能会出现分支还没合并到主分支,但该分支开发内容被弃用的情况,-d删除该分支会提示分支未合并
此时需要使用-D选项强制删除

合并冲突

在实际开发中,可能存在很多分支
在这里插入图片描述
如图,dev1dev2基于同一个master主支线的提交进行后续开发,dev1先完成开发,并合并进了master。此时master的内容已经和dev2保存的不同,此时合并就会出现合并冲突,Git 不知道要保留哪些代码

示例:

  1. 创建dev分支完成开发
#查看ReadMe内容
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe
hello git
#创建并切换分支
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout -b dev
Switched to a new branch 'dev'
#完成开发并提交
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ vim ReadMe 
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
dev branch coding...
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git add .
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git commit -m "md ReadMe:dev branch coding"
[dev 0e0b57d] md ReadMe:dev branch coding
 1 file changed, 1 insertion(+)
  1. master 也同步进行开发
#切换回master分支
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout master 
Switched to branch 'master'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
#完成开发并提交
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ vim ReadMe 
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
master branch coding...
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git add .
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git commit -m "md ReadMe:master branch coding"
[master e0afb54] md ReadMe:master branch coding
 1 file changed, 1 insertion(+)

此时状态图如下:
在这里插入图片描述
3. 使用master合并dev

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git branch 
  dev
* master
#合并
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git merge dev
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.
#合并发生冲突,Git标记冲突部分
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
<<<<<<< HEAD
master branch coding...
=======
dev branch coding...
>>>>>>> dev

发生合并冲突后,Git 并不知道要保留哪部分代码,所以索引都保留,然后标记出冲突的部分
Git 使用 <<<<<<========>>>>>>>>标记不停分支的冲突内容
我们必须手动调整冲突代码,并且调整完后还需要再次提交修正后的结果(一定要再次提交!!!)

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ vim ReadMe 
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
master branch coding...
dev branch coding...
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git status
On branch master
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:   ReadMe

no changes added to commit (use "git add" and/or "git commit -a")
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git add .
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git commit -m "solve the merge conflict"
[master c132cde] solve the merge conflict

此时状态图如下:
在这里插入图片描述
使用带参数的git log可以看到分支的合并情况

git log --graph --pretty=oneline --abbrev-commit

在这里插入图片描述
左侧有类似时间线的线段,*表示当时的工作分支

分支管理策略

通常合并分支时,Git 一般会采用Fast forward模式
直接将master指向合并分支的最新一次提交的commit id
Fast forward模式下,删除分支后,查看分支历史,会丢失分支信息,看不出来最新提交到底是 merge 的还是正常提交的
在合并冲突时,通过日志查看的明显不是Fast forward模式,从分支历史上可以很清晰的看到分支信息,新提交是通过 merge dev 分支进来的。该模式称为非Fast forward(no-ff)模式
Git 允许强制禁用Faste forward模式,就是在合并时带上--no-ff选项

git merge --no-ff -m "描述" [分支名]

下图是两种模式的状态图差异:
在这里插入图片描述
对于没有合并冲突的合并,--no-ff模式可以保留合并信息,而Fast forword则没有合并信息

分支策略

实际开发有一些基本原则需要遵守

  1. master分支是主分支,实际发布的分支,应该是非常稳定的,不能直接在该分支上开发
  2. 每个新功能的开发/bug修改等都要新建分支完成,完成开发并测试再合并回 master
    3. 合并时,可以先在工作分支合并 master 分支,确认无误后,再切换到 master 分支合并指定分支

综上,团队合作的分支看起来就像这样:
在这里插入图片描述

bug 分支

情景如下:
假如现在在dev2分支上开发,开发到一半,突然master分支上有bug,需要解决。在 Git 中,每个 bug 都可以通过一个新的临时分支来修复,修复后再合并分支,最后将临时分支删除


当前dev2的代码在工作区开发了一半,还无法提交。此时如果切换到master分支,会影响master分支的工作区内容

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout -b dev2
Switched to a new branch 'dev2'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ vim ReadMe 
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout master 
M	ReadMe
Switched to branch 'master'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
master branch coding...
dev branch coding...
i am coding...

Git 提供 git stash命令,可以将当前的工作区信息进行存储,被存储的内容可以在将来某个时间恢复出来

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout dev2
M	ReadMe
Switched to branch 'dev2'
#使用stash存储工作区修改
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git stash
Saved working directory and index state WIP on dev2: c132cde solve the merge conflict
#此时工作区修改已经被存储起来,dev2和master都看不到修改
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
master branch coding...
dev branch coding...
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git checkout master 
Switched to branch 'master'
ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ cat ReadMe 
hello git
master branch coding...
dev branch coding...

使用如下命令查看存储

git stash list

ubuntu@VM-12-11-ubuntu:~/lesson/gitcode$ git stash list
stash@{0}: WIP on dev2: c132cde solve the merge conflict

使用如下命令恢复工作区修改,恢复的同时会把 stash 删除,只能恢复一次

git stash pop #类似队列那样,从小序号删除

也可以不删除 stash

git stash apply #恢复现场,但不删除stash
git stash drop #需要用该命令删除stash
git stash apply stash@{0} #指定恢复

以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值