合并分支与解决冲突


你的功能分支已经完成了。切换开关能正常工作,你也把改动提交了,现在你希望这份工作能进入团队其他人代码所在的 main 分支。多数时候,把它并进去是又快又安静的一件事:Git 会比较两个分支,发现两边没有重叠的改动,就直接把工作合进去,不需要你额外做什么。但有时候,你和同事在不同分支上改动了完全相同的那几行代码,这时候 Git 无法猜出你想保留哪个版本。这种情况在任何有多人一起提交代码的项目里几乎都会遇到。这是分支协作中很正常、很日常的一部分,它的意思是 Git 发现了两种关于同一批代码的不同想法,需要你来拍板决定留哪个。
用 git merge 把分支并回来
假设你在自己的分支 add-fahrenheit-toggle 上开发了华氏度切换功能,而 main 从你分出这个分支之后就没有再变动过。切换到 main,然后用 git merge 加上你想并入的分支名:
$ git switch main
$ git merge add-fahrenheit-toggle
Updating 4f2a891..8c3d1a0
Fast-forward
src/index.js | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)git merge <branch> 总是把指定的分支合并到你当前所在的那个分支上,所以先切换到 main 很关键。你站在哪个分支上,接收合并结果的就是它。命令执行完后,main 就拥有了 add-fahrenheit-toggle 上的所有提交。功能分支本身丝毫未变:你可以继续在它上面开发,也可以把它删掉,因为它的工作现在也留在 main 上了。
git merge branch-name 会把那个分支的提交并入你当前所在的分支,所以先切换到 main。多数合并都在后台悄无声息地完成,你继续做别的事就好。功能分支本身不会有任何变化;main 拿到这份工作之后,你可以继续用它,也可以把它删掉。 合并冲突长什么样
当合并的两边都改动了相同的行时,就会发生冲突,Git 没办法判断你想保留哪个版本。假设同事把一个加载动画合并进了 main,改动了 src/index.js 里的某个函数,而你的 add-fahrenheit-toggle 分支为了加切换开关也改了同一个函数。这时合并会在中途停下,而不是直接完成:
$ git switch main
$ git merge add-fahrenheit-toggle
Auto-merging src/index.js
CONFLICT (content): Merge conflict in src/index.js
Automatic merge failed; fix conflicts and then commit the result.这就是**合并冲突(merge conflict)**。打开这个文件,你会看到 Git 已经精确标出了两个版本不一致的地方:
<<<<<<< HEAD
showLoadingSpinner(true);
=======
const tempF = celsiusToFahrenheit(tempC);
>>>>>>> add-fahrenheit-toggle<<<<<<< HEAD 标出的是当前分支(这里是 main)上的内容的起始位置。======= 把两个版本分隔开。>>>>>>> add-fahrenheit-toggle 标出的是要并入分支版本的结束位置。两个标记之间夹着的就是同一小段代码的两种不同写法。
出现冲突意味着 Git 需要你来判断,并不代表哪里坏了。Git 发现同一批代码有两处改动,没办法猜出你想要哪一个,于是就停下来,等你来做决定。编辑这个文件,直到内容变成你想要的样子——可以保留其中一个版本、两个都留,或者写一个融合两者的新版本——然后把标记那几行删掉:
showLoadingSpinner(true);
const tempF = celsiusToFahrenheit(tempC);文件内容看起来没问题之后,像处理其他改动一样把它加入暂存并提交:
$ git add src/index.js
$ git commit这里不带消息直接运行 git commit,会打开编辑器,里面已经有 Git 帮你准备好的、描述这次合并的提交信息。保存并关闭它,合并就完成了。
<<<<<<<、======= 和 >>>>>>>,编辑到你想要的样子,然后把这些标记行删掉。最后用 git add 和 git commit 收尾。我第一次遇到冲突时感觉像出了大事,结果发现它只是 Git 在问我一个挺平常的问题。 把它们串起来
合并正是让分支这件事变得值得做的原因:你在 Branches 里学到的那条属于自己的历史线上安全地做实验,等准备好了,再把这份工作并回 main,冲突也一并处理好。在 GitHub 上,同样的操作通常不是在你本机敲一句 git merge,而是通过 pull request 完成的;pull request 工作流这一章会讲到如何在共享项目中提出改动、进行审查并完成合并。如果某次合并在你已经提交之后,落到了你并不想要的地方,撤销操作会讲到如何安全地退回去。

