尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

第 6 篇:Git 分支进阶:分支策略、stash、bugfix 和 feature 开发

第 6 篇:Git 分支进阶:分支策略、stash、bugfix 和 feature 开发
📅 发布时间:2026/7/8 5:14:28

文章目录

  • Git 分支进阶:分支策略、stash、bugfix 和 feature 开发
    • 一、Fast-forward 模式的问题
    • 二、使用 --no-ff 保留分支合并记录
    • 三、常见分支策略:master、dev 与临时分支
    • 四、临时修 Bug 前,先用 stash 保存现场
    • 五、使用临时分支修复 Bug
    • 六、恢复现场并继续开发
    • 七、将 Bug 修复同步到开发分支
    • 八、Feature 分支与未合并分支删除
    • 九、本文总结

Git 分支进阶:分支策略、stash、bugfix 和 feature 开发

上一篇已经把分支的基础操作梳理了一遍,包括创建分支、切换分支、合并分支、删除分支,以及冲突解决。掌握这些命令之后,还需要继续往前走一步:实际开发中应该怎样组织分支,遇到临时 Bug 怎么处理,开发到一半的代码又该怎么临时保存。

这一篇重点整理几个更贴近日常开发的内容:

  • Fast-forward模式的问题。
  • 使用--no-ff保留分支合并记录。
  • 常见的master/dev/临时分支管理方式。
  • 使用git stash保存工作现场。
  • 用临时分支修复 Bug。
  • 将主分支上的修复同步回开发分支。
  • feature 分支开发中止时如何删除未合并分支。

下面还是接着前面的仓库状态继续操作。

一、Fast-forward 模式的问题

通常情况下,合并分支时只要条件允许,Git 会优先采用Fast-forward模式,也就是快进合并。

比如master分支没有新的提交,而dev分支只是在master的基础上往前走了几步,那么合并时 Git 不需要额外生成一个合并提交,只要把master指针直接移动到dev指向的位置即可。

这种方式很快,也很干净:

但它也有一个问题:如果合并完成后删除了临时分支,从历史记录里就不容易看出这次提交到底是直接在主分支上做的,还是从某个分支合并进来的。

换句话说,Fast-forward会让提交历史变成一条直线。直线历史本身没有错,但如果团队希望保留“这个功能曾经在一个独立分支上开发过”的信息,快进合并就不够明显。

对比一下上一篇解决冲突之后的合并历史。因为冲突合并会产生一次新的合并提交,所以历史上能看出分叉与合并:

即使后面把dev1分支删除,git log --graph里仍然能看到当时发生过一次分支合并:

hyb@139-159-150-152:~/gitcode$ git branch*master hyb@139-159-150-152:~/gitcode$ git branch-d dev1 Deleted branchdev1(was c594fd1).hyb@139-159-150-152:~/gitcode$ git log--graph--pretty=oneline--abbrev-commit*2976afc(HEAD->master)merge ReadMe|\|*c594fd1 modify ReadMe*|c10f6d0 modify ReadMe|/

这里能看出master的最新提交来自一次合并,而不是普通的线性提交。这种历史在回溯问题时更有价值。

二、使用 --no-ff 保留分支合并记录

如果希望即使可以快进,也强制 Git 生成一次合并提交,就可以使用--no-ff。

--no-ff的意思是禁用Fast-forward,让 Git 按普通合并方式处理。这样做的好处是:合并历史里会明确保留一次 merge commit,方便之后知道某个功能分支是什么时候合并进来的。

先创建并切换到一个新的dev2分支:

hyb@139-159-150-152:~/gitcode$ git checkout-b dev2 Switched to anewbranch'dev2'

在dev2上修改ReadMe并提交:

hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d hyb@139-159-150-152:~/gitcode$ git add.hyb@139-159-150-152:~/gitcode$ git commit-m"modify ReadMe"[dev241b082f]modify ReadMe

然后切回master,使用--no-ff合并:

hyb@139-159-150-152:~/gitcode$ git checkout master Switched to branch'master'hyb@139-159-150-152:~/gitcode$ git merge--no-ff-m"merge with no-ff"dev2 Merge made by the'recursive'strategy.ReadMe|1+hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d

注意这里加了-m "merge with no-ff"。因为--no-ff会生成一次新的合并提交,所以需要写提交说明。

查看提交历史:

hyb@139-159-150-152:~/gitcode$ git log--graph--pretty=oneline--abbrev-commit*5bd16b4(HEAD->master)merge with no-ff|\|*41b082f(dev2)modify ReadMe|/

此时历史结构就很清楚了:

总结一下:

  • Fast-forward:历史更线性、更简洁,但删除分支后不容易看出分支合并痕迹。
  • --no-ff:会多一次合并提交,但能保留分支开发和合并的轨迹。

实际项目里没有绝对固定的答案。如果是个人小项目,快进合并很清爽;如果是多人协作、功能分支比较多的项目,--no-ff往往更方便追踪历史。

三、常见分支策略:master、dev 与临时分支

命令学会之后,真正容易出问题的地方反而是:分支到底应该怎么用?

一种常见思路是:

  • master分支保持稳定,通常只放已经验证过、可以发布的代码。
  • dev分支用于日常开发整合,它比master更活跃,也更容易变化。
  • 每个功能或 Bug 都使用临时分支处理,完成后再合并回dev或master。

这样做的核心目标是:稳定代码和开发中代码分开,公共分支和个人临时修改分开。

比如一个团队里,主分支master负责发布版本;开发分支dev负责汇总大家正在开发的内容;每个人开发新功能时,再从dev上拉出自己的临时分支。等功能完成后,临时分支再合并回dev。

整体关系大概如下:

这里先不展开企业级分支模型,后面多人协作部分会更系统地看feature、release、develop、hotfix这些分支。当前阶段先记住一句话:不要把所有工作都堆在主分支上,临时任务应该用临时分支承载。

四、临时修 Bug 前,先用 stash 保存现场

实际开发中经常遇到这种场景:我正在dev2分支上开发一个功能,代码写到一半,还没到适合提交的程度,突然发现master上有一个紧急 Bug 需要马上修。

这时会有一个尴尬点:当前工作区有未提交修改,直接切分支可能不方便;强行提交半成品代码也不好,因为这个提交本身并不完整。

比如当前dev2分支上有未提交内容:

hyb@139-159-150-152:~/gitcode$ git branch*dev2 master hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d i am coding...hyb@139-159-150-152:~/gitcode$ git status On branch dev2 Changesnotstagedforcommit:(use"git add <file>..."to update what will be committed)(use"git restore <file>..."to discard changes in working directory)modified:ReadMe no changes added tocommit(use"git add"and/or"git commit -a")

这时可以使用git stash暂存当前工作现场:

hyb@139-159-150-152:~/gitcode$ git stash Saved working directoryandindex state WIP on dev2:41b082f modify ReadMe hyb@139-159-150-152:~/gitcode$ git status On branch dev2 nothing to commit,working tree clean

git stash可以把当前工作区和暂存区的修改临时保存起来,让工作区恢复干净。这样就可以放心切换分支去处理别的事情。

注意,stash适合保存“还不适合作为一次提交”的临时现场。它不是用来替代正常提交的。真正完成的功能还是应该用commit固化下来。

五、使用临时分支修复 Bug

现场保存好之后,就可以回到master,从master创建一个专门修 Bug 的分支。

hyb@139-159-150-152:~/gitcode$ git checkout master Switched to branch'master'hyb@139-159-150-152:~/gitcode$ git checkout-b fix_bug Switched to anewbranch'fix_bug'

在fix_bug分支上修复问题并提交:

hyb@139-159-150-152:~/gitcode$ vim ReadMe hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d,e hyb@139-159-150-152:~/gitcode$ git add ReadMe hyb@139-159-150-152:~/gitcode$ git commit-m"fix bug"[fix_bug4bbc0c4]fix bug

修复完成后,切回master,把fix_bug合并进去,然后删除临时分支:

hyb@139-159-150-152:~/gitcode$ git checkout master Switched to branch'master'hyb@139-159-150-152:~/gitcode$ git merge--no-ff-m"merge fix_bug branch"fix_bug Merge made by the'recursive'strategy.ReadMe|2+-hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d,e hyb@139-159-150-152:~/gitcode$ git branch-d fix_bug Deleted branchfix_bug(was4bbc0c4).

这套流程的好处是很清晰:

  • 未完成的新功能仍然放在原来的开发分支。
  • 紧急 Bug 在独立分支修复。
  • 修复完成后合并回稳定分支。
  • 临时分支完成使命后删除。

六、恢复现场并继续开发

Bug 修复完成后,还要回到dev2继续刚才没写完的功能。

hyb@139-159-150-152:~/gitcode$ git checkout dev2 Switched to branch'dev2'hyb@139-159-150-152:~/gitcode$ git status On branch dev2 nothing to commit,working tree clean

此时工作区是干净的,因为刚才未完成的内容被stash保存起来了。可以先查看保存列表:

hyb@139-159-150-152:~/gitcode$ git stash list stash@{0}:WIP on dev2:41b082f modify ReadMe

使用git stash pop恢复现场:

hyb@139-159-150-152:~/gitcode$ git stash pop On branch dev2 Changesnotstagedforcommit:(use"git add <file>..."to update what will be committed)(use"git restore <file>..."to discard changes in working directory)modified:ReadMe no changes added tocommit(use"git add"and/or"git commit -a")Dropped refs/stash@{0}(4f873250b3503687b5efd26196776aee7e3724c2)

pop的含义是:恢复现场,并把这条 stash 记录删除。

再次查看 stash 列表,已经没有可恢复内容:

hyb@139-159-150-152:~/gitcode$ git stash list hyb@139-159-150-152:~/gitcode$

还有另一种恢复方式:

git stash apply stash@{0}

apply只恢复,不删除 stash 记录。如果确认不需要这条记录了,可以再手动删除:

git stash drop stash@{0}

简单区分一下:

  • git stash pop:恢复并删除,适合最常见的临时保存场景。
  • git stash apply:只恢复不删除,适合想多次尝试恢复的场景。
  • git stash drop:删除指定 stash 记录。
  • git stash list:查看当前保存过的工作现场。

恢复现场后,继续完成开发并提交:

hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d i am coding...Done!hyb@139-159-150-152:~/gitcode$ git add.hyb@139-159-150-152:~/gitcode$ git commit-m"modify ReadMe"[dev2 ed0916d]modify ReadMe

到这里,dev2上的新功能也继续完成了。

七、将 Bug 修复同步到开发分支

现在还有一个问题:刚才 Bug 是在master上修好的,而dev2是之前从旧的master拉出来的,所以dev2上并没有这个 Bug 修复。

当前状态可以理解为:

如果最后直接切到master合并dev2,有可能在master上遇到冲突。对于重要分支来说,这不是一个好习惯。更推荐的做法是:先在自己的开发分支上合并最新的master,如果有冲突就在开发分支解决并测试,确认没问题后,再让master合并开发分支。

这样可以把风险留在开发分支上,而不是把冲突处理过程直接放到稳定分支上。

直接在master上合并开发分支,风险大概是这样:

更推荐的流程是先让dev2吸收master的最新修复:

开发分支解决冲突并测试后,再合并回master:

对应操作如下。当前在dev2上,先合并master:

hyb@139-159-150-152:~/gitcode$ git branch*dev2 master hyb@139-159-150-152:~/gitcode$ git merge master Auto-merging ReadMeCONFLICT(content):Merge conflict in ReadMe Automatic merge failed;fix conflictsandthen commit the result.

出现冲突后查看文件:

hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch<<<<<<<HEAD a,b,c,d i am coding...Done!=======a,b,c,d,e>>>>>>>master

这里的含义是:

  • HEAD部分是当前dev2分支上的内容。
  • master部分是主分支中修复 Bug 后的内容。
  • 最终文件应该同时保留 Bug 修复和dev2上的新功能内容。

手动整理后的文件如下:

hyb@139-159-150-152:~/gitcode$ vim ReadMe hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d,e i am coding...Done!hyb@139-159-150-152:~/gitcode$ git add.hyb@139-159-150-152:~/gitcode$ git commit-m"merge master"[dev2447d29f]merge master hyb@139-159-150-152:~/gitcode$ git status On branch dev2 nothing to commit,working tree clean

此时dev2已经包含master上的 Bug 修复,也包含自己的新功能。确认测试没有问题后,再切回master合并dev2:

hyb@139-159-150-152:~/gitcode$ git checkout master Switched to branch'master'hyb@139-159-150-152:~/gitcode$ git merge dev2 Updating193421f..447d29f Fast-forward ReadMe|1+hyb@139-159-150-152:~/gitcode$ git status On branch master nothing to commit,working tree clean

这时master合并dev2就很顺利了,因为冲突已经在dev2上处理过。

最后删除dev2:

hyb@139-159-150-152:~/gitcode$ git branch-d dev2 Deleted branchdev2(was447d29f).

这个流程在多人协作中很重要:不要把冲突解决和验证工作直接压到稳定分支上,先在自己的分支上同步主分支并解决问题,会稳很多。

八、Feature 分支与未合并分支删除

新功能开发时,通常会创建一个独立的 feature 分支。比如要开发一个新需求,就从当前开发分支拉出一个临时分支,在里面开发、提交、测试,完成后再合并。

这类分支的价值是:把一个功能相关的改动集中在一起,不干扰其他分支。

不过实际开发里也会遇到功能中止的情况。比如某个新功能做到一半,需求突然取消了,这个 feature 分支就不需要继续保留。如果这个分支上的提交还没有合并到主线,普通删除会失败。

先创建一个dev3分支模拟新功能开发:

hyb@139-159-150-152:~/gitcode$ git checkout-b dev3 Switched to anewbranch'dev3'

在dev3上开发并提交:

hyb@139-159-150-152:~/gitcode$ vim ReadMe hyb@139-159-150-152:~/gitcode$ cat ReadMe hello bit hello git hello world hello version1 hello version2 hello version3 write bbbfornewbranch a,b,c,d,e i am coding...Done!i am writingnewfeatures...hyb@139-159-150-152:~/gitcode$ git add.hyb@139-159-150-152:~/gitcode$ git commit-m"modify ReadMe for new features"[dev3 cd2f149]modify ReadMefornewfeatures

现在假设这个功能停止开发,切回master准备删除dev3:

hyb@139-159-150-152:~/gitcode$ git checkout master Switched to branch'master'

使用普通删除:

hyb@139-159-150-152:~/gitcode$ git branch-d dev3 error:The branch'dev3'isnotfully merged.If you are sure you want todeleteit,run'git branch -D dev3'.

Git 阻止删除,是因为dev3上有提交还没有合并。如果直接删除,这些提交就会变得很难再找回来。这个保护非常有用,可以避免误删有价值的分支。

但如果确认这个功能确实不要了,可以强制删除:

hyb@139-159-150-152:~/gitcode$ git branch-D dev3 Deleted branchdev3(was cd2f149).hyb@139-159-150-152:~/gitcode$ git branch*master

这里要区分两个命令:

  • git branch -d 分支名:安全删除。分支已经合并时才允许删除。
  • git branch -D 分支名:强制删除。即使分支没有合并,也会删除。

所以,-D不要随手用。它适合“明确废弃”的实验分支或需求取消分支,不适合不加确认地清理分支。

九、本文总结

  • Fast-forward合并会让历史保持线性,但删除分支后不容易看出分支合并痕迹。
  • git merge --no-ff -m "说明" 分支名可以强制生成合并提交,保留分支合并历史。
  • 常见分支策略里,master保持稳定,dev承载日常开发,临时分支负责具体功能或 Bug。
  • 开发到一半需要切走时,可以用git stash保存现场,让工作区恢复干净。
  • git stash pop会恢复并删除 stash 记录,git stash apply只恢复不删除。
  • 修复紧急 Bug 时,可以从稳定分支创建fix_bug临时分支,修复后合并回去并删除。
  • 主分支有新修复后,建议先在自己的开发分支合并主分支,解决冲突并测试,再合并回主分支。
  • feature 分支适合承载独立功能开发,功能完成后合并,功能取消后可以按情况删除。
  • git branch -d是安全删除,git branch -D是强制删除,后者要谨慎使用。

到这里,分支已经不只是几个命令了,而是逐渐变成一种开发组织方式。后面继续看远程仓库时,分支会和clone、push、pull、远程分支一起出现,使用场景会更接近真实团队协作。

相关新闻

  • 2026 年射频测试仪器保养与校准周期指南——延长寿命、保证数据可靠
  • 为什么你的校园生意只能做两三个月?缺一套长效经营体系
  • 各向异性可见性建模:让机器人真正理解‘看得见’的物理含义

最新新闻

  • FastAPI订单防超卖实战:从数据库锁到Saga分布式事务,这一篇给你理清了
  • 10-30V直流,每轴1.9A RMS——六轴控制集成度做到这个水平,只需一块TMCM-6214
  • 终极LLM评估革命:DeepEval如何用数据驱动重塑AI质量保障体系
  • TestDisk PhotoRec终极指南:专业级数据恢复与分区修复实战
  • Midjourney v6 与 Flux.1 真人头像生成对比:5组提示词实测与风格差异解析
  • C# 枚举(Enum)详解

日新闻

  • PROPKA 3深度解析:蛋白质pKa预测的实战指南与算法原理
  • 微信小程序 globalData 监听:基于 Object.defineProperty 的 3 种实现方案对比
  • MySQL 8.0 数据清洗实战:3类异常值识别与 UPDATE/DELETE 批量处理

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号