无论是 rebase 还是 merge,在执行 pull 时都不会“自动抹掉”你的本地工作成果 —— 在这两种情况下,你的提交记录都会保留在仓库中(要么在分支历史中,要么在 reflog 存活期间以旧的 SHA 形式存在)。
pull.rebase false(merge):git pull会生成一个 merge commit,你的提交和远程提交 不会被覆盖或重写,分支历史只是简单地 合并 到一起。从视觉上看,“更安全”:你清晰地看到两条分支交汇的路径。pull.rebase true(rebase):你的本地提交会被 复制覆盖 在远程提交之上(生成新的 SHA 值)。提交内容通常保持一致,但在成功 rebase 后,旧的提交可能仅保留在git reflog中 —— 这是正常的,如果操作出错,你可以从 reflog 中 恢复(例如使用git reset --hard回到某个 ref)。
如果你最关心的是“不丢失工作成果”:
- 在执行高风险操作前 —— 先提交(或使用
git stash)并可选创建一个独立的备份分支(如git branch backup-tgisn-46),这是廉价且安全的备份。 - 不要混淆“丢失工作成果”与这些命令,比如
git reset --hard、无必要时的 force push、git clean -fd。 - 在 rebase/merge 后的几天内,避免执行激进的
git gc—— 因为reflog会保留恢复路径。
对于“不丢失工作成果,同时不严重复杂化历史”的场景,建议设置:git config pull.rebase false —— 当出现冲突时,你总会得到一个 merge,不会重写本地提交。如果你已经习惯 rebase(如过去使用 pull --rebase)—— 可以保留 pull.rebase true,但切勿在没有协商的情况下对公共分支执行 push --force。
总结: 选择 pull 策略本身不会导致工作成果丢失;真正的风险来自其他命令和force push;为安心起见,在执行不确定操作前先提交 + 创建备份分支。
以下是与你遇到的相同场景:一个共同提交 C,在 origin 上有五个提交 r1…r5,在本地只有一个提交 L(你的工作成果)。
1. pull 之前(分支已发散)
gitGraph
commit id: "C (共同)"
branch local
checkout local
commit id: "L (我的提交)"
checkout main
commit id: "r1"
commit id: "r2"
commit id: "r3"
commit id: "r4"
commit id: "r5"
含义:本地分支的末端是 L,主分支末端是 r5,共同祖先为 C。无论哪种方式,你的工作成果都不会丢失 —— 只是合并历史的方式不同。
2. 执行 git pull 且不启用 rebase(pull.rebase false → merge)
gitGraph
commit id: "C"
branch local
checkout local
commit id: "L"
checkout main
commit id: "r1"
commit id: "r2"
commit id: "r3"
commit id: "r4"
commit id: "r5"
checkout local
merge main
commit id: "M (merge commit)"
生成一个 merge commit M,它有两个父提交(L 和 r5)。提交 L 和 r1…r5 作为对象依然存在;历史是分支状,没有重写。
3. 执行 git pull 且启用 rebase(pull.rebase true → rebase)
gitGraph
commit id: "C"
commit id: "r1"
commit id: "r2"
commit id: "r3"
commit id: "r4"
commit id: "r5"
commit id: "L′ (相同补丁,新 hash)"
历史变为线性:你的工作成果位于远程提交之上。L 的历史中出现了一个新的提交 L′(相对于 r5 的补丁相同,但 hash 不同);旧的 L 会暂时保留在 git reflog 中,直到你手动清理 reflog expire。
简而言之: merge 是 分叉 + merge 节点;rebase 是 一条直线,你的提交“覆盖”在远程之上。在两种正常场景下,文件变更内容都不会丢失;区别仅在于历史形态和rebase 后本地提交的 hash。