目录
[1.1 origin/feature/driver 是什么?](#1.1 origin/feature/driver 是什么?)
[1.2 fetch / merge / pull 到底是什么?](#1.2 fetch / merge / pull 到底是什么?)
[三、场景 1:同一分支上,本地改动不需要保留(直接丢弃)](#三、场景 1:同一分支上,本地改动不需要保留(直接丢弃))
[3.1 先确认你改到哪一层(决定用哪条命令)](#3.1 先确认你改到哪一层(决定用哪条命令))
[1)丢弃工作区改动(没 add 的情况)](#1)丢弃工作区改动(没 add 的情况))
[2)如果你 add 过(暂存区也被污染)](#2)如果你 add 过(暂存区也被污染))
[3.2 清理完成后,拉取公司最新代码(对齐远端)](#3.2 清理完成后,拉取公司最新代码(对齐远端))
[1)更新远端快照(只更新 origin/*)](#1)更新远端快照(只更新 origin/*))
[3.3 你在错误分支上乱改了:想删分支重来(最干净)](#3.3 你在错误分支上乱改了:想删分支重来(最干净))
四、场景2:同一分支上,本地改动需要保留(最危险、但经常发生)
[4.1 做法 A:先 commit(最推荐、最清晰)](#4.1 做法 A:先 commit(最推荐、最清晰))
[1)Step 1:确认当前分支](#1)Step 1:确认当前分支)
[2)Step 2:查看改动(工程习惯)](#2)Step 2:查看改动(工程习惯))
[3)Step 3:暂存并提交改动(建立回滚锚点)](#3)Step 3:暂存并提交改动(建立回滚锚点))
[4)Step 4:更新远端快照](#4)Step 4:更新远端快照)
[5)Step 5:合并公司最新到当前分支](#5)Step 5:合并公司最新到当前分支)
[4.2 做法 B:先 stash(适合改到一半,不想形成 commit)](#4.2 做法 B:先 stash(适合改到一半,不想形成 commit))
[1)Step 1:先保存现场](#1)Step 1:先保存现场)
[2)Step 2:拉最新远端快照并合并](#2)Step 2:拉最新远端快照并合并)
[3)Step 3:将之前暂存的改动拿回来](#3)Step 3:将之前暂存的改动拿回来)
[五、场景 3:不同分支(个人功能分支)上,本地改动不需要保留(删分支重建,最干净)------ 与同一分支上方法(3.3)一致](#五、场景 3:不同分支(个人功能分支)上,本地改动不需要保留(删分支重建,最干净)—— 与同一分支上方法(3.3)一致)
[5.1 切走(当前分支不能删除自己)](#5.1 切走(当前分支不能删除自己))
[5.2 删除本地功能分支](#5.2 删除本地功能分支)
[5.3 拉取公司最新快照](#5.3 拉取公司最新快照)
[5.4 基于公司分支重建功能分支](#5.4 基于公司分支重建功能分支)
[六、场景 4:不同分支(个人功能分支)上,本地改动需要保留(最推荐的协作方式)](#六、场景 4:不同分支(个人功能分支)上,本地改动需要保留(最推荐的协作方式))
[6.1 标准 merge 同步法](#6.1 标准 merge 同步法)
[Step 1:切到你的功能分支](#Step 1:切到你的功能分支)
[Step 2:更新远端快照](#Step 2:更新远端快照)
[Step 3:把公司主线合到你分支](#Step 3:把公司主线合到你分支)
[Step 4:有冲突就解决(第七章),然后推送备份](#Step 4:有冲突就解决(第七章),然后推送备份)
[6.2 什么时候才考虑 rebase?](#6.2 什么时候才考虑 rebase?)
[八、关于"merge 会不会多一个 commit?"](#八、关于“merge 会不会多一个 commit?”)
[8.1 结论先行](#8.1 结论先行)
[8.2 分清三个层级](#8.2 分清三个层级)
[1️⃣ 本地分支(local branch)](#1️⃣ 本地分支(local branch))
[2️⃣ 远端跟踪分支(origin/xxx)](#2️⃣ 远端跟踪分支(origin/xxx))
[3️⃣ 远端真实分支(公司仓库里的分支)](#3️⃣ 远端真实分支(公司仓库里的分支))
[8.3 真实工程场景举例](#8.3 真实工程场景举例)
[8.4 公司什么时候"才会看到"这个 merge commit?](#8.4 公司什么时候“才会看到”这个 merge commit?)
[✅ 情况 1:你 push 到公司分支(不推荐随便做)](#✅ 情况 1:你 push 到公司分支(不推荐随便做))
[✅ 情况 2:你 push 自己的分支 + 发 PR / MR](#✅ 情况 2:你 push 自己的分支 + 发 PR / MR)
[8.5 用一张"逻辑关系图"强化理解](#8.5 用一张“逻辑关系图”强化理解)
[8.6 总结](#8.6 总结)
[十、Git 冲突合并四象限决策图(工程版)](#十、Git 冲突合并四象限决策图(工程版))
文章摘要
在真实团队开发中,最常见、也最容易翻车的场景就是:
你本地分支已经改了代码(甚至改到一半),与此同时公司远端分支也被同事提交了更新。
这时如果你直接
git pull,很容易出现:冲突爆炸、代码乱、甚至把本地修改弄丢。
本文从工程实践出发,把"本地是否有改动 + 远端是否有更新"的问题,按 分支角色 × 是否保留改动 拆成 四大核心场景 ,并给出每种场景的最稳命令链路 、关键认知点 、冲突解决流程 与常见问题 QA ,让你能真正做到:
✅ 保住自己代码
✅ 吸收公司最新提交
✅ 不踩 detached HEAD
✅ 不误用 fetch/pull
✅ 冲突能解决、历史可回滚、协作更规范
一、统一概念
1.1 origin/feature/driver 是什么?
origin/feature/driver 是 远端分支在你本地的只读快照 ,由 git fetch 更新。
它的特点:
✅ 只能用于对比/同步
❌ 不能在上面直接开发(否则很容易 detached HEAD)
❌ 你的 commit 不可能提交到
origin/xxx上
一句话理解:
origin/xxx = 远端状态的镜像快照,不是你的开发分支。
1.2 fetch / merge / pull 到底是什么?
git fetch origin
(远端仓库 -> 本地仓库)✅ 更新远端快照
origin/*✅ 不会改你的工作区(安全)
git merge origin/xxx
(本地仓库 -> 工作区)✅ 把远端快照合并到你当前分支
✅ 可能产生 merge commit(正常)
git pull****(远端仓库 -> 工作区)✅ =
fetch + merge一步到位⚠️ 你在状态不清楚/本地改动很多时直接 pull,容易出事(新手不建议)

二、进入正题:四大真实场景总览(工程完整版)
真正工程里最稳的分类方式是两条轴:
轴 A:你在哪种分支上?
公共分支:
feature/driver/dev(多人共享)个人功能分支:
feature/kaifa(你自己的)
轴 B:本地改动要不要保留?
不要(可以丢弃)
要(必须保住)
于是得到 四大核心场景:
1)公共分支 + 不保留本地改动
2)公共分支 + 保留本地改动
3)个人分支 + 不保留本地改动
4)个人分支 + 保留本地改动(最推荐的团队协作方式)
三、场景 1:同一分支上,本地改动不需要保留(直接丢弃)
适用:你在
feature/driver上改错了 / 测试代码不想要。目标:清空本地污染 → 对齐公司最新。
3.1 先确认你改到哪一层(决定用哪条命令)
bash
git status
你可能看到:
Changes not staged for commit:工作区改动(没 add)
Changes to be committed:暂存区改动(add 过)
Untracked files:新建文件(未跟踪)
1)丢弃工作区改动(没 add 的情况)
bash
git restore .
旧写法(不建议新人用,但可以提一下):
bash
git checkout -- .
✅ 效果:把所有已跟踪文件恢复到"上一次 commit"的状态。
2)如果你 add 过(暂存区也被污染)
分两步:
① 先清空暂存区:
bash
git restore --staged .
② 再清空工作区:
bash
git restore .
此时再检查:
bash
git status
应该看到:
working tree clean(工作区干净)
3)如果你有新建文件(untracked)
git restore 对 未跟踪文件 无效,你需要:
bash
git clean -fd
-f强制
-d删除目录
⚠️ 这一步很危险,会删文件,
用之前先确认 untracked 里面确实都是垃圾文件
3.2 清理完成后,拉取公司最新代码(对齐远端)
推荐可控的两步法:
bash
git fetch origin
git merge origin/feature/driver
1)更新远端快照(只更新 origin/*)
bash
git fetch origin
你可以验证远端快照更新了没:
bash
git log --oneline --decorate --graph --all -10
2)合并公司最新代码到你当前分支
如果你当前就在要同步的分支上(比如你当前分支就是 feature/driver):
bash
git merge origin/feature/driver
如果你当前不在该分支,建议先切过去:
bash
git switch feature/driver
git merge origin/feature/driver
合并完成后:
bash
git status
应该看到:
working tree clean(工作区干净)
为什么不用 pull?
因为 fetch + merge 你能分清每一步发生了什么,更可控。
3.3 你在错误分支上乱改了:想删分支重来(最干净)
典型:你在
feature/driver写崩了,直接重建一条干净分支
1)先切走(因为当前分支不能被删除)
bash
git switch main(别的分支)
2)强删本地分支
bash
git branch -D feature/driver
3)拉最新远端快照
bash
git fetch origin
4)基于公司分支重建个人分支
bash
git switch -c feature/driver origin/feature/driver
这一套是公司里非常常见的"重开一条干净分支"。
四、场景2:同一分支上,本地改动需要保留(最危险、但经常发生)
- 适用:你在
feature/driver(本地)上写了东西必须保留,同时远端也更新了。此时需要把两边合到一起。
目标:保住你的修改 + 吸收公司的最新提交 ,最后能 push。
核心原则:
先把本地改动变成"可控对象"(commit 或 stash),再同步远端。
最关键的一句:先把本地改动变成"可控状态"
Git 合并时必须保证你对本地改动的"归属"清楚,否则:
合并到一半你不确定哪些是你的
冲突解决时容易误删自己代码
出问题也难回滚
所以,你只有两条安全路线:
✅ A:commit(推荐)
✅ B:stash(临时保存)
4.1 做法 A:先 commit(最推荐、最清晰)
1)Step 1:确认当前分支
bash
git branch --show-current
确认输出是:
feature/driver(当前需要提交的本地分支)
2)Step 2:查看改动(工程习惯)
bash
git status
git diff
3)Step 3:暂存并提交改动(建立回滚锚点)
bash
git add .
git commit -m "feat: 我的本地修改"
✅ 此刻你至少有一个"锚点 commit",随时可以回滚。
4)Step 4:更新远端快照
bash
git fetch origin
5)Step 5:合并公司最新到当前分支
bash
git merge origin/feature/driver
6)结果分两种:
✅ 无冲突:直接
git push❗有冲突:按第七章流程解决,再
git push
4.2 做法 B:先 stash(适合改到一半,不想形成 commit)
1)Step 1:先保存现场
bash
git stash push -m "wip: 临时保存"
确认 stash 成功:
bash
git stash list
2)Step 2:拉最新远端快照并合并
bash
git fetch origin
git merge origin/feature/driver
3)Step 3:将之前暂存的改动拿回来
bash
git stash pop
⚠️ 这一步也可能产生冲突(因为你改动跟公司更新冲突了):同样按第七章解决。
五、场景 3:不同分支(个人功能分支)上,本地改动不需要保留(删分支重建,最干净)------ 与同一分支上方法(3.3)一致
适用:你自己的
feature/kaifa写崩了/不想要了。目标:直接丢弃这条分支,从公司最新重新开一条干净分支。
5.1 切走(当前分支不能删除自己)
bash
git switch main
5.2 删除本地功能分支
bash
git branch -D feature/kaifa
5.3 拉取公司最新快照
bash
git fetch origin
5.4 基于公司分支重建功能分支
bash
git switch -c feature/kaifa origin/feature/driver
这套是公司里非常常见的"重开分支重来"的做法。
六、场景 4:不同分支(个人功能分支)上,本地改动需要保留(最推荐的协作方式)
这就是团队最健康的方式:
公司主开发分支主线:feature/driver不断更新
你开发分支功能:feature/kaifa
你需要"持续吸收主线更新",避免最后一次性冲突爆炸。
✅ 不是把你的分支推回主分支
✅ 而是:把主线更新合到你的分支,避免你开发到最后一次性冲突爆炸
6.1 标准 merge 同步法
Step 1:切到你的功能分支
bash
git switch feature/kaifa
确认:
bash
git branch --show-current
Step 2:更新远端快照
bash
git fetch origin
Step 3:把公司主线合到你分支
bash
git merge origin/feature/driver
Step 4:有冲突就解决(第七章),然后推送备份
bash
git push
(首次 push 别忘了
-u)
6.2 什么时候才考虑 rebase?
merge:协作安全、保留真实分叉历史(新人推荐)
rebase:历史更线性,但冲突处理更敏感(团队明确要求再用)
七、冲突处理标准流程
冲突文件会出现:
bash
<<<<<<< HEAD
你的修改
=======
同事的修改
>>>>>>> origin/feature/driver
标准步骤:
1)只改冲突块:保留双方合理内容
2)保存文件
3)标记已解决:
bash
git add 冲突文件
4)结束合并提交:
bash
git commit -m "merge: resolve conflicts"
5)推送:
bash
git push
八、关于"merge 会不会多一个 commit?"
8.1 结论先行
merge 产生的 commit,默认只存在于你当前的本地分支;
只要你不 push 到公司分支,公司远端是完全看不到的。
8.2 分清三个层级
1️⃣ 本地分支(local branch)
比如:
bash
feature/kaifa feature/driver(本地)
你
git commit你
git merge你解决冲突产生的 commit
👉 全部只发生在本地
2️⃣ 远端跟踪分支(origin/xxx)
比如:
bash
origin/feature/driver
origin/feature/kaifa
这是远端状态的只读快照
只会被
git fetch更新不会因为你本地 merge/commit 而改变
3️⃣ 远端真实分支(公司仓库里的分支)
比如:
bash
公司仓库中的 feature/driver
只有在你 push 到对应分支
或 通过 PR/MR 合并
才会发生变化
8.3 真实工程场景举例
1)场景:你在功能分支上同步公司主线
bash
git switch feature/kaifa
git fetch origin
git merge origin/feature/driver
2)此时发生了什么?
如果无冲突:
可能 fast-forward(不新增 commit)
也可能产生一个 merge commit
如果有冲突:
你解决后
git commit产生一个 merge commit
👉 但注意:
这个 merge commit
只存在于本地的 feature/kaifa 分支
8.4 公司什么时候"才会看到"这个 merge commit?
只有两种情况
✅ 情况 1:你 push 到公司分支(不推荐随便做)
bash
git push origin feature/driver
这通常只有在你是维护者/负责人时才允许
✅ 情况 2:你 push 自己的分支 + 发 PR / MR
bash
git push origin feature/kaifa
然后:
在 GitLab / GitHub / Gitee
发起 PR/MR:feature/kaifa → feature/driver
👉 公司是否看到:
取决于 是否合并 PR
合并后,merge commit 才进入公司分支
8.5 用一张"逻辑关系图"强化理解
bash
本地 feature/kaifa
|
o───o───M ← merge commit(你本地有)
\
o───o origin/feature/driver(远端快照)
公司远端 feature/driver
|
o───o ← 完全没变
只要你 不 push 到 feature/driver:
-
公司分支:❌ 看不到
-
同事:❌ 完全无感知
-
风险:❌ 不存在
8.6 总结
merge 过程中产生的 commit,默认只存在于当前操作的本地分支上
(例如
feature/kaifa)。在 VSCode 中,也只会在该分支看到新的 commit 与 push 提示;
其他公共分支(如feature/driver或其远端跟踪分支origin/feature/driver)只要不将该分支 push 到公司公共分支(或通过 PR/MR 合并),
公司远端分支是完全感知不到这些 commit 的。因此,merge 产生的额外 commit 并不是"污染公司代码",
而是 Git 用来记录分支关系的正常历史节点。
九、命令速查表
| 场景 | 最稳命令链路 |
|---|---|
| 公共分支不保留改动 | restore/clean → fetch → merge |
| 公共分支保留改动 | commit(or stash) → fetch → merge → resolve → push |
| 个人分支不保留改动 | 切走 → 删分支 → fetch → switch -c 重建 |
| 个人分支保留改动(推荐) | switch 功能分支 → fetch → merge 主线 → resolve → push |
十、Git 冲突合并四象限决策图(工程版)
bash
本地改动是否需要保留?
┌───────────────┬────────────────┐
│ 否 │ 是 │
┌───────────────────┼───────────────┼────────────────┤
│ │ │ │
│ 公共分支 │ ① 丢弃改动 │ ② 保留改动 │
│ (feature/driver) │ restore/clean │ commit / stash │
│ │ fetch + merge │ fetch + merge │
│ │ │ resolve + push │
├───────────────────┼───────────────┼────────────────┤
│ │ │ │
│ 个人功能分支 │ ③ 删分支重建 │ ④ 持续同步主线 │
│ (feature/kaifa) │ branch -D │ fetch + merge │
│ │ switch -c │ resolve + push │
│ │ │ ★ 最推荐 │
└───────────────────┴───────────────┴────────────────┘
十一、总结
Git 冲突合并问题的本质不在命令,而在"分支角色 + 是否保留改动"。
先判断你在哪个分支、改动要不要保留,再决定 restore / stash / commit / merge / 重建,才是工程级正确做法。