git pull 和 git fetch 有啥区别?
我见过很多 Git 事故,开头都差不多:
“我就随手 pull 了一下……”然后分支就开始长出一堆莫名其妙的 merge commit,或者你本地改到一半突然冲突,心态当场下线。
其实
git pull和git fetch的区别很简单:一个只更新“情报”,一个更新“情报 + 现场”。
先一句话结论(TL;DR)
git fetch:把远端的新提交拉到本地,但不动你当前分支(不合并、不改工作区)。git pull:等价于git fetch+ 把远端分支的更新合到你当前分支(默认 merge,也可以 rebase)。
所以我通常这样记:
- fetch = “我先看看远端发生了啥”
- pull = “我直接把远端的变化拿过来并处理掉”
先讲清楚一个重要概念:远端跟踪分支
你执行 git fetch origin 以后,Git 会更新这些东西:
origin/mainorigin/masterorigin/feature-xxx
注意:origin/main 这种叫 远端跟踪分支(remote-tracking branch),它只是 Git 在你本地保存的一份“远端快照”,用来告诉你:
“远端 main 现在走到哪了。”
它不是你正在工作的 main,也不是你本地的 feature 分支。它更像一个“情报板”。
git fetch:只拉更新,不改你的分支
最常用的姿势:
1 | git fetch origin |
它会做两件事:
- 去远端拿最新的对象(提交、树、tag 等)
- 更新本地的远端跟踪分支(比如
origin/main指向新的提交)
但它不会做:
- 不会自动把
origin/main合到你的main - 不会动你当前工作区的文件
- 不会帮你解决冲突(因为它根本没合并)
fetch 后你一般会干啥?
常见三件事:
1) 看看远端比我多了啥
1 | git fetch origin |
2) 对比差异
1 | git fetch origin |
3) 决定怎么更新本地 main
- 你想“合并”:
git merge origin/main - 你想“变基”:
git rebase origin/main
git pull:拉回来,并且立刻合进当前分支
最常见的姿势:
1 | git pull |
它默认干的事(在大多数配置下)是:
git fetch(把远端更新拉到本地,更新origin/xxx)git merge(把origin/当前分支合到当前分支)
所以可以粗暴理解为:
1 | git pull = git fetch + git merge |
但注意:pull 的“第二步怎么合”是可配置的。
pull 的两种常见模式
1) merge 模式(默认)
1 | git pull |
如果你本地也有提交、远端也有提交,就会出现一个 merge commit。你会在历史里看到:
“Merge branch ‘main’ of origin”
它不是错,但很多团队不喜欢“历史长得像麻花”。
2) rebase 模式(更常见的团队偏好)
1 | git pull --rebase |
它的效果更像:
- 先把你本地的提交“临时摘下来”
- 把远端更新放到前面
- 再把你本地提交一个个接回去
这样历史更线性,看起来更舒服。
一张图把它们的差别说清楚
假设现在是这种情况:
- 你本地
main在 A - 远端
origin/main在 B(比你多了几个提交)
1 | 你本地 main: A |
你执行 fetch
git fetch origin 之后:
origin/main更新到 B- 你本地
main还在 A
1 | main: A |
你执行 pull
git pull 之后:
origin/main更新到 B- 并且把 B 合到了
main(merge 或 rebase)
1 | main: B |
fetch 是“更新情报”,pull 是“更新情报并让你立刻跟上”。
什么时候用 fetch?什么时候用 pull?
我建议你优先用 fetch 的场景
- 你本地有改动(尤其是改到一半),不想被 pull 强行打断
- 你想先看看远端改了啥,再决定怎么合(merge 还是 rebase)
- 你在排查问题:想对比某次提交、想做 bisect、想确认远端到底有没有更新
一句话:不确定要不要合的时候,先 fetch。
pull 更适合的场景
- 你当前分支就是干净的(没改动,或已提交)
- 你就是想同步一下,不想多想
- 团队已经约定好了 pull 的策略(比如统一
--rebase)
一句话:确定要把远端变化合进来时,用 pull。
两个实用建议(能少很多冲突)
1) 把 pull 变得更“可控”
如果你们团队希望历史线性,我会建议大家养成:
1 | git pull --rebase |
再狠一点:只允许快进合并(不产生 merge commit):
1 | git pull --ff-only |
--ff-only 的效果是:能快进就快进,不能快进就直接失败,让你自己决定怎么处理(而不是悄悄给你造一个 merge commit)。
2) 你改到一半想同步?先 stash 或开新分支
改到一半硬 pull,冲突概率会飙升。更稳的顺序是:
1 | git stash -u |
当然,这里不是说 stash 是银弹,只是它能让你从“工作区一团乱麻”回到“先把同步处理干净”的状态。
最后总结
git fetch:只更新远端跟踪分支,安全,适合先观察再决策git pull:更新并合入当前分支,省事,但更容易把你拉进冲突现场
你要是只记一句就行:pull 会动你的分支,fetch 不会。
Happy Coding!
