短松江月

Git 分支分叉的解决方案简介

· simons ·
暂无

让我用几个生活中的比喻来解释不同的分支分叉解决方案:

📚 场景设定

想象你在写一本小说:

  • 远程仓库 = 出版社的底稿
  • 你的本地 = 你手里的稿子
  • 其他作者 = 同事也在修改

现在情况是:

出版社底稿:第一章 → 第二章 → 第三章
你的稿子: 第一章 → 第二章 → 第三章 → [你新增的第四章]
出版社最新:第一章 → 第二章 → 第三章 → [同事修改的第三章结尾]

🎯 三种解决方案详解

1. Merge(合并) - “拼图游戏法”

git pull --no-rebase  # 或 git pull(默认可能是merge)

比喻

你和同事各写了一段剧情,编辑把两段剧情拼在一起,中间加个说明: “此处有两个版本,都保留了”

实际效果

第一章 → 第二章 → 第三章 → [你的第四章]
                       ↘
                        [同事的第三章结尾] → (合并提交)

特点

  • ✅ 保留所有历史,像完整的日记
  • ✅ 不会改变已有的提交
  • ❌ 会产生额外的"合并提交"
  • ❌ 历史看起来像树枝分叉

适合

  • 团队合作的大型功能
  • 需要保留完整合并记录的情况

2. Rebase(变基) - “时间旅行法”

git pull --rebase

比喻

你"穿越"到同事修改之后的时间点,重新写下你的第四章 好像你一开始就是在最新版本上写的一样

实际效果

第一章 → 第二章 → 第三章 → [同事的第三章结尾] → [你的第四章]

特点

  • ✅ 历史是干净的直线
  • ✅ 看起来像顺序发生
  • ❌ 会"重写"你的提交历史
  • ❌ 如果已经推送到远程,需要强制推送

适合

  • 个人开发的小修改
  • 想要整洁历史的情况
  • 还没推送到远程的提交

3. Fast-Forward Only(仅快进) - “严格排队法”

git pull --ff-only

比喻

编辑说:“如果你的稿子只是单纯追加,没有分叉,我就直接接上” “如果有分叉,我不做任何操作,你自己决定”

实际效果

  • 如果可以直线连接:直接合并
  • 如果有分叉:直接失败,让你手动处理

特点

  • ✅ 最安全,不会自动合并
  • ✅ 保持最简单的历史
  • ❌ 经常需要手动介入
  • ❌ 不适合频繁协作的场景

适合

  • 非常严格的项目
  • 你想要完全控制合并过程

🎮 更形象的比喻

Merge 像做三明治

面包(原始代码)
↓
你加火腿   同事加芝士
↓           ↓
-------------------(合并层)
   三明治完成!
  • 两层都在,看得见每一层
  • 中间有明确的"合并层"

Rebase 像拍续集电影

第一部电影(原始代码)
↓
导演重拍了开头(同事修改)
↓
你在新版开头后拍续集(你的修改)
  • 看起来像一气呵成
  • 观众不知道中间有过修改

Fast-Forward 像排队上车

队伍:A → B → C
你想站在C后面
↓
如果C确实是最后一个:✅ 直接排上
如果C后面已经有人:   ❌ 请重新排队

📊 对比表格

方案比喻历史形状是否改历史适合场景
Merge拼图/三明治树枝状 🌳不改团队协作、大功能
Rebase时间旅行/续集直线状 🚀个人开发、小修改
FF-Only严格排队直线或拒绝不改严格项目、谨慎合并

💡 实战建议

新手选择

# 先用这个看看情况
git pull --ff-only

# 如果失败,再用这个
git pull --no-rebase

进阶选择

# 设置默认用 rebase(很多人这样设置)
git config --global pull.rebase true

# 需要时强制用 merge
git pull --no-rebase

查看当前设置

git config pull.rebase  # 查看你的设置
# 返回 true/false 或空(使用默认)

🚨 重要警告

Rebase 的危险性(特别是已推送时):

# 如果你已经 push 到远程,然后本地 rebase
git push origin main
# 会提示你需要强制推送

# 强制推送(小心!会影响其他人)
git push --force-with-lease origin main

推荐

# 1. 先用 rebase 保持历史整洁
git pull --rebase origin main

# 2. 如果有冲突(别人也改了CSS),解决冲突
# 3. 然后推送
git push origin main

🤔 简单决策树

开始拉取代码
    ↓
问自己:我的修改重要吗?
    ↓
是 → 用 Merge(保留完整历史)
    ↓
否 → 用 Rebase(保持整洁)
    ↓
不确定? → 用 FF-Only(先看看情况)

记住:没有绝对的最好,只有最适合当前情况的。从简单开始,随着经验增长,你自然会找到自己喜欢的风格!