介绍
Riverlight Garden 需要一份准确的游客指南。已为你准备好的本地提交调整了入口位置,并更新了游客服务台电话。队友已经发布了一条新的无障碍通行路线。游客需要这三项更正全部到位。
你将获取队友的工作,合并彼此独立的更改,再发布结果。一个新的接收克隆会让你查看实际交付的文件。共享仓库和两个副本都是同一台教学机器上的本地目录;这是使用真实 Git 进行的协作,不需要托管服务、搭建服务器或账号。
你应已了解提交、分支、git add、git commit 和基本差异。本实验会解释远程仓库名称、获取、合并、推送和克隆。35 分钟是作者估计的时长,包括阅读和处理普通错误的时间。
发现队友的更新
本步骤中,你将查明准备好的本地更新为何暂时无法交付,然后获取队友的版本,同时保持自己的文件不变。
打开 Terminal。首先进入准备好的编辑仓库:
cd /home/labex/project/guide-team/editor
cd 会改变当前终端的工作目录。如果路径拼错,可使用 pwd 打印当前目录、使用 ls 列出目录内容,再重新执行上面的完整 cd 命令。此类普通的目录切换错误不需要新建 VM。
新的合并提交需要作者身份。--local 仅在当前仓库中保存这些设置。引号内的文本即使包含空格,也会作为一个完整的值;示例邮箱是合成数据。你也可以自行选择姓名和邮箱。
git config --local user.name "Guide Editor"
git config --local user.email "guide@example.com"
现有的本地提交已经完成。读取其中的游客信息:
cat guide.txt
cat contacts.txt
你应看到 South entrance 和游客服务台电话 010-555-0120。保留指南中说明最晚入园时间的句子。单独的路线文件仍写着 Use the north ramp:
cat access.txt
git status --short 以简洁格式列出已更改文件。这里没有输出,表示准备好的贡献已经提交,工作区是干净的:
git status --short
远程仓库是一个具名的、连接到另一仓库的配置。origin 是这个连接的名称,并不是某种特殊服务器。-v 显示它用于获取和推送的地址:
git remote -v
两个地址都指向 /home/labex/project/guide-team/shared.git。这是一个裸仓库:它保存共享历史,但没有可编辑的工作副本。不要编辑它的内部文件。
尝试交付你的分支。push 发送提交;main 指定要在 origin 上更新的分支。预期第一次推送会失败,并返回非零退出状态。 单独运行这条命令,被拒绝后继续:
git push origin main
留意 [rejected]、main -> main 和 (fetch first)。共享分支包含当前本地历史中没有的工作,因此 Git 拒绝替换它。这属于非快进更新:现有共享分支的末端提交不是拟推送末端提交的祖先。强制推送会从分支中丢弃队友的贡献,违反本任务要求。
fetch 下载远程提交,并更新本地的远程跟踪指针 origin/main。它不会将这些提交合并到你自己的 main,也不会改写工作文件:
git fetch origin
对比两边历史。--oneline 为每个提交显示一行简短信息;--graph 绘制父提交连接;--all 同时包含本地分支和远程跟踪分支;--decorate 添加这些分支的标签。--no-pager 直接打印输出;如果你在尝试时打开了分页查看器,请按 q 退出。
git --no-pager log --oneline --graph --all --decorate
找到 Move the gate and update the visitor desk(位于 HEAD -> main)和 Update the step-free route(位于 origin/main)。两者都源自 Open the garden guide。HEAD 表示当前检出的提交。两项贡献各不相同,不能相互替代。
直接从队友的快照读取路线。show 接受 revision:path 表达式,因此 origin/main:access.txt 表示已获取版本中的这个文件:
git --no-pager show origin/main:access.txt
其中写着 Use the riverside ramp。你的工作区路线仍写着 Use the north ramp。这个差异说明,获取操作让新历史变得可用,同时保持工作区不变。第一个检查点要求已获取该版本,且原来的本地提交仍完整保留。
合并彼此独立的贡献
本步骤中,你将把两边历史合并为一个版本,其中包含南入口、更新后的游客电话和河畔坡道。
留在 Terminal 中,目录为 /home/labex/project/guide-team/editor。合并会组合历史。由于这些更改涉及不同文件,Git 可以自动合并它们的文本。--no-edit 接受 Git 生成的合并信息,避免打开编辑器:
git merge --no-edit origin/main
预期会看到合并成功的摘要,通常为 Merge made by the 'ort' strategy.。Git 会创建一个有两个父提交的合并提交:父提交分别是你原来的提交和队友原来的提交。两项贡献都不会被改写。
读取实际合并后的文件:
cat guide.txt
cat access.txt
cat contacts.txt
指南必须保留 South entrance、09:00-17:00 和最晚入园时间的句子;路线必须为 Use the riverside ramp;电话必须仍为 010-555-0120。独立更改顺利合并了,但你仍需判断其内容含义。
查看生成的历史:
git --no-pager log --oneline --graph --all --decorate
HEAD -> main 处的合并连接了两条贡献历史线。推送之前,origin/main 仍标在之前获取的队友提交上。这是正常的:合并改变的是本地 main,而不是共享的 main。
检查工作区状态:
git status --short
预期没有输出。如果其他尝试留下了进行中的合并,git merge --abort 可以取消该次未完成合并并恢复到合并前的状态;仅在合并进行中运行它,然后重新执行合并命令。它不能取消已经完成的提交。检查点要求存在一个合并后的提交,其两个父提交是原来的两个提交,且三个文件的内容均完整。
发布并接收完整指南
本步骤中,你将把合并后的版本交付到共享仓库,再从一个新的接收副本中读取它。仅在本地合并,还没有向其他副本交付任何内容。
留在 Terminal 中,目录为 /home/labex/project/guide-team/editor。push origin main 将本地 main 的历史发送到名为 origin 的仓库。这一次,共享贡献是合并提交的祖先,因此推送能够推进共享 main,而不移除该贡献。
git push origin main
预期会看到 main -> main,且没有拒绝信息。如果被拒绝,请再次获取并检查历史图;不要添加强制选项。准备好的场景中没有后台贡献者,但真实团队可能随时发布新工作。
现在切换到包含这两个仓库的目录:
cd /home/labex/project/guide-team
git clone 根据来源创建一个新仓库和工作文件。这里,shared.git 是现有的本地来源路径,received-guide 是新的目标目录。接收副本必须以共享仓库为来源,这样才能显示合并结果是否真正交付。
git clone shared.git received-guide
预期会看到 Cloning into 'received-guide'... 和 done.。如果你在尝试时已经克隆过,请保留该副本:进入 received-guide,使用之前学过的 git fetch origin,再执行 git merge --no-edit origin/main 来更新它。不要为了重新尝试克隆而删除原来的编辑仓库。
进入接收副本:
cd received-guide
读取每个实际文件。cat 会打印文件,而不改变它:
cat guide.txt
cat access.txt
cat contacts.txt
将这些信息与上一步中合并后的业务要求对照。三个文件的内容都必须完整,包括未更改的行。仅凭克隆成功信息,无法证明内容正确。
最后,读取接收副本的历史。--oneline 简化每条提交的显示,--graph 绘制父提交连接,--decorate 标记分支指针。--no-pager 直接打印,而不打开可滚动的查看器。
git --no-pager log --oneline --graph --decorate
顶端的合并具有两条祖先历史线,包含原来两项贡献的信息和最初的提交。你的具体提交 ID 会有所不同。检查内容是否完整保留,以及接收副本是否位于 main,其已跟踪工作区文件是否干净:
git status --short
没有输出表示不存在已暂存、未暂存或未跟踪的更改。你已通过真实的 Git 仓库交付一组可用文件,所有仓库都运行在这一台教学机器上。
总结
你处理了一次真实的推送拒绝,在不覆盖自己文件的情况下获取了队友的提交,合并了两项独立贡献,并通过共享仓库交付了完整指南。一个真实的接收克隆包含了合并后的指南、无障碍通行路线和游客联系方式。
原始提交仍保留在历史中。接下来,练习当两个人修改同一行、Git 需要你作出判断时如何合并。



