Git 远程仓库 — push / pull / fetch / clone

前面学的 init/add/commit/branch 都是在本地操作。但要团队协作、要备份、要参与开源,就必须有一个"远程中心"——这就是远程仓库。这一章讲怎么把本地代码推(push)上去、把同事的代码拉(pull)下来,以及 Fork 工作流。

1. 远程仓库是什么

本地 Git 是完全离线的——你的提交、分支、历史都存在自己电脑的 .git 目录里。但团队协作需要一个"中心枢纽",让所有人能同步代码。这个枢纽就是远程仓库

常见的远程托管平台:

一个本地仓库可以关联多个远程(比如同时推 GitHub 和 Gitee 做备份),但通常只用一个,约定叫 origin

2. git remote — 关联远程

本地仓库建好后,要告诉它"远程在哪":

# 关联远程仓库(GitHub/GitLab/Gitee)
# 1. 先在网站建一个空仓库,拿到地址(SSH 或 HTTPS)
# 2. 本地关联远程
git remote add origin git@github.com:you/repo.git
#         远程名 ↑     ↑ 远程地址
# "origin" 是约定俗成的默认远程名,可以自定义

# 查看已关联的远程
git remote -v
# 输出:
#   origin  git@github.com:you/repo.git (fetch)
#   origin  git@github.com:you/repo.git (push)

# 修改远程地址(换了服务器或改用 SSH)
git remote set-url origin git@github.com:you/new-repo.git

# 删除远程关联
git remote remove origin

# 一个仓库可以关联多个远程(比如同时推 GitHub 和 Gitee)
git remote add github git@github.com:you/repo.git
git remote add gitee   git@gitee.com:you/repo.git

3. git push / pull — 推送与拉取

这是日常协作最高频的两个命令。push 把本地提交上传到远程,pull 把远程更新下载并合并到本地。

# 第一次推送:-u 把本地 main 和远程 main 关联(建立追踪)
git push -u origin main
# 之后这个分支就能直接 git push / git pull,不用带参数

# 日常三件套
git fetch              # 只下载远程变化到本地,不合并(更安全)
git pull               # 拉远程更新并合并到当前分支(= fetch + merge)
git push               # 推本地提交到远程

# 推送其他分支
git push -u origin feature-login

# 删除远程分支
git push origin --delete feature-login

# 强制推送(覆盖远程历史!慎用,只在私人分支)
git push --force-with-lease   # 比 --force 安全:远程被别人改过会拒绝
git push -f                   # 暴力覆盖,不推荐

黄金法则:已 push 到共享分支的提交,绝不强制覆盖(--force)。否则同事 pull 时会遇到噩梦般的冲突——他们的提交会"消失"。如果一定要强推,务必用 --force-with-lease(远程被别人改过会自动拒绝,更安全)。

4. fetch vs pull — 关键区别

新手最容易混淆这两个命令。简单说:fetch 只下载不合并(更安全可控),pull 下载并合并(更方便但可能突然出冲突)。

# fetch 和 pull 的关键区别
#
# git fetch:只下载,不合并
#   - 把远程的新提交下载到本地的 origin/main(远程跟踪分支)
#   - 你的工作区、本地 main 都不变
#   - 适合:想先看看远程有啥变化再决定怎么合
git fetch origin
git log main..origin/main --oneline   # 看远程比我多了哪些提交
git diff main origin/main             # 看具体差异
git merge origin/main                 # 看完再决定合并

# git pull:下载 + 合并(= fetch + merge 一步到位)
#   - 直接把远程变化合并进当前分支
#   - 方便,但有冲突时会突然进入合并状态
git pull

# 推荐:用 pull --rebase 保持线性历史
git pull --rebase
# 等价于 git fetch + git rebase,避免多余的 merge 提交

推荐养成"先 fetch 看看再决定"的习惯,尤其在多人协作的分支上。pull --rebase 能避免产生无意义的 merge 提交,保持历史线性干净。

5. git clone — 克隆远程仓库

加入一个已有项目时,第一步永远是 clone——把远程仓库整个下载到本地(含全部历史)。

# 克隆:把远程仓库整个下载到本地(含全部历史)
git clone git@github.com:vuejs/vue.git
# 自动建立 origin 关联、自动 checkout 默认分支

# 克隆到指定目录名
git clone git@github.com:vuejs/vue.git my-vue

# 浅克隆:只取最近 1 次提交(大仓库省时间/流量)
git clone --depth 1 git@github.com:torvalds/linux.git

# 克隆后补全历史(浅克隆后想要完整历史)
git fetch --unshallow

# 克隆指定分支
git clone -b dev git@github.com:you/repo.git

# 只克隆最近 N 次提交
git clone --depth 50 git@github.com:you/repo.git

大仓库(如 Linux 内核、Chromium)全量克隆可能几 GB,用 --depth 1 浅克隆只取最新一次提交,省时省流量。

6. SSH vs HTTPS

远程地址有两种协议,各有优劣:

长期开发推荐 SSH(配法见上一篇"安装与配置")。临时 clone 别人的项目用 HTTPS 更省事。

7. Fork 工作流 — 参与开源

给别人的开源项目(你没有写权限)贡献代码,要用 Fork 模式:

# Fork 工作流(给开源项目贡献代码)
# 1. 在 GitHub 网页点 Fork,把别人的仓库复制一份到你账号下
# 2. 克隆你 fork 的仓库
git clone git@github.com:你/vue.git
cd vue

# 3. 添加原始仓库为 upstream(上游)
git remote add upstream git@github.com:vuejs/vue.git
git remote -v
#   origin    git@github.com:你/vue.git       (你的 fork)
#   upstream  git@github.com:vuejs/vue.git    (原仓库)

# 4. 开发前同步 upstream 的最新改动
git fetch upstream
git switch main
git merge upstream/main      # 把原仓库 main 合并到你的 main
git push origin main         # 推到你的 fork

# 5. 开 feature 分支开发,完成后 push 到 origin
git switch -c fix-typo
# ... 改代码 ...
git push -u origin fix-typo

# 6. 在 GitHub 网页发起 Pull Request:你/vue:fix-typo → vuejs/vue:main

这里出现了第二个远程 upstream(上游)——指原始仓库,用来同步原作者的最新改动。你的 origin 是自己 fork 的副本(有写权限)。这种"双远程"结构是开源协作的标准姿势。

日常协作命令总结

← 上一篇 Git 合并与冲突

下一篇 Git 工作流

✈️💬