【Git版本控制 02】分支管理

目录

一、创建分支

二、切换分支

三、合并分支

四、删除分支

五、合并冲突

六、分支策略

七、bug分支


一、创建分支

bash 复制代码
# 当前仓库只有 master 一个主分支
# 可通过 git branch 是进行分支管理的命令,可通过不同参数对分支进行查看、创建、删除

(base) [root@localhost gitcode]# cat .git/HEAD
ref: refs/heads/master
(base) [root@localhost gitcode]# cat .git/refs/heads/master
84b615bfb313b40010c263cbadc67f24ce1ed1d3
(base) [root@localhost gitcode]# git branch
* master
(base) [root@localhost gitcode]# git branch dev
(base) [root@localhost gitcode]# git branch
  dev
* master
(base) [root@localhost gitcode]# ls .git/refs/heads/
dev  master
(base) [root@localhost gitcode]# cat .git/refs/heads/*
84b615bfb313b40010c263cbadc67f24ce1ed1d3
84b615bfb313b40010c263cbadc67f24ce1ed1d3
(base) [root@localhost gitcode]# 

# * 表示当前 HEAD 指向的分支是 master 分支
# git branch 只能查看本地分支,git branch -r 可查看远程分支

二、切换分支

bash 复制代码
(base) [root@localhost gitcode]# git checkout dev
切换到分支 'dev'
(base) [root@localhost gitcode]# cat .git/HEAD
ref: refs/heads/dev
(base) [root@localhost gitcode]# git branch
* dev
  master
(base) [root@localhost gitcode]# 
bash 复制代码
# 在新分支上修改文件内容

(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: dev
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for dev"
[dev 088ce6d] modify file1 for dev
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
(base) [root@localhost gitcode]# 


# 为什么 dev分支 和 master分支 上同一个文件的内容不一样呢?
# 我们可以看到 dev分支和 master分支 上两者指向的提交是不一样的

(base) [root@localhost gitcode]# cat .git/refs/heads/dev
088ce6d478daaadbd94870ceebd47bd05bf1b4e1
(base) [root@localhost gitcode]# cat .git/refs/heads/master
84b615bfb313b40010c263cbadc67f24ce1ed1d3
(base) [root@localhost gitcode]# 

三、合并分支

bash 复制代码
# 先切回到 master分支,再通过 git merge 合并 dev分支

(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
(base) [root@localhost gitcode]# git merge dev
更新 84b615b..088ce6d
Fast-forward
 file1 | 1 +
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: dev
(base) [root@localhost gitcode]# 

Fast-forward代表"快进模式",也就是直接把master指向dev的当前提交,所以合并速度非常快。

四、删除分支

合并完成后, dev分⽀ 对于我们来说就没⽤了,那么 dev分⽀ 就可以被删除掉,注意如果当前正处于某分⽀下,就不能删除当前分⽀。

bash 复制代码
(base) [root@localhost gitcode]# git branch
* dev
  master
(base) [root@localhost gitcode]# git branch -d dev
error: 无法删除您当前所在的分支 'dev'。
(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# git branch -d dev
已删除分支 dev(曾为 088ce6d)。
(base) [root@localhost gitcode]# git branch
* master
(base) [root@localhost gitcode]# 

因为创建、合并和删除分⽀⾮常快,所以Git⿎励你使⽤分⽀完成某个任务,合并后再删掉分⽀,这和直接在master分⽀上⼯作效果是⼀样的,但过程更安全。

五、合并冲突

在实际分⽀合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。

bash 复制代码
# git checkout -b 可以创建并跳转到新分支
# 分别在 dev1分支 和 master分支上对file1文件修改并提交

(base) [root@localhost gitcode]# git checkout -b dev1
切换到一个新分支 'dev1'
(base) [root@localhost gitcode]# git branch
* dev1
  master
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: dev1
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for dev1"
[dev1 77f1455] modify file1 for dev1
 1 file changed, 1 insertion(+), 1 deletion(-)
(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: dev
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for master"
[master b7534ec] modify file1 for master
 1 file changed, 1 insertion(+), 1 deletion(-)
(base) [root@localhost gitcode]# 

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

bash 复制代码
(base) [root@localhost gitcode]# git branch
  dev1
* master
(base) [root@localhost gitcode]# git merge dev1
自动合并 file1
冲突(内容):合并冲突于 file1
自动合并失败,修正冲突然后提交修正的结果。
(base) [root@localhost gitcode]# git status
# 位于分支 master
# 您有尚未合并的路径。
#   (解决冲突并运行 "git commit")
#
# 未合并的路径:
#   (使用 "git add <file>..." 标记解决方案)
#
#       双方修改:     file1
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
<<<<<<< HEAD
write sth. for new branch: master
=======
write sth. for new branch: dev1
>>>>>>> dev1
(base) [root@localhost gitcode]# 

Git会⽤ <<<<<<<,=======,>>>>>>> 来标记出不同分⽀的冲突内容,此时我们必须要⼿动调整冲突代码,并需要再次提交修正后的结果!!

bash 复制代码
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for master and dev1"
[master 0dc19d0] modify file1 for master and dev1
(base) [root@localhost gitcode]# git status
# 位于分支 master
无文件要提交,干净的工作区
(base) [root@localhost gitcode]# 
bash 复制代码
# 用带参数的 git log 也可以看到分支合并情况

(base) [root@localhost gitcode]# git log --graph --pretty=oneline --abbrev-commit
*   0dc19d0 modify file1 for master and dev1
|\  
| * 77f1455 modify file1 for dev1
* | b7534ec modify file1 for master
|/  
* 088ce6d modify file1 for dev
* 84b615b delete file3
* 0f28717 delete file4
* c31b56a modigy: add vertion2
* 167def0 modify: add vertion1
* 7df1e32 modify: file1
* f2e9210 Add three files
* fc3a350 Add first file
(base) [root@localhost gitcode]# 
bash 复制代码
# 分支使用完最好删除掉

(base) [root@localhost gitcode]# git branch -d dev1
已删除分支 dev1(曾为 77f1455)。
(base) [root@localhost gitcode]# git branch
* master
(base) [root@localhost gitcode]# 

六、分支策略

通常合并分⽀时,如果可能,Git会采⽤ Fast forward 模式。

在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是 merge 进来的还是正常提交的。

但在合并冲突部分,我们也看到通过解决冲突问题,会再进⾏⼀次新的提交。

那么这就不是 Fast forward 模式了,这样的好处是,从分⽀历史上就可以看出分⽀信息。

Git ⽀持我们强制禁⽤ Fast forward 模式,那么就会在 merge 时⽣成⼀个新的 commit ,这样,从分⽀历史上就可以看出分⽀信息。

bash 复制代码
# 新建 dev2分支 并在新分支上修改 file1

(base) [root@localhost gitcode]# git checkout -b dev2
切换到一个新分支 'dev2'
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for dev2"
[dev2 13c3c71] modify file1 for dev2
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]#
bash 复制代码
# 使用 git -merge --no-ff 合并分支会提交一个新的 commit

(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
(base) [root@localhost gitcode]# git merge --no-ff -m "merge with no-ff: dev2" dev2
Merge made by the 'recursive' strategy.
 file1 | 1 +
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
(base) [root@localhost gitcode]# git log --graph --pretty=oneline --abbrev-commit
*   cb70524 merge with no-ff: dev2
|\  
| * 13c3c71 modify file1 for dev2
|/  
*   0dc19d0 modify file1 for master and dev1
|\  
| * 77f1455 modify file1 for dev1
* | b7534ec modify file1 for master
|/  
* 088ce6d modify file1 for dev
* 84b615b delete file3
* 0f28717 delete file4
* c31b56a modigy: add vertion2
* 167def0 modify: add vertion1
* 7df1e32 modify: file1
* f2e9210 Add three files
* fc3a350 Add first file
(base) [root@localhost gitcode]# 

可以看出,在 --no-ff 模式下,merge后的分支图为:

所以在合并分⽀时,加上 --no-ff 参数就可以⽤普通模式合并,合并后的历史有分⽀,能看出来曾经做过合并,⽽ fast forward 合并就看不出来曾经做过合并。

分支管理原则

  1. master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活;
  2. ⼲活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布时,再把dev分⽀合并到master上,在master分⽀发布1.0版本;

七、bug分支

假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有bug,需要解决。在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。

可现在 dev2 的代码在⼯作区中开发了⼀半,还⽆法提交,怎么办?

bash 复制代码
(base) [root@localhost gitcode]# git checkout dev2
切换到分支 'dev2'
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
this is a bug ...
(base) [root@localhost gitcode]# git status
# 位于分支 dev2
# 尚未暂存以备提交的变更:
#   (使用 "git add <file>..." 更新要提交的内容)
#   (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
#       修改:      file1
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
(base) [root@localhost gitcode]# 
bash 复制代码
# Git提供了 git stash 命令可以将当前工作区信息进行储藏
# 被储藏的内容可以在将来的某个时间恢复出来

(base) [root@localhost gitcode]# git stash
Saved working directory and index state WIP on dev2: 13c3c71 modify file1 for dev2
HEAD 现在位于 13c3c71 modify file1 for dev2
(base) [root@localhost gitcode]# git status
# 位于分支 dev2
无文件要提交,干净的工作区
(base) [root@localhost gitcode]# 
bash 复制代码
# 储藏 dev2 ⼯作区之后,由于我们要基于master分⽀修复bug,
# 所以需要切回 master 分⽀,再新建临时分⽀来修复bug

(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# git checkout -b fix_bug
切换到一个新分支 'fix_bug'
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
fix a bug here!
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "fix a bug"
[fix_bug 1ec9fbd] fix a bug
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]#  
bash 复制代码
# 修复完成后,切换到 master 分⽀,并完成合并,最后删除 fix_bug 分⽀

(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# git merge --no-ff -m "merge fix_bug branch" fix_bug
Merge made by the 'recursive' strategy.
 file1 | 1 +
 1 file changed, 1 insertion(+)
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
fix a bug here!
(base) [root@localhost gitcode]# git branch -d fix_bug
已删除分支 fix_bug(曾为 1ec9fbd)。
(base) [root@localhost gitcode]#
bash 复制代码
# bug的修复⼯作已经做完了,我们还要继续回到 dev2 分⽀进⾏开发。
# ⼯作区是⼲净的,需要恢复现场
# git stash list 查看工作现场列表
# git stash pop  恢复工作现场

(base) [root@localhost gitcode]# git checkout dev2
切换到分支 'dev2'
(base) [root@localhost gitcode]# git status
# 位于分支 dev2
无文件要提交,干净的工作区
(base) [root@localhost gitcode]# git stash list
stash@{0}: WIP on dev2: 13c3c71 modify file1 for dev2
(base) [root@localhost gitcode]# git stash pop
# 位于分支 dev2
# 尚未暂存以备提交的变更:
#   (使用 "git add <file>..." 更新要提交的内容)
#   (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
#       修改:      file1
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
丢弃了 refs/stash@{0} (f9841933f9d2d3112f4262fc0e5c9f882fea7fd7)
(base) [root@localhost gitcode]# git stash list
(base) [root@localhost gitcode]#
bash 复制代码
# 恢复完代码之后我们便可以继续完成开发,开发完成后便可以进⾏提交
# 但是修复bug的内容并没有在dev2中显示

(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
this is a bug ...
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "modify file1 for dev2"
[dev2 030cb5d] modify file1 for dev2
 1 file changed, 1 insertion(+), 1 deletion(-)
(base) [root@localhost gitcode]# 

Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们

在 dev2 中当然看不⻅修复bug的相关代码。

我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合

并即可,但这样其实是有⼀定⻛险的。

因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到master 上。

解决这个问题的⼀个好的建议就是:最好在⾃⼰的分⽀上合并下 master ,再让 master 去合并

dev ,这样做的⽬的是有冲突可以在本地分⽀解决并进⾏测试,⽽不影响 master 。

bash 复制代码
# dev2 合并 master

(base) [root@localhost gitcode]# git branch
* dev2
  master
(base) [root@localhost gitcode]# git merge master
自动合并 file1
冲突(内容):合并冲突于 file1
自动合并失败,修正冲突然后提交修正的结果。
(base) [root@localhost gitcode]# 
bash 复制代码
# 发生冲突,将冲突解决并重新提交

(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
<<<<<<< HEAD
this is a bug ...
=======
fix a bug here!
>>>>>>> master
(base) [root@localhost gitcode]# vim file1
(base) [root@localhost gitcode]# cat file1
hello git
hello world
add vertion1
add vertion2
write sth. for new branch: master
write sth. for new branch: dev1
write sth. for new branch: dev2
i am coding ... done!
(base) [root@localhost gitcode]# git add .
(base) [root@localhost gitcode]# git commit -m "merge master"
[dev2 9604340] merge master
(base) [root@localhost gitcode]# git status
# 位于分支 dev2
无文件要提交,干净的工作区
(base) [root@localhost gitcode]# 
bash 复制代码
# 切回master,合并dev2

(base) [root@localhost gitcode]# git checkout master
切换到分支 'master'
(base) [root@localhost gitcode]# git merge dev2
更新 1bcd87b..9604340
Fast-forward
 file1 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
(base) [root@localhost gitcode]# git status
# 位于分支 master
无文件要提交,干净的工作区
(base) [root@localhost gitcode]# git branch -d dev2
已删除分支 dev2(曾为 9604340)。
(base) [root@localhost gitcode]# 
相关推荐
_君莫笑17 小时前
大厂Git使用规范
git
无心水1 天前
【Hermes:安全、权限与生产环境】39、智能体也会犯错?Hermes 纠错、回滚与遗忘机制全指南 —— 让 AI 的错误像 Git 一样可逆可控
人工智能·git·安全·mcp协议·openclaw·hermes·honcho
南境十里·墨染春水1 天前
linux学习进展 git详解
linux·git·学习
zhangfeng11331 天前
CodeBuddy ai对话框上面的git docs terminal Rulds 干嘛用的,以thinkphp fastadmin 为例,插件市场
人工智能·git·编程
OYangxf1 天前
Git Conflict Resolution
大数据·git·elasticsearch
高斯林.神犇1 天前
Git全套流程
git
次元工程师!1 天前
LangFlow开发(一)—安装和部署
git·python·大模型·langflow
怣疯knight1 天前
【无标题】
git
Jim-zf1 天前
git 锁文件
git
lcx_defender1 天前
Git常见操作与指令
git