核心概念
一句话总结
- Branch(分支):可移动的指针,用于开发
- Tag(标签):固定的书签,用于标记版本
形象比喻
Branch 像导航路标
想象你在修路(开发项目):
起点 ──→ 路段A ──→ 路段B ──→ 路段C
↑
路标(main分支)
修新路段D后,路标会往前移:
起点 ──→ 路段A ──→ 路段B ──→ 路段C ──→ 路段D
↑
路标(自动前进)
Tag 像里程碑
想象公路上的里程碑:
起点 ──→ 100km ──→ 200km ──→ 300km
↑ ↑ ↑
里程碑1 里程碑2 里程碑3
即使继续修路,里程碑的位置永远不变:
起点 ──→ 100km ──→ 200km ──→ 300km ──→ 400km
↑ ↑ ↑
v1.0.0 v2.0.0 v3.0.0(固定不变)
深入理解 Branch
Branch 的工作原理
初始状态:
A ← B ← C
↑
main分支(指针)
提交新 commit D:
A ← B ← C ← D
↑
main(自动移动)
再提交 commit E:
A ← B ← C ← D ← E
↑
main(继续移动)
Branch 的特点
✅ 可移动性
bash
# 每次提交,分支指针都会自动前进
git commit -m "新功能" # main分支自动移到新commit
✅ 可以同时存在多个
D ← E ← feature分支
↗
A ← B ← C ← F ← G ← main分支
✅ 可以合并
bash
git merge feature # 把feature分支合并到main
✅ 可以删除
bash
git branch -d feature # 删除分支(commit不会删除)
Branch 的本质
Branch 只是一个指向 commit 的指针
bash
# 查看分支指向哪个commit
$ git log main -1
commit abc1234... (main)
# 本质上,分支存储在这里:
.git/refs/heads/main # 文件内容就是commit的hash
深入理解 Tag
Tag 的工作原理
发布版本历史:
A ← B ← C ← D ← E ← F ← G
↑ ↑ ↑
v1.0.0 v2.0.0 v3.0.0(永远固定)
继续开发:
A ← B ← C ← D ← E ← F ← G ← H ← I
↑ ↑ ↑
v1.0.0 v2.0.0 v3.0.0(位置不变!)
Tag 的特点
🔒 不可移动性
bash
# Tag创建后就固定了
git tag v1.0.0 # 创建tag
git commit -m "新提交" # tag位置不变
🔒 只能删除,不能"移动"
bash
# 如果打错了tag,只能删除重建
git tag -d v1.0.0 # 删除旧tag
git tag v1.0.0 abc123 # 在正确的commit上重建
🔒 通常用于标记发布版本
bash
git tag -a v4.0.3 -m "Release version 4.0.3"
Tag 的本质
Tag 是一个永久指向特定 commit 的引用
bash
# Tag存储在这里:
.git/refs/tags/v4.0.3 # 永远指向同一个commit
# 查看tag信息
$ git show v4.0.3
tag v4.0.3
Tagger: Jesse Vincent <jesse@fsck.com>
Date: Thu Jan 23 2026
Release v4.0.3: Strengthen using-superpowers
关键区别对比
直观对比表
| 特性 | Branch(分支) | Tag(标签) |
|---|---|---|
| 作用 | 开发、追踪进度 | 标记版本、存档 |
| 移动性 | ✅ 自动移动 | ❌ 固定不动 |
| 可修改 | ✅ 可以提交新内容 | ❌ 只读(技术上可以删除重建) |
| 生命周期 | 可以删除 | 通常永久保留 |
| 使用场景 | 日常开发 | 版本发布 |
| checkout后 | 正常状态 | Detached HEAD状态 |
| 命名约定 | 功能描述(feature/xxx) | 版本号(v1.0.0) |
技术层面对比
1. 存储位置不同
bash
# 分支
.git/refs/heads/main
.git/refs/heads/develop
# 标签
.git/refs/tags/v1.0.0
.git/refs/tags/v2.0.0
2. checkout 行为不同
bash
# checkout 分支 → 正常状态
$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
# checkout tag → Detached HEAD
$ git checkout v4.0.3
Note: switching to 'v4.0.3'.
You are in 'detached HEAD' state...
HEAD is now at b9e1649 Release v4.0.3
3. 提交行为不同
bash
# 在分支上提交
$ git checkout main
$ git commit -m "新功能"
[main abc1234] 新功能 # ✅ 分支自动前进
# 在tag上"提交"(实际上不推荐)
$ git checkout v4.0.3
$ git commit -m "修改"
[detached HEAD xyz5678] 修改 # ⚠️ commit游离,容易丢失
实际应用场景
Branch 的使用场景
场景1:功能开发
bash
# 创建功能分支
git checkout -b feature/user-login
# 开发过程中多次提交
git commit -m "添加登录表单"
git commit -m "实现登录逻辑"
git commit -m "添加错误处理"
# 合并回主分支
git checkout main
git merge feature/user-login
场景2:Bug 修复
bash
# 创建修复分支
git checkout -b fix/login-error
# 修复并提交
git commit -m "修复登录超时问题"
# 合并
git checkout main
git merge fix/login-error
场景3:并行开发
bash
# 团队成员各自开发
git checkout -b feature/payment # 张三开发支付
git checkout -b feature/admin # 李四开发后台
git checkout -b feature/mobile # 王五开发移动端
# 各自完成后合并到main
Tag 的使用场景
场景1:版本发布
bash
# 开发完成,准备发布v1.0.0
git checkout main
git tag -a v1.0.0 -m "首次正式发布"
git push origin v1.0.0
# 用户下载
git clone https://github.com/xxx/project.git
cd project
git checkout v1.0.0 # 获取1.0.0版本
场景2:Bug 回溯
bash
# 用户报告:"v2.3.1有bug"
# 开发者立即检出那个版本
git checkout v2.3.1
# 复现bug,找到问题所在
场景3:版本对比
bash
# 对比两个发布版本的差异
git diff v1.0.0 v2.0.0
# 查看某个版本的代码
git show v1.5.0:src/main.js
💡 重点总结
核心原则
-
开发用 Branch,发布用 Tag
- Branch是活的(movable)
- Tag是死的(immutable)
-
Branch 可以改,Tag 不能改
- Branch:可以随意提交、合并、删除
- Tag:创建后就固定,只能删除重建
-
Checkout 行为不同
git checkout <branch>→ 正常工作模式git checkout <tag>→ Detached HEAD模式(只读)
记忆口诀
分支动,标签静
开发用分支,发布打标签
分支可移动,标签不能变
切换分支正常,切换标签警告
最佳实践
✅ DO(推荐)
- 用分支进行日常开发
- 发布版本时打tag
- Tag命名遵循语义化版本(v1.2.3)
- 重要版本永久保留tag
❌ DON'T(不推荐)
- 不要在tag上直接开发
- 不要随意删除已发布的tag
- 不要用分支来标记版本
- 不要在detached HEAD状态下长期工作