Git 分支管理指南:从基础概念到团队协作规范
背景
在多人协作开发中,缺乏清晰的 Git 分支管理规范常导致代码覆盖、版本回滚困难及冲突堆积等问题。Git 的分支能力本是版本控制的利器,但如果使用无章,就会变成团队协作的绊脚石。掌握科学的分支管理策略,是提升开发效率、降低线上风险的关键。
本文将从为什么要做分支管理出发,层层拆解核心概念、主流策略、实操命令和避坑指南,既兼顾新手的入门理解,也满足团队协作的实战需求。
一、为什么要分支?——分支的意义
Git 分支是版本控制的核心能力,它能解决三大核心问题:
- 并行开发:多人协作不冲突(比如 A 开发支付功能,B 修复登录 bug)
- 风险隔离:新功能开发不影响线上稳定版本
- 版本回溯:出现问题可快速回滚到历史稳定版本
分支就像是平行宇宙,当你正在一个分支学习时,另一个分支可以独立运行。如果两个分支互不干扰,对当前工作没影响。在某个时间点,两个分支合并了,结果整合了双方的成果。
二、Git 分支基础:核心概念与常用命令
2.1 分支与 HEAD 指针解析
- 分支:Git 分支并非复制完整代码目录,而是一个'指向提交记录的指针'(占极少存储空间)。例如
master分支指向最新的稳定提交,feature/login分支指向登录功能的最新提交。 - HEAD 指针:Git 用
HEAD指针标记'当前所在的分支',执行git branch命令时,带*的分支即为 HEAD 指向的当前分支。
HEAD 严格来说不是指向提交,而是指向当前分支,当前分支才是指向提交的。所以,HEAD 指向的就是当前分支。
每次提交,master 分支都会向前移动一步,随着不断提交,master 分支的线也越来越长,而 HEAD 只要一直指向 master 分支即可指向当前分支。
查看我们当前的版本库:
user@host:~/project$ cat .git/HEAD
ref: refs/heads/master
user@host:~/project$ cat .git/refs/heads/master
ebc48f707e2908206260e9279a8932f66a71c4c7
master 指向的是最近一次提交的 commit id,我们可以使用 git log 来查看。
2.2 基础指令:查看、创建、切换分支
<1> 查看分支(git branch)
查看本地所有分支(* 表示当前分支):
user@host:~/project$ git branch
* master
<2> 创建分支(git branch <分支名>)
Git 支持我们查看或创建其它分支,创建分支时,Git 会基于'当前分支的最新提交'创建新指针,不会复制代码文件。在这里我们来创建第一个自己的分支 dev,对应的命令为:
user@host:~/project$ git branch dev
user@host:~/project$ git branch
* master
dev
我们发现 heads 多了一个刚刚创建的 dev 分支。
<3> 切换分支(git checkout)
此时 dev 分支指向的也是最近一次的提交,但是,进行修改等操作还是只能在 master 分支进行操作。此时如果想要切换到 dev 分支下进行操作该怎么办呢?
user@host:~/project$ git checkout dev
Switched to branch 'dev'
user@host:~/project$ git branch
* dev
master
user@host:~/project$ cat .git/HEAD
ref: refs/heads/dev
接下来,我们在 dev 分支下对 ReadMe 文件新增一行代码:
user@host:~/project$ ls file1 ReadMe
user@host:~/project$ vim ReadMe
user@host:~/project$ git add ReadMe
user@host:~/project$ git commit -m "md ReadMe"
[dev a2c0656] md ReadMe
1 file changed, 1 insertion(+)
user@host:~/project$ git status
On branch dev
nothing to commit, working tree clean
user@host:~/project$ cat ReadMe
Hello git
Hello Git
aaa on dev branch
我们在 dev 分支下对 ReadMe 文件修改,现在切换回 master 分支,看一下 ReadMe 文件:
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git branch
* master
dev
user@host:~/project$ ls file1 ReadMe
user@host:~/project$ cat ReadMe
Hello git
Hello Git
我们发现,在 master 分支下,ReadMe 文件并没有变化,我们新增的那一行代码并没有显示出来。我们再切回 dev 分支:
user@host:~/project$ git checkout dev
Switched to branch 'dev'
user@host:~/project$ git branch
* dev
master
user@host:~/project$ ls file1 ReadMe
user@host:~/project$ cat ReadMe
Hello git
Hello Git
aaa on dev branch
在 dev 分支上,内容还在。为什么会出现这个现象呢?我们来看看 dev 分支和 master 分支的指向,会发现两者的指向是不同的:
user@host:~/project$ cat .git/refs/heads/dev
a2c0656bbc3c1a570d863680882d389684230991
user@host:~/project$ cat .git/refs/heads/master
ebc48f707e2908206260e9279a8932f66a71c4c7
因为我们是在 dev 分支上提交的,而 master 分支此刻的提交点并没有变。
三、Git 分支进阶:合并、删除和冲突
分支开发完成后,需要将代码合并到目标分支;若合并时出现代码冲突,需手动解决;当然,删除分支也是必不可少的操作。
3.1 合并分支(git merge 分支名)
为了在 master 主分支上能看到新的提交,就需要将 dev 分支合并到 master 分支。合并分支的核心逻辑是'将源分支的提交记录合并到目标分支',需先切换到目标分支,再执行合并命令。
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git merge dev
Updating ebc48f7..a2c0656 Fast-forward
ReadMe | 1 +
1 file changed, 1 insertion(+)
user@host:~/project$ cat ReadMe
Hello git
Hello Git
aaa on dev branch
git merge 分支名命令用于合并指定分支到当前分支。合并后,master 就能看到 dev 分支提交的内容。
我们会看到上面合并之后,会出现 Fast-forward 代表'快进模式',也就是直接把 master 指向 dev 的当前提交,所以合并速度非常快。当然,也不是每次合并都能 Fast-forward。
3.2 删除分支(git branch -d 分支名)
合并完成后,dev 分支对于我们来说就没用了,那么 dev 分支就可以删除掉。注意如果当前正处于某个分支下,就不能删除当前分支。
user@host:~/project$ git checkout dev
Switched to branch 'dev'
user@host:~/project$ git branch -d dev
error: Cannot delete branch 'dev' checked out at '/home/user/project'
而可以在其它分支下删除当前分支:
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git branch -d dev
Deleted branch dev (was a2c0656).
user@host:~/project$ git branch
* master
因为创建、合并、删除分支非常快,所以 Git 鼓励你使用分支完成某个任务,合并后再删除分支,这和直接在 master 分支上工作效果是一样的,但过程更安全。
3.3 解决合并冲突
若合并的两个分支修改了'同一文件的同一部分'(如 master 分支和 dev1 都修改了 ReadMe 文件),Git 无法自动判断保留哪部分代码,会触发'合并冲突',此时需手动解决。
创建一个新的分支 dev1,并切换至目标分支,我们可以使用 git checkout -b dev1 一步完成创建并切换的动作。
user@host:~/project$ git checkout -b dev1
Switched to a new branch 'dev1'
user@host:~/project$ git branch
* dev1
master
在 dev 分支下修改 ReadMe 文件,更改文件内容,并进行一次提交。
user@host:~/project$ vim ReadMe
user@host:~/project$ git add .
user@host:~/project$ git status
On branch dev1
Changes to be committed:
modified: ReadMe
user@host:~/project$ git commit -m "md ReadMe:bbb"
[dev1 74cd7a0] md ReadMe:bbb
1 file changed, 1 insertion(+), 1 deletion(-)
切换至 master 分支,观察 ReadMe 文件内容。我们切换回来会发现文件内容还没变,这个是因为还没提交。那么我们此时如果在 ReadMe 文件再进行一次修改,并进行提交:
user@host:~/project$ git checkout master
M ReadMe Already on 'master'
user@host:~/project$ vim ReadMe
user@host:~/project$ git add .
user@host:~/project$ git commit -m "md ReadMe:ccc"
[master 0b2410c] md ReadMe:ccc
1 file changed, 1 insertion(+), 1 deletion(-)
现在,master 分支和 dev1 分支都分别有了新的提交。这种情况下,Git 只能试图把各自的修改合并起来,但这种合并就可能会有冲突。
user@host:~/project$ git branch dev1
* master
user@host:~/project$ git merge dev1
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.
我们发现 ReadMe 文件有冲突后,可以直接查看文件内容。Git 会用 <<<<<<<, =======, >>>>>>> 来标记出不同分支的冲突内容。此时我们需要手动调整冲突代码,并需要再次提交修正后的结果(再次提交很重要,不要忘记)。
我们将 dev1 下的 ReadMe 文件修改为 bbb on dev branch,再次提交:
user@host:~/project$ vim ReadMe
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
user@host:~/project$ 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:
both modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
user@host:~/project$ git add .
user@host:~/project$ git commit -m "merge dev1"
[master de63d7e] merge dev1
user@host:~/project$ git status
On branch master
nothing to commit, working tree clean
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
到这里冲突就解决完成。我们可以使用 git log 打印一下日志:
user@host:~/project$ git log --graph --pretty=oneline --abbrev-commit
* de63d7e (HEAD -> master) merge dev1
| |
| * 74cd7a0 (dev1) md ReadMe:bbb
| * | 0b2410c md ReadMe:ccc
|/
* a2c0656 md ReadMe
* ebc48f7 delete file2
... (省略后续日志)
最后,不要忘记 dev1 分支使用完毕后就可以删除了。
四、分支管理规范
4.1 禁用 Fast forward 模式
通常合并分支时,如果可能,Git 会采用 Fast forward 模式。在这种模式下,删除分支后,查看分支历史时,会丢掉分支信息,看不出来最新提交到底是 merge 进来的还是正常提交的,在公司里,如果产品出现错误,不能追究到个人。
但在合并冲突部分,通过解决冲突问题,会再进行下一次提交,得到的最终状态就不是 Fast forward 模式了。这样的好处是,从历史分支上就可以看出分支信息。例如我们现在已经删除了在合并冲突部分创建的 dev2 分支,但依旧能看到 master 其实是由其它分支合并得到。
我们在以后分支修改与提交过程可以采用这种模式,可以观察到历史信息与提交记录。
no Fast forward 命令: git merge --no-ff -m "merge dev2" dev2
我们来实战一下:
切换回 dev2 分支,并修改 ReadMe 文件:
user@host:~/project$ git checkout -b dev2
Switched to a new branch 'dev2'
user@host:~/project$ vim ReadMe
提交一下:
user@host:~/project$ git add .
user@host:~/project$ git commit -m "md ReadMe"
[dev2 2b90647] md ReadMe
1 file changed, 1 insertion(+)
切回 master 分支,开始 merge 合并:
--no-ff参数,表示禁用Fast forward模式。禁用Fast forward模式后合并会创建一个新的commit,所以加上-m参数,把描述写进去。
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git merge --no-ff -m "merge dev2" dev2
Merge made by the 'ort' strategy.
ReadMe | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
abcde
合并后,查看分支历史:
user@host:~/project$ git log --graph --abbrev-commit
* commit 8b22d5b (HEAD -> master) |
| Merge: 2b90647 ba59442
| |
| Author: user <[email protected]>
| Date: Fri Dec 12 08:28:26 2025 +0800
| |
| merge dev2
| |
| * commit ba59442 (dev2)
|/ Author: user <[email protected]>
| Date: Fri Dec 12 08:27:01 2025 +0800
| |
| md ReadMe
所以在合并分支时,加上 --no-ff 参数就可以普通合并模式,合并后的历史有分支,能看出曾经做过合并,而 Fast forward 合并后就看不出来曾经做过合并。
4.2 分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理: 首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; 那在哪里干活呢?干活都在 dev 分支上,也就是说,dev 分支是不稳定的,到某个时候,比如 1.0 版本发布时,再把 dev 分支合并到 master 上,在 master 分支上发布 1.0 版本; 你和你的小伙伴们每个人都在 dev 分支上干活,每个人都有自己的分支,时不时地往 dev 分支上合并就可以了。
4.3 修改 bug 创建新分支
假如我们现在正在 dev2 分支上进行开发,开发到一半,突然发现 master 分支上面有 bug,需要解决。在 Git 中,每个 bug 都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
但是我们还不想提交 dev2,那我们应该怎么办?
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
abcde
i am coding...
user@host:~/project$ git status
On branch master
Changes not staged for commit:
modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
Git 提供了 git stash 命令,可以将当前工作区信息进行储藏,被储存的内容可以在将来某个时间恢复出来。
user@host:~/project$ git checkout dev2
M ReadMe
Switched to branch 'dev2'
user@host:~/project$ git stash
Saved working directory and index state
WIP on dev2: ba59442 md ReadMe
再查看工作区,因此可以放心的创建分支来修复 bug。储藏 dev2 工作区后,由于我们要基于 master 分支修复 bug,所以需要切回 master 分支,再新建临时分支来修复 bug。
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git checkout -b fix_bug
Switched to a new branch 'fix_bug'
user@host:~/project$ vim ReadMe
user@host:~/project$ git add .
user@host:~/project$ git commit -m "fix bug:f"
[fix_bug e035682] fix bug:f
1 file changed, 1 insertion(+), 1 deletion(-)
修复完成后,切换到 master 分支,并完成合并:
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git merge --no-ff -m "merge fix_bug" fix_bug
Merge made by the 'ort' strategy.
ReadMe | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
user@host:~/project$ git status
On branch master
nothing to commit, working tree clean
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
abcdef
bug 的修复工作已经做完了,我们还要继续回到 dev2 分支进行开发,切换回 dev2 分支,工作区是干净的,刚才的工作存到哪里去了?用 git stash list 命令看看:
user@host:~/project$ git stash list
stash@{0}: WIP on dev2: ba59442 md ReadMe
工作现场还在,Git 把 stash 内容存在某个地方了,但是需要恢复一下。如果恢复现场呢?我们可以使用 git stash pop 命令,恢复的同时会把 stash 也删了。
user@host:~/project$ git stash pop
On branch dev2
Changes not staged for commit:
modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (c3c2100ccd5938ee9b7456ee29bf7cfb5e00)
恢复完代码之后我们还可以继续完成开发,开发完后就可以提交了。
但是我们注意到了,修复 bug 的内容,并没有在 dev2 上显示。Master 分支目前最新的提交,是要领先于新建 dev2 时基于的 master 分支的提交的,所以我们在 dev2 中当然看不见修复 bug 的相关代码。
我们的最终目的是要让 master 合并 dev2 分支的,那么正常情况下我们切回 master 分支直接合并即可,但这样其实是有一定风险的。是因为在合并分支时可能会有冲突,而代码冲突需要我们手动解决(在 master 上解决)。我们无法保证对于冲突问题可以正确地一次性解决掉,因为在实际的项目中,代码冲突不只一两行那么简单,有可能几十上百行,甚至更多,解决的过程中难免手误出错,导致错误的代码被合并到 master 上。
解决这个问题的一个好的建议就是:最好在自己的分支上合并下 master,再让 master 去合并 dev,这样做的目的是又冲突可以在本地解决并进行测试,而不影响 master。
最后 merge 合并 dev2 分支:
user@host:~/project$ git branch
* dev2
fix_bug
master
# dev2 分支合并 master
user@host:~/project$ git merge --no-ff -m "merge master" master
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.
# 在 dev2 分支上修改
user@host:~/project$ vim ReadMe
user@host:~/project$ git add .
user@host:~/project$ git commit -m "merge master fix"
[dev2 996e6ee] merge master fix
# 切换回 master 分支
user@host:~/project$ git checkout master
Switched to branch 'master'
# 合并 dev2 分支
user@host:~/project$ git merge --no-ff -m "merge dev2" dev2
Merge made by the 'ort' strategy.
ReadMe | 1 +
1 file changed, 1 insertion(+)
user@host:~/project$ cat ReadMe
Hello git
Hello Git
bbb on dev branch
abcdef
i am coding...
Done!
user@host:~/project$ git branch
* master
dev2
fix_bug
# 删除 fix_bug 分支
user@host:~/project$ git branch -d fix_bug
Deleted branch fix_bug (was e035682).
# 删除 dev2 分支
user@host:~/project$ git branch -d dev2
Deleted branch dev2 (was 996e6ee).
4.4 删除临时分支
软件开发中,总有无穷无尽的新的功能要不断添加进来。添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个分支,我们可以将其称之为 feature 分支,在上面开发,完成后,合并,最后,删除该 feature 分支。
可是,如果我们今天正在某个 feature 分支上开发了一半,被产品经理突然叫停,说是要停止新功能的开发。虽然白干了,但是这个 feature 分支还是必须就地销毁,留着无用了。这时使用传统的 git branch -d 命令删除分支的方法是不行的。
user@host:~/project$ git checkout -b dev3
Switched to a new branch 'dev3'
user@host:~/project$ vim ReadMe
user@host:~/project$ git add .
user@host:~/project$ git commit -m "md ReadMe"
[dev3 63bfcad] md ReadMe
1 file changed, 1 insertion(+)
user@host:~/project$ git checkout master
Switched to branch 'master'
user@host:~/project$ git branch -d dev3 # 删除失败
error: The branch 'dev3' is not fully merged. If you are sure you want to delete it, run 'git branch -D dev3'.
直接使用传统的删除分支方式不行,按照提示,我们使用如下方式:
user@host:~/project$ git branch -D dev3
Deleted branch dev3 (was 63bfcad).
user@host:~/project$ git branch
* master
小结:分支管理的落地,更需要团队全员的共识与执行:从禁止直接提交主分支,到认真处理每一次代码冲突,再到定期清理冗余分支,每一个细节都在影响协作效率。如果你的团队还没有明确的规范,不妨从今天开始,从一份简单的分支命名规则、一次规范的 PR 提交做起。


