Git 远程操作全解:从克隆到团队协作

📝 前言
如果让你给 Git 的功能排个"实用榜",远程操作绝对能进前三。
前两篇我们一直在本地玩 Git——创建仓库、提交、版本回退、玩分支,看起来很完整。但只要你想"和别人一起开发"或者"在多台电脑上同步代码",就必须懂远程操作。
可现实是,很多人第一次接触远程操作就懵了:
- “GitHub 是什么?怎么用?”
- “SSH Key 怎么配?HTTPS 怎么用?”
- “
git fetch和git pull有什么区别?” - “为什么
git push被拒绝?” - “远程有但本地没有的分支怎么拉下来?”
别慌。这篇博客就是来一次说清楚的。我们从远程仓库是什么讲起,配置 SSH Key 免密推送,再到 clone / push / pull 三大基础操作,然后深入远程跟踪分支、fetch vs pull 的区别、推送冲突的解决、Tag 标签管理,最后用完整实战工作流把所有知识串起来。
🎯 本节目标:让你彻底玩转 Git 远程操作。学完之后,你能用 SSH 免密推送、能 clone 任意开源项目、能在团队里流畅地"拉取-修改-推送",并能解决 90% 的远程冲突。
通过本文,你将掌握:
| 技能 | 应用场景 |
|---|---|
| 理解远程仓库的本质 | 知道 GitHub/Gitee 在你架构里的位置 |
| 配置 SSH Key 免密推送 | 日常推送再也不用输密码 |
| 熟练使用 clone / push / pull | 团队协作基础 |
| 区分 fetch vs pull | 搞清楚什么时候用哪个 |
| 理解远程跟踪分支 | 看懂 origin/master 这种奇怪的分支名 |
| 解决推送冲突 | 团队协作必踩的坑 |
| 用 Tag 标记版本 | 上线、发版必备 |
📌 前置知识: 熟练掌握第 1 篇(本地仓库)和第 2 篇(分支管理)。本篇命令同样在
user@localhost虚拟环境下演示。
文章目录
一、🌐 远程仓库是什么:GitHub/Gitee/GitLab
1.1 为什么需要"远程"
第 1 篇说过,Git 是分布式的——每个人本地都有完整版本库。既然本地就够用了,为什么还要"远程"?
实际上没有真正的"必须",但现实团队开发里远程是不可替代的:
| 需求 | 没有远程会怎样 | 有远程的好处 |
|---|---|---|
| 多人协作 | 互相拷 U 盘 | 集中式代码管理 |
| 异地办公 | 邮件传文件 | 网络实时同步 |
| 多设备办公 | 笔记本和台式机代码不同步 | 一台 push,另一台 pull 就能同步 |
| 防止丢失 | 硬盘坏了代码全没 | 远程仓库就是备份 |
| 开源贡献 | 没法给开源项目提 PR | fork → 改 → pull request |
💡 远程仓库 = 一台 24 小时开机的服务器 + Git 服务。开发者把本地仓库的"镜像"推送到这台服务器,团队成员从这里拉取。
1.2 主流远程平台对比
| 平台 | 网址 | 特点 |
|---|---|---|
| GitHub | https://github.com | 全球最大开源社区 |
| Gitee(码云) | https://gitee.com | 国内访问快,中文友好 |
| GitLab | https://gitlab.com | 可自建,企业私有部署常用 |
| Bitbucket | https://bitbucket.org | Atlassian 出品,集成 Jira |
💡 国内开发者强烈推荐 Gitee:访问速度快、私有仓库免费、界面中文。开源项目可以同时托管在 GitHub 和 Gitee。
1.3 创建远程仓库(Gitee 示例)
Step 1:注册 Gitee 账号(略)
Step 2:创建新仓库
进入 Gitee 首页 → 右上角 + → 新建仓库
Step 3:填写仓库信息
| 字段 | 建议 |
|---|---|
| 仓库名称 | git-remote-practice(小写、横线连接) |
| 路径 | 自动生成 |
| 仓库介绍 | 一句话说明项目 |
| 是否开源 | 私有 / 公开 |
| 初始化 | 勾选 使用 README 文件初始化仓库 |
| 添加 .gitignore | 选对应语言模板(如 Python) |
| 添加许可证 | 可选(开源项目建议选) |
Step 4:点 创建
你会看到仓库页面,最重要的就是这个 URL:
https://gitee.com/your-name/git-remote-practice.git
这就是你远程仓库的"地址",所有 clone、push、pull 操作都要用到它。
1.4 远程仓库的本质
远程仓库本质上就是一个 Git 仓库,跟你在本地 git init 出来的仓库结构完全一样——只是放在了一台服务器上。
💡 没有什么神秘的。你可以用
git clone把任何远程仓库"镜像"到本地,用git push把本地仓库"镜像"到远程。两边是对等的。
二、🔑 配置 SSH Key:免密推送
远程操作有两种连接方式:HTTPS 和 SSH。强烈推荐 SSH——免密码、更安全。
2.1 HTTPS vs SSH 对比
| 维度 | HTTPS | SSH |
|---|---|---|
| 认证方式 | 账号密码 / Token | SSH Key(公钥+私钥) |
| 是否要输密码 | 每次 push 都要 | 配好后免密 |
| 防火墙友好 | 走 443 端口 | 走 22 端口(可能被挡) |
| 适用场景 | 临时使用、CI/CD | 长期开发、本地日常 |
2.2 生成 SSH Key
Step 1:检查是否已有 SSH Key
# 看默认目录下有没有密钥
ls -la ~/.ssh/
# 看 id_rsa / id_ed25519 文件存不存在
如果存在就跳过这步。
Step 2:生成新的 SSH Key
# 推荐用 ed25519 算法(更安全、更快)
ssh-keygen -t ed25519 -C "your.email@example.com"
💡
-C后面是注释,一般填你的邮箱,方便识别这是谁的 key。
Step 3:一路回车(默认设置)
Enter file in which to save the key (/home/user/.ssh/id_ed25519): [回车]
Enter passphrase (empty for no passphrase): [回车]
Enter same passphrase again: [回车]
Step 4:查看公钥
cat ~/.ssh/id_ed25519.pub
输出类似:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0wm9pJ8... your.email@example.com
整行复制这一串。
2.3 把公钥配置到 Gitee
进入 Gitee → 右上角头像 → 设置 → SSH公钥 → 粘贴 → 起个标题(比如"我的笔记本")→ 确定
💡 公钥 = 你家门牌号(可以公开)。私钥 = 你家钥匙(绝对不能泄露,放在
~/.ssh/id_ed25519里)。
2.4 测试连接
# Gitee
ssh -T git@gitee.com
# GitHub
ssh -T git@github.com
第一次连接会提示:
The authenticity of host 'gitee.com (xxx.xxx.xxx.xxx)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
输入 yes,看到:
Hi 你的用户名! You've successfully authenticated, but Gitee.com does not provide shell access.
就说明配置成功了 🎉
2.5 把公钥配到 GitHub(如果你用 GitHub)
GitHub 的配置步骤完全类似:
GitHub → 右上角头像 → Settings → SSH and GPG keys → New SSH key → 粘贴公钥 → 保存
⚠️ 一个 SSH Key 可以在多个平台用同一对公钥/私钥。你也可以为不同平台生成不同 Key(建议这样做),管理更清晰。
2.6 多个 SSH Key 管理
如果你有 GitHub + Gitee 两套账号,要用不同 Key:
# 1. 生成两个不同的 key
ssh-keygen -t ed25519 -C "email1@example.com" -f ~/.ssh/id_ed25519_github
ssh-keygen -t ed25519 -C "email2@example.com" -f ~/.ssh/id_ed25519_gitee
# 2. 配置 ~/.ssh/config
cat > ~/.ssh/config << EOF
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_ed25519_gitee
EOF
这样就能同时管理多个平台的 SSH Key。
三、📥 克隆远程仓库:git clone
3.1 第一次接触远程操作
有了远程仓库,下一步就是把它"搬到"本地。这个动作叫 clone(克隆)。
# 克隆 Gitee 仓库
git clone git@gitee.com:your-name/git-remote-practice.git
# 输出:
# Cloning into 'git-remote-practice'...
# remote: Enumerating objects: 4, done.
# remote: Counting objects: 100% (4/4), done.
# remote: Compressing objects: 100% (3/3), done.
# Receiving objects: 100% (4/4), done.
# remote: Total 4 (delta 0), reused 0 (delta 0)
3.2 clone 后发生了什么
cd git-remote-practice
# 1. 自动创建本地仓库
ls -la
# .git/ ReadMe ...
# 2. 自动添加远程地址(默认叫 origin)
git remote -v
# origin git@gitee.com:your-name/git-remote-practice.git (fetch)
# origin git@gitee.com:your-name/git-remote-practice.git (push)
# 3. 自动创建 master/main 分支
git branch
# * master
💡
origin是远程仓库的默认名称,是你本地的"代号",对应一个真实 URL。
3.3 clone 时的常见选项
# 1. 克隆到指定目录
git clone <url> <directory-name>
# 2. 只克隆某个分支
git clone -b dev <url>
# 3. 浅克隆(只拉最新一次 commit,适合大项目)
git clone --depth 1 <url>
# 4. 克隆并切换目录
git clone <url> && cd $(basename $_ .git)
3.4 协议选择
clone URL 一般有 3 种形式:
| 协议 | 例子 | 推荐 |
|---|---|---|
| HTTPS | https://gitee.com/your-name/repo.git | 公司网络、临时使用 |
| SSH | git@gitee.com:your-name/repo.git | 日常开发 |
| Git | git://gitee.com/your-name/repo.git | 只读场景 |
强烈推荐 SSH。HTTPS 在 Gitee 上已经被官方弃用了,GitHub 上还能用但经常要求输入 Token。
3.5 克隆开源项目
GitHub 上的开源项目直接 clone:
# 克隆一个有名的开源项目
git clone https://github.com/torvalds/linux.git
# (这个会很久,因为它有百万次提交)
# 浅克隆看代码(只要最新一次)
git clone --depth 1 https://github.com/torvalds/linux.git
💡 看开源项目代码用浅克隆就够了。要研究历史再用完整克隆。
四、📤 推送本地到远程:git push
克隆完远程仓库后,你在本地做修改、提交,最后要把这些提交推送到远程——这个动作叫 push。
4.1 第一次推送
# 1. 做一些修改
echo "hello remote" > ReadMe
git add ReadMe
git commit -m "add ReadMe"
# 2. 推送到远程
git push origin master
# 输出:
# Enumerating objects: 4, done.
# Counting objects: 100% (4/4), done.
# Writing objects: 100% (3/3), 280 bytes | 280.00 KiB/s, done.
# Total 3 (delta 0), reused 0 (delta 0)
# To gitee.com:your-name/git-remote-practice.git
# abc1234..def5678 master -> master
💡
git push语法:git push <远程名> <本地分支>:<远程分支>。如果本地分支和远程分支同名,可以简写成git push origin master。
4.2 推送时的"上游分支"概念
第一次 push 时 Git 会提示:
fatal: The current branch master has no upstream branch.
意思是当前 master 分支没有"上游分支"。上游分支就是"本地分支对应的远程分支"。
两种方法建立上游分支:
# 方法一:push 时加 -u
git push -u origin master
# 之后直接 git push 就行
# 方法二:push 时用完整语法
git push --set-upstream origin master
💡
-u是--set-upstream的简写。一旦设置了上游分支,以后git push、git pull都不用带参数,Git 自动知道推/拉哪个远程分支。
4.3 推送失败:rejected
最常见的错误:
! [rejected] master -> master (fetch first)
error: failed to push some refs to '...'
hint: Updates were rejected because the remote contains work that you do not have locally.
这是因为远程有你本地没有的提交。最常见原因:
- 你 clone 之后,别人 push 了新内容
- 你在另一台机器上 push 过
解决方案:先 pull,再 push:
# 1. 先拉取远程的改动
git pull origin master
# 2. 解决可能的冲突(详见第 7 节)
# ...
# 3. 重新 push
git push origin master
4.4 推送 tag
# 1. 创建本地 tag
git tag v1.0.0
# 2. 推送 tag 到远程
git push origin v1.0.0
# 或推送所有 tag
git push origin --tags
💡 tag 默认不会跟着 commit push。
git push不会推 tag,要单独推。
4.5 强制推送:--force
# 强制 push(覆盖远程历史)
git push --force origin master
⚠️
--force是危险操作!它会丢弃远程的提交。多人协作时如果别人已经基于远程 commit 在工作了,强制 push 会让他们的本地历史"脱节"。慎用!
更安全的方式:--force-with-lease
git push --force-with-lease origin master
这条命令会在 push 前先检查远程是否被别人更新过。如果别人 push 过,拒绝 push,避免误删别人提交。
💡 团队开发永远不要用
--force,用--force-with-lease。这个习惯能救命。
4.6 删除远程分支
# 删除远程分支
git push origin --delete dev
# 老的语法(也支持)
git push origin :dev
⚠️ 远程分支删除后,本地的
origin/dev远程跟踪分支还在。下次 fetch 时会更新(详见第 7 节)。
五、📥 拉取远程到本地:git pull
push 是把本地推到远程,pull 则是把远程拉到本地。
5.1 git pull 基础
# 拉取并合并远程 master
git pull origin master
git pull 实际上是两步操作的简写:
# 等价于:
git fetch origin
git merge origin/master
5.2 pull 时的"上游分支"前提
只有配置了上游分支的本地分支才能直接 git pull:
# 已配置上游:直接 pull
git pull
# 未配置:必须指定
git pull origin master
💡 这就是为什么第一次 push 时要
git push -u origin master——同时设置了上游。
5.3 pull 时遇到冲突
git pull origin master
# Auto-merging ReadMe
# CONFLICT (content): Merge conflict in ReadMe
# Automatic merge failed; fix conflicts and then commit the result.
解决方法和 merge 冲突完全一样(参考第 2 篇第 5 节):
# 1. 编辑冲突文件
# 2. git add <file>
# 3. git commit -m "merge origin/master"
5.4 git pull --rebase:保持线性历史
默认 git pull 会产生一个 merge commit:
本地: C1 ── C2
远程:C1 ── C3 ── C4
pull 之后:
合并提交 ── C2, C3, C4 (merge commit)
如果你想让历史保持线性(没有 merge commit):
# 配置默认行为
git config --global pull.rebase true
# 之后 git pull 就会 rebase 而非 merge
本地: C1 ── C2
远程:C1 ── C3 ── C4
pull --rebase 之后:
C1 ── C3 ── C4 ── C2
💡 推荐配置
pull.rebase true——团队协作时线性历史更清晰,避免无意义的 merge commit。
5.5 撤销 pull
如果 pull 错了想回退:
# 撤销最近一次 merge(pull 默认是 merge)
git reset --hard HEAD^
# 撤销 rebase pull
git reset --hard origin/master
⚠️
--hard会丢工作区未提交的改动。pull 前先 commit 一下是好习惯。
六、🔍 远程跟踪分支:理解 origin/master
很多新手看到 origin/master、origin/dev 这种名字会懵——这是什么?
6.1 远程跟踪分支的概念
💡 远程跟踪分支(Remote Tracking Branch) 是对远程仓库状态的"只读引用",格式是
<remote>/<branch>。
比如 origin/master 表示"远程 origin 仓库的 master 分支在本地最后已知的位置"。
# 1. 查看所有分支(含远程跟踪分支)
git branch -a
# * master
# remotes/origin/HEAD -> origin/master
# remotes/origin/master
# 2. 查看具体远程跟踪分支的指向
git log origin/master --oneline -3
# def5678 latest commit on master
6.2 远程跟踪分支的更新时机
远程跟踪分支只在 git fetch 或 git pull 时更新。fetch 更新跟踪分支;pull 在 fetch 基础上还会 merge。
# 模拟场景:远程有新提交,本地远程跟踪分支还是旧的
# 1. 第一次看远程跟踪分支
git log origin/master --oneline -1
# abc1234 old commit
# 2. fetch 一下
git fetch origin
# remote: Enumerating objects: 5, done.
# remote: Counting objects: 100% (3/3), done.
# Unpacking objects: 100% (3/3), done.
# From gitee.com:your-name/git-remote-practice
# abc1234..def5678 master -> origin/master
# 3. 远程跟踪分支更新了
git log origin/master --oneline -1
# def5678 new commit
6.3 远程跟踪分支和本地分支的关系
远程仓库:
master ──→ C1 ── C2 ── C3
本地的远程跟踪分支:
origin/master ──→ C3 (fetch 后同步)
本地分支(master):
master ──→ C1 ── C2 (还没 merge/pull 远程)
工作流:
# 1. fetch(拉取远程状态,不影响本地代码)
git fetch origin
# origin/master 更新到 C3,本地 master 还是 C2
# 2. 查看远程最新
git log origin/master --oneline
# 3. 合并远程到本地
git merge origin/master
# 或
git pull origin master
6.4 本地新建分支跟踪远程分支
# 在本地创建一个新分支,跟踪远程的 dev
git checkout -b dev origin/dev
# 或新语法
git switch -c dev origin/dev
# 之后 git pull 就会自动拉取 origin/dev
七、⚠️ 推送冲突:原因与解决
推送冲突是远程操作最让人崩溃的场景。但理解了原理,解决并不难。
7.1 为什么会冲突
两台机器上对同一个文件的同一行做了不同修改,然后都 push 远程:
机器 A 改了文件,commit + push 成功
↓
远程 master 现在是 C3
↓
机器 B 改了同一文件,commit 后想 push
↓
B 的本地 master 是 C2,B 想把本地 commit 推到远程
↓
但远程已经是 C3 了,Git 拒绝
7.2 推送冲突的错误信息
To gitee.com:your-name/git-remote-practice.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to '...'
hint: Updates were rejected because the remote contains work that you do not have locally.
This is usually caused by another repository pushing to the same ref.
You may want to first integrate the remote changes
(e.g., 'git pull ...') before pushing again.
7.3 解决推送冲突的标准流程
# 1. 拉取远程的改动
git pull origin master
# 2. 解决可能的冲突
# vim ReadMe # 手动解决
# git add ReadMe
# git commit -m "merge origin/master"
# 3. 重新 push
git push origin master
7.4 推送冲突的"特殊"情况
情况 1:远程只有一个 merge commit,没有实质改动
# 拉取后产生空 merge
git pull --no-ff
# Already up to date.
# 重新 push
git push
情况 2:你确定远程的修改要被丢弃
# 危险!用 --force-with-lease 更安全
git push --force-with-lease
7.5 预防推送冲突的好习惯
| 习惯 | 怎么做 |
|---|---|
| 推送前先 fetch | git fetch origin && git status |
| 推送前先 pull | git pull --rebase origin master(已配置) |
| 小颗粒度提交 | 一次提交一个功能 |
| 频繁推送 | 每完成一个功能就 push |
| 早上第一件事 pull | git pull 看远程最新 |
💡
fetch + rebase流程是金标准:git fetch origin git rebase origin/master # 解决冲突 git push origin master这样历史是线性的,PR 评审也清晰。
八、🏷️ 标签管理:git tag
8.1 什么是 tag
💡 tag(标签) 是给某个特定 commit 起一个有意义的名字。常用于版本发布(v1.0.0、v2.1.3)。
tag 和分支的区别:
- 分支:可移动的指针,会随着新提交自动移动
- tag:固定的指针,永远指向那个 commit
8.2 标签的两种类型
| 类型 | 说明 |
|---|---|
| 轻量标签 | 只是一个名字,指向某个 commit |
| 附注标签 | 包含打标签者的信息、日期、说明,推荐 |
8.3 创建 tag
# 1. 创建轻量标签
git tag v1.0.0
# 2. 创建附注标签(推荐)
git tag -a v1.0.0 -m "发布 1.0.0 版本"
# 3. 给历史 commit 打 tag
git tag -a v0.9.0 <commit-id> -m "0.9.0 版本"
8.4 查看 tag
# 1. 列出所有 tag
git tag
# v0.9.0
# v1.0.0
# 2. 查看 tag 详情
git show v1.0.0
# 3. 模糊搜索 tag
git tag -l "v1.*"
# v1.0.0
# v1.1.0
8.5 推送 tag 到远程
# 1. 推送单个 tag
git push origin v1.0.0
# 2. 推送所有 tag
git push origin --tags
⚠️ tag 不会自动跟随
git push推送——必须显式 push。
8.6 删除 tag
# 1. 删除本地 tag
git tag -d v1.0.0
# 2. 删除远程 tag
git push origin --delete v1.0.0
# 或
git push origin :refs/tags/v1.0.0
8.7 检出 tag
# 切换到某个 tag
git checkout v1.0.0
# 会进入"detached HEAD"状态(详见第 13 节思考题)
💡 tag 状态下的 commit 不建议修改——它代表一个"已发布"的版本。如需修改应创建新版本号。
8.8 tag 的实战用法
# 1. 发布新版本
git checkout master
git tag -a v1.0.0 -m "发布 1.0.0"
git push origin v1.0.0
# 2. 修复历史版本的 Bug
git checkout -b hotfix/1.0.1 v1.0.0
# ... 修 Bug、commit
git checkout master
git merge hotfix/1.0.1
git tag -a v1.0.1 -m "1.0.1 紧急修复"
git push origin v1.0.1 --tags
git branch -d hotfix/1.0.1
💡 打 tag 一定要推送——不上远程的 tag 等于没打。
九、📌 远程操作实操:完整工作流演示
把这一篇的所有知识点串起来,做一个完整实战。
任务:在两台"机器"上协作(用本地不同目录模拟),完成"开发-推送-拉取-解决冲突"全流程。
场景:双机器协作
# 1. 准备远程仓库
mkdir -p /home/user/test/remote-workflow
cd /home/user/test/remote-workflow
git init --bare remote-repo.git
# bare 仓库:纯远程仓库,不带工作区
# 2. 机器 A:克隆并首次提交
cd /home/user/test
git clone /home/user/test/remote-workflow/remote-repo.git machine-a
cd machine-a
echo "v1" > app.py
git add .
git commit -m "v1: 初始版本"
git push -u origin master
模拟两台机器同时改文件
# 机器 A 改 app.py
cd /home/user/test/machine-a
echo "v2 from A" >> app.py
git add .
git commit -m "v2: A 改的"
# 机器 B 同步(cd 到另一个目录模拟)
cd /home/user/test
git clone /home/user/test/remote-workflow/remote-repo.git machine-b
cd machine-b
echo "v2 from B" >> app.py # 改同一行!
git add .
git commit -m "v2: B 改的"
# 机器 A 先 push
cd /home/user/test/machine-a
git push origin master
# 成功
# 机器 B 推送
cd /home/user/test/machine-b
git push origin master
# 失败!rejected
解决冲突
# 机器 B pull
cd /home/user/test/machine-b
git pull origin master
# CONFLICT
# 编辑 app.py 解决冲突
cat app.py
# <<<<<<< HEAD
# v2 from B
# =======
# v2 from A
# >>>>>>> origin/master
# 改成:
# v2 from A and B merged
git add app.py
git commit -m "merge: 解决 A/B 冲突"
git push origin master
# 成功!
这就是真实的"团队协作"流程。学完这一套,你已经具备远程协作的基础能力了。
十、❓ 本节常见问题解答
挑 1 个跟远程操作最核心的问题。
1️⃣ 远程有但本地没有的分支怎么拉取?
答:用 git fetch + git checkout(或 git switch)。
# 1. 先抓取远程所有分支信息
git fetch origin
# 2. 看远程有哪些分支
git branch -r
# origin/master
# origin/dev
# origin/feature/pay
# 3a. 创建并切换到远程分支(老语法)
git checkout -b dev origin/dev
# 3b. 创建并切换到远程分支(新语法,推荐)
git switch -c dev origin/dev
之后这个本地 dev 分支会自动跟踪远程 origin/dev,可以直接 git pull / git push。
💡 详细步骤拆解:
git fetch origin抓取远程最新信息(不修改本地工作区)git branch -r看远程分支列表git switch -c 本地名 远程/远程名创建并切换
补充:fetch vs pull 区别
# fetch:只下载,不合并
git fetch origin
# 工作区不变,origin/* 远程跟踪分支更新
# pull:fetch + merge
git pull origin master
# 工作区改变,自动合并 origin/master
💡 推荐平时只用 fetch,看清楚再决定是否 merge。
pull是"自动化",出问题不好回退;fetch + merge是"手动挡",更可控。
十一、🎯 实战练习:远程操作"五连击"
来练 5 个连续动作,体验真实远程操作。
任务(用 Gitee 或本地 bare 仓库模拟):
- 在 Gitee 上创建公开仓库
git-remote-practice - 用 SSH 协议 clone 到本地
- 创建
dev分支并 push 到远程 - 在本地 dev 分支加一个文件
feature.txt,commit + push - 在另一台"机器"(用新目录模拟)clone 远程仓库,切到 dev,修改
feature.txt并 push - 回到第一台机器 pull,看到冲突,解决冲突后 push
参考答案(用本地 bare 仓库模拟):
# 1. 准备远程仓库
mkdir -p /home/user/test/remote-practice
cd /home/user/test/remote-practice
git init --bare origin-repo.git
# 2. 机器 A 克隆
cd /home/user/test
git clone /home/user/test/remote-practice/origin-repo.git machine-a
cd machine-a
git config user.email "a@example.com"
git config user.name "Machine A"
# 3. 创建 dev 分支并 push
git checkout -b dev
git push -u origin dev
# 4. 加文件 commit push
echo "feature A" > feature.txt
git add .
git commit -m "feat: A 加 feature.txt"
git push origin dev
# 5. 机器 B 克隆
cd /home/user/test
git clone /home/user/test/remote-practice/origin-repo.git machine-b
cd machine-b
git config user.email "b@example.com"
git config user.name "Machine B"
git switch dev
echo "feature B" > feature.txt # 改同一文件!
git add .
git commit -m "feat: B 改 feature.txt"
git push origin dev # 成功(此时没有冲突)
# 6. 回到 A,改同一行
cd /home/user/test/machine-a
echo "feature A modified" > feature.txt
git add .
git commit -m "feat: A 也改 feature.txt"
git push origin dev # 失败!被拒绝
git pull origin dev # 拉取 B 的改动
# CONFLICT 提示
# 解决冲突
echo "feature merged" > feature.txt
git add .
git commit -m "merge: 解决 A/B 冲突"
git push origin dev # 成功
跑完这个流程,你就掌握了远程协作的核心模式。
十二、📌 关键命令速查表
| 命令 | 作用 |
|---|---|
git clone <url> | 克隆远程仓库 |
git remote -v | 查看远程地址 |
git remote add origin <url> | 添加远程仓库 |
git remote remove origin | 删除远程仓库 |
git remote rename <old> <new> | 重命名远程仓库 |
git push | 推送到上游分支 |
git push -u origin <branch> | 推送并设置上游 |
git push origin --tags | 推送所有 tag |
git push origin --delete <branch> | 删除远程分支 |
git push --force-with-lease | 安全强制推送 |
git pull | 拉取并合并(上游分支) |
git pull --rebase | 拉取并 rebase |
git fetch | 只下载不合并 |
git fetch -p | 下载并清理已删除的远程分支 |
git branch -r | 查看远程分支 |
git branch -a | 查看所有分支 |
git switch -c <name> origin/<name> | 创建并跟踪远程分支 |
git tag | 列出所有 tag |
git tag -a <name> -m "msg" | 创建附注 tag |
git push origin <tagname> | 推送 tag |
git tag -d <name> | 删除本地 tag |
git push origin --delete <tagname> | 删除远程 tag |
十三、🤔 几个思考题
学完本文,来试试回答这些问题:
1️⃣ HTTPS 和 SSH 哪个更安全?
答:从不同维度看,不完全可比。
| 维度 | HTTPS | SSH |
|---|---|---|
| 传输加密 | 都加密 | 都加密 |
| 身份认证 | 账号密码 / Token | 公私钥对 |
| 易用性 | 简单,clone 就能用 | 需配置 SSH Key |
| 长期使用 | 需定期更换 Token | 一次配置,永久免密 |
| 多设备 | 每台设备都要 Token | 每台设备配一次 Key |
| CI/CD | 推荐用 Token | 不推荐(Key 管理麻烦) |
选择建议:
- 个人日常开发:SSH(一次配置终身免密)
- CI/CD 流水线:HTTPS + Token(Token 可吊销)
- 临时用别人电脑:HTTPS(省去配置 Key 麻烦)
💡 没有绝对安全——定期更换 Token、定期 review SSH Key 列表、避免在公共电脑保存私钥,这些都是好习惯。
2️⃣ git fetch 后什么都没变,是 bug 吗?
答:不是。
git fetch 只会更新远程跟踪分支(origin/*),不会修改你的工作区。这正是 fetch 和 pull 的核心区别。
# fetch 后
git fetch origin
# 远程跟踪分支 origin/master 更新了
# 但本地 master 分支、工作区都没变
# 验证
git log origin/master --oneline -3 # 看远程最新
git log master --oneline -3 # 看本地(可能落后)
💡 这就是为什么
fetch比pull安全——“先看清楚再决定”。
3️⃣ git push --force 和 git push --force-with-lease 区别?
答:是否检查远程是否被更新过。
# --force:无脑覆盖
git push --force origin master
# 远程被更新也会强制覆盖
# --force-with-lease:会检查
git push --force-with-lease origin master
# 如果远程已被更新(被别人 push 过),拒绝 push
举例:
# 场景:你强制回退了本地 master
git reset --hard HEAD~3
# 准备强制 push
git push --force origin master
# --force 会成功,但别人基于你之前提交的代码会"脱节"
# --force-with-lease 会拒绝,让你先 pull
⚠️ 团队开发永远用
--force-with-lease。这个习惯能避免 90% 的"误删别人代码"事故。
4️⃣ 怎么"撤销"已经 push 的提交?
答:用 git revert 而不是 git reset。
# 1. 找到要撤销的 commit
git log --oneline -5
# def5678 add bad code
# abc1234 previous good code
# 2. 用 revert 创建一个"撤销"提交
git revert def5678
# 这会产生一个新的 commit,撤销 def5678 的改动
# 历史保留,但实际效果是"回退"
# 3. push 撤销提交
git push origin master
💡
git reset会改写历史,已经 push 出去再用 reset 会让队友本地"脱节"。git revert不改写历史,通过新提交"反向操作",是远程回退的正确姿势。
5️⃣ git pull 之后想撤销,怎么做?
答:分情况。
情况 1:pull 用了 merge(默认)
# 撤销 merge commit
git reset --hard HEAD^
情况 2:pull 用了 rebase
# 撤销 rebase
git reset --hard origin/master
# 或
git reset --hard @{1} # 回到 rebase 前的状态
情况 3:用 git reflog 找回去
git reflog
# 看到所有操作记录,找到 pull 前的 commit id
git reset --hard <commit-id>
⚠️
--hard会丢工作区未提交内容。pull 前先 commit 是好习惯。
写在最后
到这里,《Git 远程操作全解》就告一段落了 🎉
我们从远程仓库的本质讲起,配置 SSH Key 实现免密推送,再到 clone / push / pull 三大基础操作,深入了远程跟踪分支和 fetch vs pull 的区别,再到推送冲突的解决和 Tag 标签管理。
学完本篇,你已经能:
- ✅ 用 SSH 免密推送
- ✅ clone 任意开源项目
- ✅ 团队里流畅地"拉取-修改-推送"
- ✅ 解决 90% 的远程冲突
📝 下一篇是《Git 多人协作实战》。我们会把远程操作、分支管理、冲突解决串成真实的多人协作场景,带你体验"5 人团队怎么用 Git 高效配合"——以及一些职场老鸟才懂的协作技巧(比如"我改了一行代码,要不要直接 push ?")
我们下一篇见!
✅ 本节完…
📝 作者:say-fall | 编辑:say-fall | 🌟 原创不易,如果对你有帮助,记得 👍 点赞 + ⭐ 收藏 哦!

174

被折叠的 条评论
为什么被折叠?



