【Git 精品详解】远程操作:远程仓库、clone / push / pull、推送冲突和tag标签管理

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

在这里插入图片描述

🌈 say-fall:个人主页
🚀 专栏:《手把手教你学会C++》 | 《系统深入Linux操作系统》 | 《数据结构与算法》 | 《小游戏与项目》
💪 格言:做好你自己,才能吸引更多人,与他们共赢,这才是最好的成长方式。

📝 前言

如果让你给 Git 的功能排个"实用榜",远程操作绝对能进前三。

前两篇我们一直在本地玩 Git——创建仓库、提交、版本回退、玩分支,看起来很完整。但只要你想"和别人一起开发"或者"在多台电脑上同步代码",就必须懂远程操作。

可现实是,很多人第一次接触远程操作就懵了:

  • “GitHub 是什么?怎么用?”
  • “SSH Key 怎么配?HTTPS 怎么用?”
  • git fetchgit 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 就能同步
防止丢失硬盘坏了代码全没远程仓库就是备份
开源贡献没法给开源项目提 PRfork → 改 → pull request

💡 远程仓库 = 一台 24 小时开机的服务器 + Git 服务。开发者把本地仓库的"镜像"推送到这台服务器,团队成员从这里拉取。

1.2 主流远程平台对比

平台网址特点
GitHubhttps://github.com全球最大开源社区
Gitee(码云)https://gitee.com国内访问快,中文友好
GitLabhttps://gitlab.com可自建,企业私有部署常用
Bitbuckethttps://bitbucket.orgAtlassian 出品,集成 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:免密推送

远程操作有两种连接方式:HTTPSSSH。强烈推荐 SSH——免密码、更安全。

2.1 HTTPS vs SSH 对比

维度HTTPSSSH
认证方式账号密码 / TokenSSH 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 → 右上角头像 → SettingsSSH and GPG keysNew 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 种形式:

协议例子推荐
HTTPShttps://gitee.com/your-name/repo.git公司网络、临时使用
SSHgit@gitee.com:your-name/repo.git日常开发
Gitgit://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 pushgit 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 pushgit 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/masterorigin/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 fetchgit 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 预防推送冲突的好习惯

习惯怎么做
推送前先 fetchgit fetch origin && git status
推送前先 pullgit pull --rebase origin master(已配置)
小颗粒度提交一次提交一个功能
频繁推送每完成一个功能就 push
早上第一件事 pullgit 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,看清楚再决定是否 mergepull 是"自动化",出问题不好回退;fetch + merge 是"手动挡",更可控。


十一、🎯 实战练习:远程操作"五连击"

来练 5 个连续动作,体验真实远程操作。

任务(用 Gitee 或本地 bare 仓库模拟):

  1. 在 Gitee 上创建公开仓库 git-remote-practice
  2. 用 SSH 协议 clone 到本地
  3. 创建 dev 分支并 push 到远程
  4. 在本地 dev 分支加一个文件 feature.txt,commit + push
  5. 在另一台"机器"(用新目录模拟)clone 远程仓库,切到 dev,修改 feature.txt 并 push
  6. 回到第一台机器 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 哪个更安全?

答:从不同维度看,不完全可比。

维度HTTPSSSH
传输加密都加密都加密
身份认证账号密码 / 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          # 看本地(可能落后)

💡 这就是为什么 fetchpull 安全——“先看清楚再决定”

3️⃣ git push --forcegit 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 | 🌟 原创不易,如果对你有帮助,记得 👍 点赞 + ⭐ 收藏 哦!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值