第 02 章

远程仓库日常

clone、pull、fetch——把别人的代码拉下来,把远程更新同步回来

换台电脑也能接着干,团队改了你也能跟上

代码不在手上

你想动手,却发现代码不在当前这台机器上

要用别人的项目

你看到 GitHub 上一个不错的小工具,想跑起来看看。下载 zip 吗?那样拿不到 Git 历史,也没法后续更新。

换电脑继续干

你昨天在宿舍 push 了代码,今天想在机房接着写。机房是空目录,怎么把代码弄过来?

队友改了东西

队友往 GitHub 推了新功能,你本地的还是旧的。怎么把他的改动同步到你的电脑?

本章解决三件事:把远程仓库整个搬下来(clone)、把远程的新提交同步回本地(pull / fetch)、看清远程发生了什么(网页历史)。
这是你日后每天都会用的高频操作。

开始之前

适合谁

  • 已经完成第 01 章,会做首次 push
  • 想拉取别人的开源项目到本地
  • 需要在多台电脑之间同步自己的项目

你将学会

  • 用 git clone 把远程仓库复制到本地
  • 区分 pull 和 fetch,知道何时用哪个
  • 管理多个 remote(origin、upstream)
  • 在 GitHub 网页上看懂提交历史和 blame

本章暂不覆盖

  • 解决合并冲突(第 03 章)
  • fork 与开源贡献(第 06 章)
  • 分支策略(第 05 章)

克隆仓库

把一个完整的远程仓库复制到本地,含全部历史

# 克隆别人的公开仓库
$ git clone https://github.com/用户名/仓库名.git

# 克隆到指定文件夹名
$ git clone https://github.com/用户名/仓库名.git 我的文件夹

clone 做了什么

  • 下载远程仓库所有文件
  • 下载全部提交历史
  • 自动设置 origin 指向源地址
  • 自动检出默认分支(通常是 main)
clone ≠ 下载 zip。zip 只给文件快照,clone 给你完整 Git 能力——能看历史、能切换版本、能拉取后续更新。只要你想「动这个项目的代码」,就用 clone。

试一下克隆

拿一个真实开源项目练手

$ git clone https://github.com/octocat/Hello-World.git
Cloning into 'Hello-World'...
remote: Enumerating objects: 11, done.
remote: Total 11 (delta 0), reused 0 (delta 0), pack-reused 11
Receiving objects: 100% (11/11), done.

$ cd Hello-World
$ git log --oneline
octocat/Hello-World 是 GitHub 官方的演示仓库,文件少、历史简单,适合第一次 clone 练手。克隆后进目录跑 git log,你会看到这个项目的全部提交记录。

之后想删除,直接删文件夹即可——clone 出来的就是普通文件夹,没有特殊状态。

同步远程更新

远程有了新提交,怎么弄到本地?两个命令

图:fetch 与 pull 的区别

fetch 只下载

把远程的新提交取回本地,但不动你的工作区

$ git fetch origin
remote: Enumerating objects: 5, done.
...
From https://github.com/用户名/仓库名
 * [new branch]      feature   -> origin/feature
   3a2f1c4..8b9d021  main      -> origin/main

fetch 之后

  • 远程的新提交存在 origin/main 这种「远程跟踪分支」
  • 你的 main 工作区完全没变
  • 可以用 git log origin/main 先看看远程发生了什么
fetch 是「只看不碰」。适合不确定远程改动是否安全时——先 fetch 下来看一眼,再决定要不要合并。这是最安全的同步方式。

pull 一步到位

fetch + merge,把远程更新直接合并进当前分支

$ git pull
Updating 3a2f1c4..8b9d021
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)

pull = fetch + merge

先下载远程更新,再自动合并到你当前所在的分支。日常最常用。

何时用 pull

  • 确定要同步远程改动
  • 本地没有未提交的工作
  • 和队友协作时的日常更新
pull 可能产生冲突。如果你本地和远程改了同一个文件,pull 会触发合并冲突。先 git status 看状态,按第 03 章的方法处理。

到底用哪个

看场景选命令,没有绝对的对错

场景推荐理由
日常同步自己项目 git pull 一步到位,省事
多人项目,不确定改了啥 git fetch 先看再合,更稳妥
本地有未提交的改动 先 commit/stash,再 pull 避免 pull 把工作搞乱
只想看远程有没有更新 git fetch 不影响本地任何东西
新手记住一句话:不确定就先 git fetch,看完状态再决定合不合并。等你熟练了,git pull 就是肌肉记忆。

管理远程地址

一个本地仓库可以关联多个远程

# 查看当前关联了哪些远程
$ git remote -v
origin  https://github.com/你/仓库名.git (fetch)
origin  https://github.com/你/仓库名.git (push)

# 添加一个新的远程(比如上游原始仓库)
$ git remote add upstream https://github.com/原作者/仓库名.git

# 删除一个远程
$ git remote remove upstream

# 改名
$ git remote rename origin myfork
为什么要有多个远程?最常见的场景是 fork:你的副本叫 origin,原作者的仓库叫 upstream。从 upstream 拉最新改动,推送到自己的 origin。第 06 章开源贡献会详细讲。

网页看历史

不敲命令也能读懂一个项目——GitHub 网页自带可视化

Commits 列表

仓库首页文件列表上方有个 N commits 链接,点进去看到所有提交,按时间倒序排列。每条显示作者、时间、消息。

单次 commit 详情

点任意一条 commit,能看到这次具体改了哪些行——绿色是新增,红色是删除。比 git show 直观。

按作者筛选

commits 页面右上角能选作者,看某个人都提交了什么。团队项目里追踪贡献很方便。

Network 图

看分支和合并的可视化全景

怎么打开

仓库页面 → Insights 标签 → 左侧 Network。

能看到什么

  • 每个分支是一条横线,commit 是线上的点
  • 分支分叉和合并一目了然
  • 还包括全网的 fork(谁从你这分出去开发了什么)
Network 是理解 Git 分支模型的最佳工具。当你被 merge、rebase 绕晕时,去看 Network 图——它把抽象的分支关系画成了直观的线条。第 03 章讲 PR 时我们会反复用到它。

Blame 追溯

每一行代码,是谁、在哪个 commit、为什么加的

怎么打开

打开任意文件 → 右上角 Blame 按钮。

能看到什么

  • 每一行左侧标注最后修改它的 commit
  • 显示作者头像、时间、commit 消息
  • 点 commit 能跳到完整改动详情
「这行 bug 是谁写的?」——别急着甩锅,先用 blame 查清楚。
经常你会发现,那行代码有它的历史原因。blame 不是为了追责,是为了理解上下文。

该忽略什么

.gitignore 文件告诉 Git 哪些文件不要追踪

# 通用:操作系统产生的垃圾文件
.DS_Store
Thumbs.db

# Python
__pycache__/
*.pyc
.venv/
.env

# Node
node_modules/
dist/

# IDE 配置
.vscode/
.idea/
为什么重要:把 node_modules/ 或 .env(含密码!)推上 GitHub 是经典事故。.gitignore 在第一次 commit 之前就配好,能避免绝大多数麻烦。

别从零写

github/gitignore 仓库有现成模板,直接抄

在哪找

  • 访问 github.com/github/gitignore,按语言找对应模板
  • 或建仓库时在 .gitignore 下拉框选语言,GitHub 自动生成
  • 网站 gitignore.io 输入技术栈一键生成

已被追踪的文件怎么办

如果文件已经被 commit 过,加进 .gitignore 不会自动移除。需要:

$ git rm --cached 文件名
$ git commit -m "停止追踪该文件"

--cached 表示只从仓库移除,本地文件保留。

README 是门面

别人点进你仓库第一眼看到的就是 README

一个好 README 该有

  • 项目名 + 一句话简介:它是干什么的
  • 安装步骤:怎么跑起来
  • 使用示例:最少一段可运行代码
  • License:能不能用、怎么用(可选)

常见坏习惯

  • README 只有项目名一行字
  • 写了一大段但没说怎么运行
  • 把内部笔记当 README

把 README 当成「给陌生人看的说明书」来写。

README 用 Markdown 写,GitHub 会自动渲染。标题用 #,代码块用三反引号,图片直接拖进编辑器就能上传。第 08 章 GitHub Pages 会教你把 README 做成完整网站。

临时藏起来

git stash——还没写完的改动,先存一边,回头再取

# 写到一半,要先 pull 最新代码
$ git stash        # 把当前改动藏进「抽屉」
Saved working directory and index state WIP on main: ...

$ git pull         # 现在能干净地拉取了

$ git stash pop    # 把刚才藏的改动取回来
On branch main
Your changes are back

什么时候用

  • 改到一半要切分支处理紧急问题
  • pull 前本地有未提交改动,怕冲突
  • 想试试另一条思路,又不想丢当前进度

进阶

  • git stash list:看藏了几份
  • git stash drop:丢掉最新一份
  • 可藏多份,按栈顺序 pop
stash 不是 commit。它把改动暂存到一个临时区域,工作区变干净。取回(pop)后改动回到原处。适合「一会儿就回来接着干」的短时暂存——别用它当长期备份。

排错:pull 冲突

报 Your local changes would be overwritten by merge

原因

你本地有未提交的改动,且和远程改了同一区域。Git 怕覆盖你的工作,拒绝合并。

三种处理

# 1. 先提交本地改动
$ git add . && git commit -m "wip"
$ git pull

# 2. 暂存改动再 pull
$ git stash
$ git pull
$ git stash pop

# 3. 丢弃本地改动(慎用!)
$ git restore .
$ git pull
养成习惯:拉取更新前先 git status 看本地是否干净。有未提交改动就先 commit 或 stash,这是避免 90% 同步事故的简单规则。

动手试一试

完整走一遍 clone → 改 → pull 流程

你的任务

任务:克隆自己的远程仓库到新文件夹,做一处改动推送回去,再从另一处模拟更新拉取。

要求:

  1. 把自己第 01 章建的仓库 clone 到一个新文件夹
  2. 修改 README,commit 并 push
  3. 回到原来的文件夹,git fetch 查看,再 git pull 同步
  4. 确认两边的代码一致

提示

  1. clone 会在当前目录新建文件夹,不用手动建
  2. fetch 后用 git log HEAD..origin/main 能看远程多了哪些提交
第 02 章

小结

你已经能在多台机器之间自如地同步代码了

本章要点

  • clone 把完整仓库(含历史)搬到本地
  • fetch 只下载不合并,pull = fetch + merge
  • 一个本地仓库可关联多个 remote(origin / upstream)
  • 网页工具:commits 列表、Network 图、Blame 追溯
  • .gitignore 要在首次 commit 前配好
下一步:第 03 章 Pull Request 全流程 —— 学会 GitHub 上最核心的协作载体,从开分支到合并进主干的完整链路。