Git 分支管理指南:从基础概念到团队协作规范
背景
在多人协作开发中,缺乏清晰的 Git 分支管理规范常导致代码覆盖、版本回滚困难及冲突堆积等问题。Git 的分支能力本是版本控制的利器,但如果使用无章,就会变成团队协作的绊脚石。掌握科学的分支管理策略,是提升开发效率、降低线上风险的关键。
Git 分支管理是版本控制的核心能力,解决并行开发、风险隔离与版本回溯问题。本文详解分支与 HEAD 指针原理,涵盖查看、创建、切换、合并及冲突解决等核心命令。通过禁用 Fast forward 模式、制定分支策略(master/dev)、临时分支修复 Bug 及清理冗余分支,建立规范的团队协作流程,提升开发效率并降低线上风险。

在多人协作开发中,缺乏清晰的 Git 分支管理规范常导致代码覆盖、版本回滚困难及冲突堆积等问题。Git 的分支能力本是版本控制的利器,但如果使用无章,就会变成团队协作的绊脚石。掌握科学的分支管理策略,是提升开发效率、降低线上风险的关键。
本文将从为什么要做分支管理出发,层层拆解核心概念、主流策略、实操命令和避坑指南,既兼顾新手的入门理解,也满足团队协作的实战需求。
Git 分支是版本控制的核心能力,它能解决三大核心问题:
分支就像是平行宇宙,当你正在一个分支学习时,另一个分支可以独立运行。如果两个分支互不干扰,对当前工作没影响。在某个时间点,两个分支合并了,结果整合了双方的成果。
master 分支指向最新的稳定提交,feature/login 分支指向登录功能的最新提交。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 来查看。
<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 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。
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 分支上工作效果是一样的,但过程更安全。
若合并的两个分支修改了'同一文件的同一部分'(如 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 分支使用完毕后就可以删除了。
通常合并分支时,如果可能,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 合并后就看不出来曾经做过合并。
在实际开发中,我们应该按照几个基本原则进行分支管理: 首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; 那在哪里干活呢?干活都在 dev 分支上,也就是说,dev 分支是不稳定的,到某个时候,比如 1.0 版本发布时,再把 dev 分支合并到 master 上,在 master 分支上发布 1.0 版本; 你和你的小伙伴们每个人都在 dev 分支上干活,每个人都有自己的分支,时不时地往 dev 分支上合并就可以了。
假如我们现在正在 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).
软件开发中,总有无穷无尽的新的功能要不断添加进来。添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个分支,我们可以将其称之为 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 提交做起。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online