在大屏或电脑上体验更佳——动画和操作区域更宽敞。
输入

远程协作

Git 克隆有自己的对象库、本地分支和对服务器状态的缓存。fetch、pull、push 跨越不同边界,因此它们可能让这些部分停在不同提交上。

origin/main 是本地最近获知的远程位置,不是实时服务器视图。fetch 写本地对象和 origin/main,不移动 main 或检出文件;pull --ff-only 先 fetch,再尝试快进 main 与检出;push 则只在能快进服务器当前末端时,才更新远程 main。

本地克隆与 origin 分开保存状态

左侧本地仓库包含对象库、refs/heads/main、refs/remotes/origin/main、HEAD 和检出的 app.py。右侧 origin 有自己的对象库及权威分支 refs/heads/main。

名称保存位置表示什么
main本地当前本地分支末端
origin/main本地克隆最近获知的远程末端
origin:main远程本课对服务端 main 的显示名称

克隆后,三者最初都指基点,两边对象库都有它,app.py 为 v1。队友随后可推进服务器,不触碰本地两个引用。

图中的 ID 是确定性的 Git 格式。提交引用树,树引用 app.py 的 blob。动画把提交、树、blob 组合展示为传输包,同时报告精确 Git 对象数量。

一轮远程协作逐步演示

  1. 队友的已接受推送创建 server-fix,app.py 为 v2。服务器先保存 blob、树、提交,再把 origin:main 从基点推进。此时本地 main、origin/main、检出仍不变,尚不知道服务器领先。
  2. git fetch origin 读取服务器通告的 main 末端,对照本地对象库,复制缺少的可达对象。传输中引用不动;对象在本地保存完成后,只推进 origin/main 到 server-fix。
  3. 本地已有队友提交,但 main 和检出仍是 v1。可以先检查服务器报告的历史,再决定是否整合。
  4. git pull --ff-only 先 fetch。因为刚取过,本次下载零对象,也不改跟踪引用。随后检查 main 是否为 origin/main 的祖先;是,则把 main 快进到 server-fix,并检出 app.py=v2,不创建合并提交。
  5. 本地提交 client-ui,把 app.py 改为 v3,以 server-fix 为父,先保存新 blob、树、提交,再推进 main。origin/main 和 origin:main 都不动,本地领先已知远程一个提交。
  6. git push origin main 提议以本地末端更新远程 main。Git 客户端在发送前检查服务器通告的当前末端是否为拟议末端祖先;成立后,缺失的 client-ui 对象传到远程,保存完成再推进 origin:main。成功回执随后刷新本地 origin/main。最终三引用都在 client-ui,检出为 v3。

普通 fetch、快进 pull、push 不改变提交 ID,它们复制同一批按内容寻址的对象,再更新引用;网络不会把本地提交转换成另一个远程提交。

怎样读取三个引用

main 回答本地分支在哪里,origin/main 回答克隆最近观察到哪里,origin:main 回答服务器实际在哪里。队友可以在本地跟踪引用滞后时继续推送,fetch 更新缓存而不移动当前分支。

  • git status 的领先、落后比较使用本地存储的上游引用,需要新信息时先 fetch。
  • git branch -vv 显示本地分支及配置的上游,可确认 main 是否跟踪 origin/main。
  • git log --oneline main..origin/main 查看跟踪侧独有提交;反向范围 origin/main..main 查看本地独有提交。

push 或 ff-only pull 被拒绝后,先检查两个范围,再选择合并或变基。本课不展开恢复流程,但三个引用能说明哪段历史分叉、哪份信息可能过时。

边界情况

  • 已同步时 fetch,服务器通告对象已在本地,origin/main 也已一致,传输和引用写入均为零。
  • 本地 main 已包含 origin/main(两者相同或 main 领先)时,ff-only pull 报告已是最新:不写入,也不拒绝。
  • 本地 main 与 origin/main 各自从基点产生不同子提交,ff-only 不能整合。但 pull 的 fetch 阶段仍有效:下载对象和更新后的 origin/main 都保留,只是 main 与检出不变。
  • push 检查实际远程末端,不只看缓存 origin/main。上次 fetch 后队友若推进到本地 main 不包含的提交,push 被非快进拒绝。本模型拒绝时不产生持久远程对象写入或引用写入。
  • 已是最新的 push 没有缺失对象,也不移动远程分支;若成功回执比本地缓存更新,仍可刷新 origin/main。

常见错误

  • 认为 fetch 更新检出文件。它下载对象并更新跟踪引用,整合需 merge、rebase 或 pull。
  • 把 pull 当独立的第三种同步原语。它先获取,再执行整合策略;本课限定 ff-only,成功就移动一次分支,分叉就停止。
  • 认为 push 上传工作区或索引。只有拟议引用可达的对象进入载荷,未提交编辑不会从 main 可达。
  • 认为拒绝会删除本地提交。本地对象和分支仍在,Git 只是拒绝用不包含当前远程末端的历史替换它。

模型范围

真实 Git 会协商 pack、可能使用 delta 压缩、遵守配置的 refspec,支持多分支、多远程及 merge/rebase pull。本课固定一个分支、文件、远程和 pull --ff-only,最多显示八个不同提交。这些是可视化限制,不是 Git 限制。

命令契约见 git fetch、git pull、git push。