📦 第03章 · 远程仓库与协作
clone push pull remote fetch
远程仓库与协作¶
前两章都是单人、本地操作。真正干活时,你需要一个"中心仓库"让大家把代码汇到一处、再从一处取——这就是远程仓库 (remote)。在我们的环境里,它就是自托管的 GitLab gitlab.bangdream.xyz。这一章讲 clone、remote、fetch、pull、push——协作的五块基石。
远程仓库是什么¶
远程仓库本质上是一个存储在网络另一端的 Git 仓库。本地仓库里存着一份"远程地址的别名"(origin),指向某个 URL。你可以有多个远程:origin 通常指你的主要 GitLab 仓库,还可以再加 upstream、fork 等。
git remote # 列出远程别名
git remote -v # 列出别名 + 实际 URL(最常用)
在 GitLab 上新建项目后,它会给你两种克隆地址:
| 协议 | 示例 | 特点 |
|---|---|---|
| HTTPS | https://gitlab.bangdream.xyz/group/app.git |
用用户名+访问令牌认证,适合浏览器/脚本 |
| SSH | git@gitlab.bangdream.xyz:group/app.git |
用 SSH 密钥认证,免密、更安全,适合服务器 |
可以从 gitlab-rake gitlab:env:info(第 4 章)里看到本机 GitLab 生成的克隆地址,我们的项目大概长这样:
HTTP Clone URL: https://gitlab.bangdream.xyz/group/app.git
SSH Clone URL: git@gitlab.bangdream.xyz:group/app.git
git clone:一次性拉到本地¶
clone 把远程仓库完整克隆一份到本地,自动建一对默认远程别名 origin,并检出默认分支:
git clone https://gitlab.bangdream.xyz/group/app.git ~/app # HTTPS
git clone git@gitlab.bangdream.xyz:group/app.git ~/app # SSH
git clone --depth 1 <url> # 只取最近一次提交(浅克隆)
git clone --branch feature/x <url> # 克隆后直接进指定分支
克隆后 git remote -v 已经指向目标仓库了。注意 clone 拉的是仓库的全部历史,初始体积可能不小;--depth 1 可显著减小,但会牺牲完整历史。
易错
clone的网址如果敲错或权限不足,会报fatal: repository not found或Authentication failed。先确认 URL、再确认你有该仓库的读权限(第 6 章讲权限),许多"克隆失败"其实是账号没有权限。
认证方式:HTTPS 令牌 vs SSH 密钥¶
直接推送到远程必须证明身份。两种主流方式:
HTTPS 令牌——在 GitLab 个人设置 → 访问令牌 里生成一个 token,克隆/推送时填入。令牌比密码可控(可设过期、可限定 read_repository/write_repository 范围),比明文密码安全得多。
# 用令牌 URL 克隆,避免了把令牌写进命令历史
git clone https://oauth2:<令牌>@gitlab.bangdream.xyz/group/app.git
SSH 密钥——在服务器生成一对密钥,把公钥贴到 GitLab 的 SSH Keys 里。之后 git@... 的形式自动免密:
ssh-keygen -t ed25519 -C "deploy@bangdream" # 生成密钥,按三次回车默认存 ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub # 把公钥内容复制到 GitLab → Preferences → SSH Keys
ssh -T git@gitlab.bangdream.xyz # 测试连通,看到 "Welcome to GitLab, @deploy" 即成功
git clone git@gitlab.bangdream.xyz:group/app.git ~/app
安全 不要把 SSH 私钥(
id_ed25519)或 HTTPS 令牌提交进仓库、也别放进.gitignore之外会被推送的文件。部署服务器上用它做只读克隆时,建议用受限的部署令牌,而不是开发者个人密钥。
git remote:增删改远程别名¶
| 命令 | 作用 |
|---|---|
git remote add origin <url> |
为远程 URL 起别名 |
git remote set-url origin <url> |
改远程地址(如从 HTTPS 换成 SSH) |
git remote remove origin |
移除远程别名 |
git remote rename old new |
重命名别名 |
git remote show origin |
查看远程详细信息(分支、tracking) |
# 本地已有仓库,想接到 GitLab 上
git remote add origin git@gitlab.bangdream.xyz:group/app.git
git remote -v
# 若原来接的 https,想改 ssh
git remote set-url origin git@gitlab.bangdream.xyz:group/app.git
git fetch:只"拉取"不下手¶
fetch 把你的本地仓库更新到网络上别人最新提交的状态,但它不改变你当前的工作区与分支,只是把远程新提交下载到本地(origin/main 这类"远程跟踪分支")。它让你先看看远程有什么,再决定怎么整合。
git fetch origin # 下载 origin 上所有分支的最新提交
git fetch --all # 拉取所有远程
git fetch --prune origin # 同时删除本地已消失的远程分支引用
fetch 之后,git log origin/main 就能看到远程的领先状态,但你的 main 工作区纹丝不动。
git pull:fetch 之后再整合¶
pull 是 fetch + 合并(默认 merge)的组合拳,一步把远程新提交合并到你当前分支:
git pull origin main # 拉取并合并到当前分支
git pull --rebase origin main # 拉取并"变基"到最新,保持线性(推荐)
git push -u origin main # 首次推送并建立跟踪关系(见下)
fetch 与 pull 的区别一句话¶
fetch是下载看到,pull是下载并整合。多人协作时,想先看看远程改了什么再决定,用fetch;想直接同步最新,用pull。初学时建议多用git fetch && git log origin/main观察,少直接pull,避免不明来源的合并。
跟踪分支与上游 (upstream)¶
执行 git clone 或 git push -u 后,本地分支会记录一个"上游 (upstream)"——即它和远程哪个分支结对。这样直接 git pull、git push 就不用每次带 origin main。
git branch -vv # 查看本地分支与上游的对应关系
git push -u origin feature/x # 首次推送并设为上游
git push # 之后可直接简写
git push:把你本地提交推上去¶
push 把本地已提交的改动上传到远程。注意 push 的是分支,不是工作区未提交的改动。
git push origin main # 推送当前分支到 origin 的 main
git push -u origin feature/x # 首次推送并建立跟踪
git push origin --delete feature/x # 删除远程分支
git push # 有上游时简写
git push --force # 强制覆盖远程(危险!)
安全 当你的本地分支和远程分叉(各自有新提交,即历史已改写,比如本地 rebase 过)时,
git push会被拒绝(non-fast-forward)。此时不要动不动git push --force,除非你确定要覆盖远程且无他人依赖。这是一条极易引发团队事故的规则。
案例场景:从 GitLab 拉取并推送一个前端应用¶
在本服务器上,一个 Node 前端应用常驻 /var/www/<name>。用 git 做"拉取式"部署非常简单——但注意部署机一般只读地抓取,不要反向推送:
# 1. 在部署机上首次克隆(用部署 SSH 密钥,只读)
git clone git@gitlab.bangdream.xyz:group/webapp.git /var/www/bangdream
cd /var/www/bangdream
# 2. 日常工作:先拉最新再改
git switch main
git pull --rebase # 变基拉取,保持线性
# 3. 新建分支开发
git switch -c feature/login
# ...改代码、commit...
# 4. 推送到 GitLab
git push -u origin feature/login
# 之后在 GitLab 网页上发起 Merge Request,评审后合入 main
# 5. 拉最新并部署(第 7 章常与 Runner 结合)
git switch main
git pull --rebase origin main
npm ci && npm run build # 构建前端
协作的正确姿势:分支 + 合并请求¶
多人协作最稳妥的模式是"分支 + 合并请求":
- 每个人都从主线拉分支开发;
- 推送到 GitLab 后在网页上发起 Merge Request (MR);
- 评审人审核代码、跑 CI(第 7 章),再合并到
main; - 合入后,
main上的提交由 GitLab Runner 自动构建部署。
这样核心主干受保护,谁都不能直接乱推,出问题有据可查。
延伸:更常用的协作工具¶
git fetch --prune+git branch -r:清理本地已删除的远程分支引用。git tag:给特定提交打版本标签(如v1.2.0),git push origin v1.2.0上传标签,GitLab 上可据此生成 Release。git remote show origin:查看远程分支、tracking、各分支领先/落后状态,排障利器。git log origin/main..main:看本地比远程多出哪些提交,推送前先自查。
易错点¶
git pull从错误的远程/分支拉:确认当前分支与上游,git branch -vv看清再pull,否则会把别条分支的代码合进来。- 明文令牌/私钥进命令历史:别把密码、token 直接写进
git clone https://user:pass@...。用oauth2:令牌@也尽量在受控环境,或改用 SSH 密钥。 push前不看git log origin/main..main:会把自己的提交一股脑推上去,可能覆盖部署分支。- 把代码推错远程:一台服务器上可能挂了多个项目(如
/var/www/bangdream、/var/www/dsh),先git remote -v确认origin指向目标 GitLab 项目,再push。
相关命令¶
git clone、git remote、git fetch、git pull、git push、git tag、ssh-keygen、git branch -vv、git log <a>..<b>。