元数据卡: 前置知识:ch03-git-branch.md | 预计时间:10 分钟 | 完成标志:能独立解决一个合并冲突
第四场战斗:两个人改了同一行
前面几次合并都挺顺利的——你只是往主干上叠加新的零件图,跟已有的方案不冲突。但这次不一样了。
你在自己的工位上改了一个零件的尺寸,隔壁工位的同事也在他的工位上改了同一个零件的尺寸。你俩的改动方向完全相反。
"合到一起试试?"你的同事说。
你把两份图纸放上操作台,运行了比对。操作台沉默了一秒——然后弹出了一行红色的标记:
冲突
"什么叫冲突?"你有点慌了。
你和同事修改了同一张图纸上的同一处尺寸。你说"这个接口要用圆形",他说"要改成方形"。你们各自把版本登记进了工坊日志。现在你要把两个设计合到一起——操作台困惑了:"你俩到底谁对?"
这就是合并冲突。
制造一个冲突
空说无凭,我们来亲手制造一个冲突:
# 从 master 创建 feature-a 分支
git switch -c feature-a
echo "a" > main.py
git add main.py && git commit -m "feature-a: change to a"
# 回到 master,创建 feature-b 分支
git switch master
git switch -c feature-b
echo "b" > main.py
git add main.py && git commit -m "feature-b: change to b"现在回到 master,先合并 feature-a,再合并 feature-b:
git switch master
git merge feature-a
git merge feature-b语言: Bash 如何运行: 按顺序粘贴到终端 预期输出(第二条 merge 命令):
Auto-merging main.py
CONFLICT (content): Merge conflict in main.py
Automatic merge failed; fix conflicts and then commit the result.看到 CONFLICT 了吗?Git 很诚实地说:"我没法替你做决定。"
看看冲突长什么样
打开 main.py,你会看到 Git 留下的标记:
<<<<<<< HEAD
b
=======
a
>>>>>>> feature-b这是 Git 在说:
<<<<<<< HEAD和=======之间:当前分支(master)的版本——内容是b=======和>>>>>>> feature-b之间:要合并进来的分支的版本——内容是a
现在你需要做三件事:
- 删掉所有 Git 标记:
<<<<<<<、=======、>>>>>>> - 改成你想要的内容(保留一个、保留两个、或者重写)
- 保存文件,然后
git add+git commit
# 假设我决定两边都要
echo -e "a\nb" > main.py
git add main.py
git commit -m "resolve merge conflict: keep both a and b"语言: Bash 预期输出:
[master d7e8f9g] resolve merge conflict: keep both a and b冲突解决完成。
核心原则: Git 不会替你解决语义上的冲突("a 还是 b 对?"),它只解决文本上的冲突("这行有两个版本")。合并冲突不是 bug——它是 Git 诚实地说"我搞不定了,你来决定"。
试试看: 按上面的步骤亲手造一次冲突,然后打开 main.py 看看 <<<<<<< 标记长什么样。把它改成你想要的版本,add + commit 完成解决。
放弃合并
合并到一半,你觉得不对劲——改动太大,不想合了?Git 允许你放弃:
# 放弃当前正在进行的合并,回到合并前的状态
git merge --abort试试看: 在 git merge 出现冲突后,运行 git merge --abort,确认文件回到了合并前的样子。
冲突不是灾难
很多新手第一次看到 CONFLICT 就慌了,觉得"代码坏了""做错了什么"。但恰恰相反:
- 冲突 = Git 如实告诉你它没法自动合并
- 没有冲突 = Git 自动做了决定,你可能没发现它合错了
冲突是 Git 诚实谦逊的表现。 它知道自己不擅长替你做决定,所以把最困难的部分——语义判断——留给了你。
用图形工具解决冲突
如果你觉得在文本编辑器里手动找 <<<<<<< 标记太麻烦(特别是冲突文件很大时),Git 支持可视化合并工具:
# 启动配置的合并工具(如 vimdiff、meld、kdiff3)
git mergetoolVSCode 内置了合并冲突编辑器,打开冲突文件会看到三个面板:
- 当前分支(左边)
- 要合并的分支(右边)
- 合并结果(中间)
你只需要点击"采纳当前""采纳传入"或"同时保留"按钮。这让解决冲突直观得多。
下一步
你在自己的工坊里用 Git 越来越顺手了。但你终究会遇到一个需求——把代码分享给别人。或者从别人那里拉代码。
下一节,我们连接 远程仓库——把你的工坊和世界的工坊连通。