冲突需要作出内容判断
两名同学修改同一行后,Git 不一定能判断怎样组合才符合共同需求。冲突提示意味着需要检查内容,不代表某一人的提交已经丢失。正确解决也不只是删掉标记,而是保留双方有效改动,并验证合并后的程序仍符合要求。
本文在全新本地目录,用虚构语言列表演示普通 merge,不连接远程仓库。需要 Git 及 Bash 或 Git Bash。先确认所在位置,不要把覆盖练习文件的命令套到课程项目。真实仓库应先检查工作区并遵守审核约定。
建立隔离仓库与共同起点
在终端依次执行 work=$(mktemp -d) && cd "$work" && git init -b main;随后执行 git config user.name "Practice Student" 和 git config user.email "[email protected]"。这里的身份仅用于本仓库虚构提交,不改动全局配置,也不需要真实姓名或邮箱。
再执行 printf 'zh\n' > languages.txt;git add languages.txt;git commit -m "Start language list"。文件的唯一一行是 zh。这份共同起点以后用于判断双方究竟改了什么。用 git status 确认工作区干净;如果前一步失败,应先处理原因,不要继续假定提交已经存在。
让两个分支修改同一行
先执行 git switch -c teammate;printf 'zh,en\n' > languages.txt;git add languages.txt;git commit -m "Add English"。接着执行 git switch main;printf 'zh,fr\n' > languages.txt;git add languages.txt;git commit -m "Add French"。这些命令按顺序单独运行,两个分支现在都有各自的新提交。
两项需求分别是增加英语、增加法语,特意放在同一行以触发冲突。运行 git log --oneline --graph --all 可看到两条路径共享起点。只在同一分支连续修改,不会复现这里的分叉合并。
触发冲突后,先读状态与三方内容
仍在 main 上执行 git merge teammate。预期会报告 languages.txt 的内容冲突,并暂停合并;这一步返回非零状态是练习的预期结果。运行 git status 查看未合并路径,再打开文件。常见标记是 <<<<<<< HEAD、======= 和 >>>>>>> teammate,中间分别显示当前分支与待合并分支的相关内容。
本例中,HEAD 一侧是 zh,fr,另一侧是 zh,en。可分别运行 git show :1:languages.txt、git show :2:languages.txt、git show :3:languages.txt,查看共同起点、当前分支版本、对方分支版本。这里的方向针对本次普通 merge;不要把“ours”永远理解成自己的某段代码,也不要不看内容就接受整份某一侧版本。
按需求整合,再检查实际差异
现在两种新增语言都要保留,因此把文件完整内容改为一行 zh,en,fr,并保留末尾换行。仅限这份练习文件,可以执行 printf 'zh,en,fr\n' > languages.txt。确认三个冲突标记都已删除,而且中文、英语、法语各出现一次;顺序也是明确作出的决定。
随后运行 git diff --check 检查补丁中的空白问题及残留冲突标记,再运行 git diff 查看改动。这个检查不会证明语言列表符合业务要求,也不能代替项目测试。真实代码里,即使 Git 自动合并成功,两个修改的逻辑仍可能互相抵触,所以无冲突并不等于行为正确。
暂存表示已处理,提交之前再复核
确认内容后执行 git add languages.txt,再执行 git diff --cached 和 git status。对本例而言,相对 main,暂存内容应把 zh,fr 改成 zh,en,fr;status 应说明冲突已处理、仍处于合并过程中。git add 是把处理结果交给 Git,不是让 Git 替你决定结果正确。
最后执行 git commit -m "Merge language additions"。用 git show HEAD:languages.txt 核对输出,用 git status 检查工作区干净,再用 git log --oneline --graph --all 查看合并历史。预期最后文件含三种语言,而且双方原来的提交仍在历史中。没有必要通过重写远程历史来完成这个练习。
需要退出时,理解撤销的边界
如果还在冲突阶段且决定暂不继续,可使用 git merge --abort 尝试恢复合并前状态。官方文档提醒,合并前已有未提交改动时,恢复可能不完整。因此真实工作中应先以团队允许的方式妥善保存现有改动,确认工作区状态,再开始合并。不要把 abort 当成任何情况下都能找回文件的保险。
本例先提交修改再 merge,恢复边界较清楚。合并提交完成后,便不再处于“中止合并”阶段。此时先检查历史、明确要保留哪些内容,不要随手强制重置、清理文件或覆盖同学分支。
自练:双方的需求并不总能取并集
换一个新练习仓库:共同起点是 timeout=10,两个分支分别改成 timeout=20 与 timeout=30。问最终内容能否简单同时保留两行?自查答案是不能未经确认这样做,因为配置解析可能只采用其中一行,或把重复键当成错误。需要依据需求和测试确定一个值,必要时与负责者确认。
迁移方法是找共同起点,说明每侧修改意图,确定最终行为,整合内容,检查差异,测试后提交。小组课程还应记录分工和评审;版本历史有助于说明协作过程,但不能替代课程对独立贡献、引用和协作范围的要求。
参考资料
下一步
讨论版本冲突时,请先提供匿名化的最小例子、分支关系和双方修改目的,避免分享私人仓库凭据或他人的未公开代码。
