3.2 分支的增删与切换


3.2 分支的增删与切换

本节摘要:分支操作的核心命令是 git branch(列/建/删)和 git switch(切换,推荐替代 checkout)。本节逐个演示列出、创建、切换、创建并切换、安全删除与强制删除六类操作,穿插 git branch -v、--merged、--no-merged 等查看技巧,并提醒分离 HEAD 与删除未合并分支的风险。

阅读收获

阅读完本节,你应当能够:

  1. 用 git branch 列出本地/远程/全部分支,并区分当前分支标记。
  2. 用 git branch 名字 创建分支,用 git switch 切换分支。
  3. 用 git switch -c 一步创建并切换,理解它为什么是高频操作。
  4. 用 -d 安全删除已合并分支、-D 强制删除未合并分支,说清两者的风险差异。
  5. 用 --merged、--no-merged、-v 等选项快速了解分支状态。

一、问题与直觉

学会开分支之后,下一个现实问题是:分支开了一堆,怎么管? 每天面对 git branch 列出的十几条分支,你需要快速知道三件事:

  1. 我现在在哪条分支上?
  2. 这些分支里哪些还活着(有未合并的提交)、哪些是"已死"该清理的?
  3. 我要去的那条分支,切过去安全吗?

本节把这三件事对应的命令全部讲清。你会发现,分支管理其实是一套"低风险、高频率"的操作——每一步都不难,难的是养成"切分支前先确认"的习惯。很多团队事故(改错分支、误删分支)都不是命令不会,而是没确认。

先说一个"确认"的例子。有一次我在仓库里工作,本想切到 feature 分支改代码,结果一敲 git switch feature,工作区文件唰地全变了,才发现自己刚才其实在 main 上改了一下午。幸好改动不冲突,Git 帮我把它们带了过去。这事给我的教训是:切分支前看一秒钟 status,比事后慌乱半小时便宜得多。本节反复强调的各种"先确认",都是这类事故换来的经验。

再补充一个认知:分支操作的命令不多,但组合场景不少。真正的高手不是背命令,而是"看一眼现状就知道该做什么、下一步会发生什么"。比如看到 git branch --no-merged 列出一堆分支,就知道这些分支删不得;看到 git branch -v 里某分支的哈希和 main 一样,就知道它俩内容相同可以放心删。命令是死的,判断力是活的——本节所有小节都在帮你建立这种判断力。

二、核心原理

列出分支:git branch

不带参数的 git branch 列出所有本地分支,当前分支带星号标记:

$ git branch develop * main feature/new-feature

三个常用变体:

git branch -r # 只列远程跟踪分支(origin/main 之类) git branch -a # 列出本地 + 远程全部 git branch -v # 附带每个分支指向的最新提交哈希与消息

两个过滤选项格外实用:

git branch --merged # 已合并到当前分支的(通常是"可清理"的) git branch --no-merged # 尚未合并的(有独有提交,删除要谨慎)

--merged 是清理分支的利器——列出的通常都是可以安全删掉的。

创建分支:git branch 名字

git branch 新分支名 在当前提交上创建新指针,但不切换——你仍留在原分支。基于其他提交创建:

git branch feature develop # 基于 develop 分支的最新提交 git branch bugfix/v1.0 a1b2c3d # 基于某个特定提交

注意创建后 HEAD 没动,当前分支不变。很多人以为 git branch 会"跳过去",实际不会——创建与切换是两个独立动作。

创建分支后 HEAD 不动,仍在原分支;要切换得再执行 git switch。

切换分支:git switch

git switch 分支名 把 HEAD 指向目标分支,并把工作区更新成该分支的内容:

git switch feature Switched to branch 'feature'

创建并切换一步完成(日常最高频操作):

git switch -c feature/login Switched to a new branch 'feature/login'

-c(--create)等价于 git branch 名字 + git switch 名字。99% 的开分支场景都用这一条就够了。

为什么推荐 switch 而不是 checkout? checkout 是老命令,一身兼数职(切分支、恢复文件、创建分支),功能多到让人混淆——git checkout 文件 是恢复文件,git checkout 分支 是切分支,两个动作写在同一条命令里,意图经常分不清。Git 2.23 起把切分支拆给 switch、恢复文件拆给 restore,各自意图明确。新项目请习惯用 switch + restore。

删除分支:git branch -d / -D

安全删除 -d:只有当分支的提交都已合并到当前分支(或其上游)时才允许删除:

git branch -d feature/login Deleted branch feature/login (was a1b2c3d).

如果分支还有未合并的提交,-d 会拒绝并提示用 -D:

error: The branch 'feature/login' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature/login'.

强制删除 -D:无条件删除,即使有未合并提交。用前想清楚:这条分支上的独有提交如果没被任何其他分支引用,就会"失去入口",只能靠 reflog 或记下的哈希找回。删"实验失败"的分支,-D 是常态;删正常功能分支前,先确认已经合并过。如果拿不准,还有个折中方案:先把分支的关键提交哈希记下来,再删除,真后悔了还能靠哈希找回。

一套完整的"分支生命周期"实操

把本节所有命令串成一个完整剧本,跟着走一遍,分支管理就齐活了:

# 初始化并提交 git init branch-life && cd branch-life echo a > a.txt && git add . && git commit -m "初始提交" # 创建并切换 git switch -c feature/user-login echo login > login.txt && git add . && git commit -m "添加登录功能" # 回主干看分支情况 git switch main git branch # main 在前,feature/user-login 在后 git branch -v # 能看到每个分支的最新提交 # 合回主干并删除 git merge feature/user-login git branch -d feature/user-login git branch # 只剩 main,干净 # 演示 -D:创建一条"烂尾"分支 git switch -c experiment/fail echo junk > junk.txt && git add . && git commit -m "半成品" git switch main git branch -d experiment/fail # 报错:未合并 git branch -D experiment/fail # 强制删除成功

这个剧本把"建、切、看、合、删"全部演了一遍。特别是最后 -d 报错、-D 成功的那一段,亲身体会一次,以后就不会把两条命令搞混了。

切换分支时,工作区文件发生了什么

一个值得反复体会的细节:git switch main 之后,你工作区里的文件内容会跟着变——这正是指针模型的实际效果。假设 main 里 a.txt 是"v1",feature 里 a.txt 是"v2",切换时 a.txt 的内容就会在 v1 和 v2 之间来回变。这不是"文件被改坏了",而是"工作区被更新成了目标分支的状态"。

由此引出一个必须记住的规则:有未提交改动时切分支要小心。如果改动在 main 和 feature 之间不冲突,Git 会帮你带着改动切过去;如果冲突,Git 会拒绝切换(阻止你把改动弄丢)。想彻底理解这条规则,可以亲手试一次:在 main 上改 a.txt 不提交,然后 switch 到 feature——观察 Git 的反应。

三、工程实践要点

切分支前的一分钟检查

切换分支会改变工作区内容,如果有未提交的改动,Git 可能阻止切换或带着改动一起切。安全的流程是:

  1. git status:确认工作区状态。
  2. 有未提交改动想保留 → git stash(第 5 章)或先提交。
  3. 干净了再 git switch 目标分支

分支清理的例行节奏

建议每完成一个功能就清理一次,别攒:

git switch main # 回主干 git merge feature/login # 合入 git branch -d feature/login # 删掉已合并的功能分支 git branch --merged # 复查还有没有漏网的

有个常见现象值得说透:为什么分支要"即用即删"?除了保持列表干净,还有个实际原因——分支不删,它和主干的差异就会越拉越大,等你想起来再合并时,冲突已经堆积成山。趁热打铁合并删除,是把"合并的痛苦"控制在最小。这也解释了为什么大厂团队规范里都有"feature 分支生命周期不超过 X 天"这类约定:不是仪式感,是工程上的务实选择。

从"命令操作"到"分支策略"

单条命令学完后,把它们拼成策略才有威力。三种最常见的策略:

  • 单人小项目:main 一条线,偶尔开临时分支做实验,够用。
  • 小团队:main 做主线,每人一个 feature 分支,合并回 main。
  • 中大型团队:main(可发布)+ develop(集成)+ feature(开发)+ release(发布冻结)+ hotfix(紧急修复),即著名的 Gitflow 模式。

策略没有绝对对错,只有适不适合团队规模。本节先把"操作层"打牢,第 4 章讲远程协作时,会自然带出"策略在多人场景下怎么落地"。记住:分支策略是对操作的编排,操作学不扎实,策略就是空中楼阁

常见分支操作速查表

想做什么 命令
看当前分支 git branch 或 git status
创建分支 git branch 名字
创建并切换 git switch -c 名字
切换分支 git switch 名字
安全删除 git branch -d 名字
强制删除 git branch -D 名字
看已合并分支 git branch --merged
看未合并分支 git branch --no-merged
看每个分支的最新提交 git branch -v

⚠️ 常见坑:删分支时人在要删的分支上,或删除后才发现忘了合并。删除前先用 --merged 确认,再切到别的分支删。

💡 关键直觉:把分支列表想成"任务看板"。git branch 看板上有哪些任务卡,--merged 是"已完成待归档"的卡,--no-merged 是"还在推进"的卡。-D 就是"把这张卡从板上撕掉"——撕之前确认工作都留过底。

常见问题与 FAQ

"我人在 feature 上,能删掉 main 吗?" 不能删当前所在的分支,Git 会拒绝。想删 main,先切到其他分支。

"切分支时未提交的改动会被带到新分支吗?" 默认会带过去(Git 尝试保留你的改动),但可能造成混乱或切换失败。想干净切换,先 stash 或提交。想强切,用 git switch -f 分支(会丢弃工作区改动,危险)。

"git checkout 还能用吗?" 能,完全兼容,老项目、老习惯都能继续用。只是新写法更推荐 switch/restore 分而治之。你自己喜欢哪个用哪个,团队统一即可。

"怎么给分支改名字?" git branch -m 旧名 新名。改名不改变指向,只是换标签。

"切到不存在的分支会怎样?" Git 会报错提示分支不存在。想基于当前状态创建并切换,用 git switch -c;想从远程拉一条本地没有的分支,用 git switch 远程分支名(Git 会自动创建跟踪的本地分支,第 4 章细讲)。

"我忘了我上次在哪条分支上,怎么办?"git reflog 看 HEAD 的移动记录,能找到每次切换的痕迹;或者直接 git branch 看当前星号在哪。养成"开工先 git status"的习惯,这个问题自然消失。

"多个分支同时开发,会不会互相污染?" 不会。每个分支有自己的提交链和工作区状态,切换时互不影响。真正的"污染"只发生在两类场景:把未提交的改动带到别的分支、把没合并的分支误删——这两类都有对应的安全机制(Git 会阻止危险切换、-d 会拒绝未合并删除),理解机制比害怕事故更有用。

判断"这个分支能删吗"的三步法

面对一条想删的分支,按顺序自问:

  1. 它合并到当前分支了吗?→ 看 git branch --merged
  2. 如果不确定,它的独有提交还在别处吗?→ 看 git log 分支名 里有没有别的分支覆盖的提交。
  3. 确认可以删了,用 -d;真不要了,用 -D 并承担风险。

这套三步法把"删不删"从"凭感觉"变成"看事实"。刚开始可能觉得麻烦,但它是防止"误删独有提交"最实用的护栏。宁可多查两秒,不删错一条线。

补充一个很多人不知道的细节:删除分支不删除提交。被删分支指向的那个提交对象还留在对象库里,只要你还记得它的哈希(或能从 reflog 查到),随时能 git branch 分支名 哈希 把它"复活"。这也是"删分支"没有想象中那么可怕的原因——Git 的设计里,绝大多数操作都可逆,理解这个底层逻辑,操作时就少了无谓的恐惧。

要点串联

  • 列出:git branch、-r、-a、-v,当前分支带星号。
  • 过滤:--merged 是"可清理",--no-merged 是"要谨慎"。
  • 创建:git branch 名字只建不切,基于其他提交用 git branch 名字 基点。
  • 切换:git switch 切换;git switch -c 创建并切换,日常最高频。
  • switch vs checkout:新命令职责单一,推荐 switch+restore 组合。
  • 删除:-d 安全(须已合并),-D 强制(小心独有提交丢失)。
  • 切分支安全:先 status、处理未提交改动,再切换。
  • 分支策略:单人/小团队/Gitflow 三种模式按规模选择。
  • 删分支三步法:查 merged、查独有提交、再决定 -d 或 -D。
  • 习惯:切分支前 status,功能做完立即合并删除。
  • 事故预防:切分支前看一秒钟 status,比事后慌乱半小时便宜得多。

下一节把分支合回来:git merge 的快进合并与三方合并,以及 --no-ff、--squash 的取舍。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U