Git 分支管理

理解分支

本章开始介绍Git的杀手锏之一:"分支"

具体情景

分支就像玄幻电影里的"分身术"。当你正在电脑前努力学习C++的时候,你的分身正在努力学习JAVA。

分身和你之间互不影响。

不过,在某一天,你将分身合并了,于是最终你即学会了C++,又学会了JAVA




分支的本质

  • 我们一系列的提交会形成一条时间线,这条时间线就是一个分支

  • 默认情况下只有一条时间线,即主分支(master)




HEAD指针

  • HEAD严格来说不是指向提交,而是指向当前所在分支

  • master才是指向提交的(准确来说,是主分支提交)

随着不断提交,master分支的时间线越来越长,而HEAD 始终指向当前分支。





基础分支操作

创建分支

Git支持我们查看或者创建其它分支,这里我们来创建第一个自己的分支dev

Shell 复制代码
# 查看当前本地所有分支
$ git branch
* master

# 新建分支dev
$ git branch dev

# 再次查看分支
$ git branch
  dev
* master

补充*表示当前HEAD指向的分支,即当前工作分支


另外,还可以通过目录结构发现新的dev分支

Shell 复制代码
# 查看分支引用文件
$ ls .git/refs/heads/
dev  master

# 查看目录结构
$ tree .git/refs/heads/
.git/refs/heads/
|-- dev
`-- master

# 查看分支指向的提交
$ cat .git/refs/heads/*
81b7158d55c34e495558198fcc3edd5f26e728e4
81b7158d55c34e495558198fcc3edd5f26e728e4

发现目前devmaster 指向同一个修改。验证HEAD 目前是指向master

Shell 复制代码
$ cat .git/HEAD
ref: refs/heads/master

综上,HEAD 指向当前分支,而master指向具体的提交

补充HEAD 不仅可以指向master分支,还可以指向其他分支 ,而HEAD所指向的分支就是当前工作的分支。




切换分支

那如何切换到dev分支下进行开发呢?使用git checkout命令即可完成切换

Shell 复制代码
# 切换到指定分支
git checkout dev

# 创建并切换到新分支(一步完成)
git checkout -b dev1

注意: git checkout devgit checkout -- file不同,后者用于撤销工作区修改


操作示例

Shell 复制代码
# 切换到dev分支
$ git checkout dev
Switched to branch 'dev'

# 切换分支后,HEAD指向改变
$ git branch
* dev
  master
  
$ cat .git/HEAD
ref: refs/heads/dev

接下来,在dev分支下修改ReadMe文件,新增一行内容,并进行一次提交操作

Shell 复制代码
$ vim ReadMe
$ cat ReadMe
test for new branch "dev"    # 新增内容

$ git add .
$ git commit -m "insert(+) 1 in ReadMe for dev branch"
[dev 9663d75] insert(+) 1 in ReadMe for dev branch
 1 file changed, 1 insertion(+)

现在,dev分支的工作完成,我们就可以切换回master分支:

Shell 复制代码
$ git checkout master
Switched to branch 'master'
$ cat ReadMe

发现ReadMe 文件中新增内容不见了!为什么会出现这种现象呢?我们来看看devmaster指向,发现两者指向的提交是不一样的

Shell 复制代码
$ cat .git/refs/heads/dev
9663d756fda23eb65c99fa002a87c575a9eceef1

$ cat .git/refs/heads/master
81b7158d55c34e495558198fcc3edd5f26e728e4

看到这里就能明白,因为我们是在dev分支上提交的,而master分支此刻的提交点并没有变,此时的状态如下所示:

当切换到master分支时,HEAD就指向了master,当然看不到提交了!




合并分支

git merge [目标分支]命令用于合并指定分支到当前分支。为了在master分支上看到dev分支提交的内容,就需要将dev分支合并到master分支。

Shell 复制代码
# 将dev分支合并到当前分支
git merge dev

合并时可能出现两种模式:

  1. Fast-forward(快进模式):直接移动指针,合并速度最快(默认模式)

  2. no-ff(非快进模式):创建新的合并提交,保留分支历史

补充 :Fast-forward就是直接把master 指向dev分支的当前提交,所以合并速度非常快。当然也不是每次合并都能Fast-foward


操作示例

Shell 复制代码
# 查看当前分支
$ git branch
* dev
  master

# 切换到master分支
$ git checkout master
Switched to branch 'master'

# 合并dev分支
$ git merge dev
Updating 81b7158..9663d75
Fast-forward
 ReadMe | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

# 查看合并后的文件
$ cat ReadMe
test for new branch "dev"    # 新增内容



删除分支

合并完成后,dev分支对我们来说就没用了,可以删除掉git branch -d [目标分支]

Shell 复制代码
$ git branch -d dev
Deleted branch dev (was 9663d75).

**注意:**不能删除当前所在的分支(master肯定也不能删啊,走火入魔了这是!?)

建议:因为创建、合并和删除分支非常快,所以Git鼓励使用分支完成某个任务,合并后再删除分支,这和直接在master分支上工作效果是一样的,但过程更安全。





分支合并策略

Fast-forward 快进模式(默认)

当目标分支是当前分支的直接上游时,Git会默认使用快进模式,直接将指针移动到目标分支的最新提交。

Shell 复制代码
# 快速合并示例
git merge dev
# 输出:Fast-forward

缺点:删除分支后无法从历史中看出合并信息。




no-ff 非快进模式(推荐)

使用--no-ff参数强制创建合并提交,保留完整分支历史。

Shell 复制代码
# 非快速合并示例
git merge --no-ff dev -m "merge dev with no-ff"
# 输出:

优点:分支历史清晰,能看出合并点


操作示例

Shell 复制代码
# 创建并切换到新分支
$ git checkout -b dev2
Switched to a new branch 'dev2'

# 修改文件并提交
$ vim ReadMe
$ cat ReadMe
test for new branch "dev2"    # dev2 新增内容

$ git add .
$ git commit -m "insert(+) 1 in ReadMe for dev2 branch"
[dev2 5724f11] insert(+) 1 in ReadMe for dev2 branch
 1 file changed, 2 insertions(+), 1 deletion(-)

# 切回master分支并使用no-ff模式合并
$ git checkout master
$ git merge --no-ff dev2 -m "merge dev2 with no-ff"
Merge made by the 'recursive' strategy.
 ReadMe | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

注意--no-ff参数,表示禁用Fast-forward模式。禁用Fast-forward模式后合并会创建一个新的commit,所以需要加上-m参数添加描述。


合并后,用git log --graph --pretty=oneline --abbrev-commit查看分支历史

Shell 复制代码
$ git log --graph --pretty=oneline --abbrev-commit
*   da1e876 merge dev2 with no-ff
|\  
| * 5724f11 insert(+) 1 in ReadMe for dev2 branch
|/  

可以看到,不使用Fast-forward模式,merge后就像这样

处理合并冲突

当不同分支对同一文件的同一部分进行了不同修改时,就会发生合并冲突。

冲突示例

Shell 复制代码
# 创建并切换到dev1分支
$ git checkout -b dev1
Switched to a new branch 'dev1'

$ git branch
* dev1
  master

dev1分支下修改ReadMe文件,并进行一次提交

Shell 复制代码
$ vim ReadMe
$ cat ReadMe  
test for new branch "dev1"    # dev1新增内容  

$ git add .
$ git commit -m "modify ReadMe for dev1"
[dev1 19895ee] modify ReadMe for dev1
 1 file changed, 1 insertions(+), 1 deletion(-)

切换回master分支,再对ReadMe文件进行修改

Shell 复制代码
$ git checkout master
Switched to branch 'master'

$ vim ReadMe
$ cat ReadMe
test for new branch "master"    # master新增内容

$ git add .
$ git commit -m "modify ReadMe for master"
[master df5d186] modify ReadMe for master
 1 file changed, 1 insertions(+), 1 deletion(-)

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

这种情况下,Git只能试图把各自的修改合并起来,但这种合并就可能会有冲突

Shell 复制代码
$ git merge dev1
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.



冲突标记

发现ReadMe文件有冲突后,可以直接查看文件内容。Git会用<<<<<<<=======>>>>>>>来标记出不同分支的冲突内容

Shell 复制代码
<<<<<< HEAD
当前分支的内容
=======
合并分支的内容
>>>>>>> dev1

操作示例

Shell 复制代码
$ cat ReadMe

<<<<<<< HEAD
test for new branch "master"    # master新增内容
=======
test for new branch "dev1"      # dev1新增内容  
>>>>>>> dev1



解决冲突

此时我们必须要手动调整冲突代码,并需要再次提交修正后的结果!!!(再次提交很重要,切勿忘记)

Shell 复制代码
# 1. 编辑文件解决冲突
vim ReadMe

# 2. 标记冲突已解决
git add .

# 3. 提交合并
git commit -m "解决合并冲突"

操作示例

Shell 复制代码
# 编辑文件解决冲突
$ vim ReadMe

# 查看解决后的内容
$ cat ReadMe
version3
test for new branch "dev"  
test for new branch "dev1"    # 保留下来的内容  

# 提交解决结果
$ git add .
$ git commit -m "merge ReadMe"
[master aa31f2e] merge ReadMe

到这里冲突就解决完成,此时的状态就变成了




查看合并历史

Shell 复制代码
$ git log --graph --abbrev-commit
*   commit aa31f2e
|\  Merge: df5d186 19895ee
| | Author: HY <1234567890@qq.com>
| | Date:   Sun Nov 30 19:24:50 2025 +0800
| | 
| |     merge ReadMe
| |   
| * commit 19895ee
| | Author: HY <1234567890@qq.com>
| | Date:   Sun Nov 30 19:07:47 2025 +0800
| | 
| |     modify ReadMe for dev1
| |   
* | commit df5d186
|/  Author: HY <1234567890@qq.com>
|   Date:   Sun Nov 30 19:16:48 2025 +0800
|   
|       modify ReadMe for master

最后不要忘记删除dev1分支

Shell 复制代码
$ git branch
  dev1
* master

$ git branch -d dev1
Deleted branch dev1 (was 19895ee).




分支管理策略

开发基本原则

1、master分支(主分支)

  • 仅用于发布稳定版本,保持代码库稳定

  • 禁止直接在此分支上进行开发工作



2、dev分支(开发分支)

  • 作为集成开发环境,所有功能在此合并

  • 团队成员在此协作,进行功能集成测试



3、功能分支(Feature分支)

  • 每个新功能的开发,都要在dev分支的基础上,创建独立分支

  • 命名规范:feature/功能名称(如feature/user-login



4、修复分支(Hotfix分支)

  • 用于紧急bug修复的临时分支

  • 命名规范:hotfix/问题描述(如hotfix/login-bug




团队协作模型





实用分支技巧

存储工作现场

当需要切换分支,但由于当前工作未完成无法提交时,可以用git stash命令存储更改

Shell 复制代码
# 1、暂存当前工作(包括未提交的修改)
git stash

# 2、查看所有暂存记录
git stash list
# 输出示例:stash@{0}: On dev2: 正在进行的功能开发

# 3、恢复最近一次暂存(并删除暂存记录)
git stash pop

# 4、恢复指定暂存(不删除记录)
git stash apply stash@{0}

# 5、删除指定暂存记录
git stash drop stash@{0}

# 6、清空所有暂存记录
git stash clear
操作示例
Shell 复制代码
# 1、当前在dev2分支开发中,突然发现master有bug
$ git status
# On branch dev2
# Changes not staged for commit:
#   modified:   ReadMe

# 2、暂存当前工作
$ git stash
Saved working directory and index state WIP on dev2: 5724f11 insert(+) 1 in ReadMe

# 3、工作区已干净,可切换分支
$ git status
# On branch dev2
nothing to commit, working directory clean

# 4、创建并切换到修复分支
$ git checkout master
$ git checkout -b fix_bug
Switched to a new branch 'fix_bug'

$ vim ReadMe
$ cat ReadMe
This is a bug

# 5、修复bug并提交
$ vim ReadMe
$ cat ReadMe
Having fixed the bug

$ git add ReadMe
$ git commit -m "fix a bug"
[fix_bug f85271f] fix a bug
 1 file changed, 2 insertions(+), 1 deletion(-)

# 6、合并修复到master分支,并删除修复分支
$ git checkout master
Switched to branch 'master'

$ git merge fix_bug --no-ff -m "merge fix_bug branch"
Merge made by the 'recursive' strategy.
 ReadMe | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
 
$ git branch -d fix_bug
Deleted branch fix_bug (was f85271f).

# 回到dev2分支恢复工作
$ git checkout dev2
Switched to branch 'dev2'

$ git stash pop
# On branch dev2
# Changes not staged for commit:
#	modified:   ReadMe
Dropped refs/stash@{0} (b12a006d2e3b2d4966fc70b43cfe00207ded9d8a)


分支合并技巧

为避免在master分支上直接解决冲突,推荐以下操作流程

Shell 复制代码
# 1、在功能分支上更新主分支最新代码
git merge master

# 2、解决冲突并提交
vim ReadMe
git add .
git commit -m "合并master并解决冲突"

# 3、切换回master,合并功能分支
git checkout master
git merge feature-branch

# 4、删除已完成的功能分支
git branch -d feature-branch



操作示例
Shell 复制代码
# 在dev2分支开发功能
$ git checkout dev2
Switched to branch 'dev2'

# 合并master最新代码到dev2,发生冲突
$ git merge master --no-ff -m "合并master到dev2"
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.

# 查看冲突文件
$ cat ReadMe
<<<<<<< HEAD
I have coded ...              # dev2的代码
=======
Having fixed the bug          # master的修复
>>>>>>> master

# 手动解决冲突
$ vim ReadMe
I have coded ......              
Having fixed the bug

# 提交解决结果
$ git add .
$ git commit -m "merge master"
[dev2 9e3bf59] merge master
[HY@VM-24-13-centos gitcode]$ git status
# On branch dev2
nothing to commit, working directory clean

# 切换回master合并(此时应该无冲突)
$ git checkout master
Switched to branch 'master'

$ git merge dev2 --no-ff -m "merge dev2"
Merge made by the 'recursive' strategy.
 ReadMe | 1 +
 1 file changed, 1 insertion(+)

# 删除已合并的分支
$ git branch -d dev2
Deleted branch dev2 (was 9e3bf59).




强制删除分支

在开发新功能时,通常会在feature分支上进行。但如果功能开发中途被取消,该分支未合并就需要删除。此时使用git branch -d会失败,因为分支未合并。

操作示例

直接使用传统删除分支的方法不行,可以使用-D参数进行强制删除:

Shell 复制代码
# 常规删除失败(分支未合并)
git branch -d dev3
error: The branch 'dev3' is not fully merged.

# 强制删除成功
$ git branch -D dev3
Deleted branch dev3 (was 70248ce).
$ git branch
* master




小结

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,二年你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作

并且Git无论创建、切换和删除分支,Git在1秒之内就能完成!无论你的版本库是一个文件还是1万个文件

相关推荐
NEXT062 小时前
从Git三连到时光机大师:我的代码终于有了后悔药
git
stars-he2 小时前
FPGA学习笔记(8)以太网UDP数据报文发送电路设计(二)
网络·笔记·学习·fpga开发
彬匠科技BinJiang_tech2 小时前
对账太耗时?跨境ERP实现物流商/供应商自动化对账
大数据·运维·自动化
weilaikeqi11112 小时前
宠物护理技术革命:“微米银”正在改写传统抗菌方式?
大数据·人工智能·宠物
卡布叻_星星2 小时前
部署笔记之部署不同Java版本项目以及多项目内存崩溃问题
笔记
喂完待续2 小时前
【Big Data】2025年大数据技术演进与产业变革
大数据·ai·数据安全·big data·年度总结·微博之星
liangshanbo12152 小时前
从“造智能体”到“赋能技能”:大模型应用范式的战略大转向
大数据·人工智能
麻雀无能为力2 小时前
Diffusion Model(DDPM)学习笔记
笔记·学习
Chloeis Syntax2 小时前
MySQL初阶学习日记(7)--- 事务
java·数据库·笔记·学习·mysql