一篇讲透 Git:从原理到实战,顺手搞定 GitHub / Gitee 双平台同步

很多人学 Git,卡住的从来不是命令太多,而是一直没真正理解 Git 在做什么。于是 addcommitmergerebaseresetrevert 看起来都会,一到真实场景就容易乱。这篇文章会用一条清晰主线,把 Git 最核心的原理、最常用的工作流、分支与冲突处理、回滚思路,以及 GitHub / Gitee 双平台同步一次讲透。看完之后,你不只是会敲命令,而是真的知道每一步到底在操作什么。

很多人学 Git,卡住的从来不是命令不够熟。

真正难的,往往是这些时刻:

  • 不知道 git add 到底在干嘛
  • 暂存区总是似懂非懂
  • mergerebaseresetrevert 一到实战就乱
  • 想同步 GitHub 和 Gitee,又怕把远程仓库配坏

问题的根源不是你记不住命令,而是你还没有真正建立 Git 的内部模型。

这篇文章就做一件事:

把 Git 最核心的逻辑真正讲清楚。

你看完之后,会真正掌握这些内容:

  • Git 最核心的工作原理
  • 一套最常用的日常工作流
  • 分支、合并、冲突和回滚
  • SSH 配置
  • 一个项目一次 git push 同步 GitHub 和 Gitee

如果你正处在“会一点 Git,但总觉得没完全吃透”的阶段,这篇文章就是写给你的。


一、Git 到底是什么

Git 是一个分布式版本控制系统(Distributed Version Control System)。

如果只讲定义,很多人看完其实没感觉。更直白一点说,你可以把 Git 理解成:

给代码建立一条可以回退、对比、分叉、合并的时间线。

比如你写代码的过程,可能是这样的:

第 1 天  o
第 2 天  o
第 3 天  o
第 4 天  o
第 5 天  o

而 Git 做的事情,其实就是把这些关键时刻保存下来:

o──o──o──o──o
↑  ↑  ↑  ↑  ↑
每一次提交(commit)都是一个可回退的历史点

所以 Git 不只是“存文件”,而是在保存文件变化的历史

这件事非常重要,因为一旦你接受了这个视角,很多命令就不再是孤立的操作,而是在操作同一条时间线。


二、真正搞懂 Git,先理解三区模型

很多人命令背了不少,但还是经常用乱,核心原因就是没理解 Git 最关键的三区模型:

工作区(Working Directory)
    ↓ git add
暂存区(Staging Area / Index)
    ↓ git commit
本地仓库(Repository)

也可以这样看:

┌────────────────────┐
│ 工作区              │
│ 你正在修改的文件     │
└─────────┬──────────┘
          │ git add
          ↓
┌────────────────────┐
│ 暂存区              │
│ 准备提交的内容       │
└─────────┬──────────┘
          │ git commit
          ↓
┌────────────────────┐
│ 本地仓库            │
│ 已保存的历史版本     │
└────────────────────┘

这三者分别是什么?

  • 工作区:你当前正在编辑文件的地方
  • 暂存区:你准备提交的内容集合
  • 本地仓库:真正保存提交历史的地方

所以 git addgit commit 的区别,本质上就是:

  • git add:把改动放进暂存区
  • git commit:把暂存区内容变成一次正式提交

这是 Git 最关键的理解,没有之一。

很多人第一次学 Git,最困惑的就是:

我都改完文件了,为什么不能直接提交?

答案就在这里:Git 故意把“修改文件”和“正式提交”拆成两步,是为了让你有机会决定:

  • 哪些改动现在提交
  • 哪些改动晚点再提交
  • 哪些文件根本不该进这次提交

所以暂存区不是多余设计,而是 Git 非常强大的一个缓冲层。


三、第一次使用 Git,要先做什么

先检查 Git 有没有安装:

git --version

常见输出:

git version 2.43.0

接着设置用户名和邮箱:

git config --global user.name "你的名字"
git config --global user.email "你的邮箱"

查看配置:

git config --global user.name
git config --global user.email

如果你某个项目想单独使用另一套身份,也可以只对当前仓库设置:

git config user.name "项目专用用户名"
git config user.email "项目专用邮箱"

简单记住:

  • --global:影响你电脑上大多数仓库
  • 不带 --global:只影响当前项目

这一步虽然简单,但非常值得一开始就配好。否则你后面每次提交,作者信息都可能乱掉。


四、Git 最常用的 5 个命令

理解了三区模型后,很多 Git 命令其实就不难了。

真正高频、你几乎天天会用到的,核心就这 5 个:

git status   → 看现在是什么状态
git add      → 把改动放进暂存区
git commit   → 生成一个历史版本
git log      → 查看历史提交
git diff     → 对比改动内容

1)git status

git status

示例输出:

On branch main
Changes not staged for commit:
  modified:   src/login.js

Untracked files:
  README-notes.txt

这里你主要看两个词:

  • modified:文件改了,但还没 git add
  • Untracked files:Git 还没开始跟踪这个文件

你可以把 git status 理解成:

先别急着操作,先看清楚现场。

这几乎是所有 Git 操作前最值得先敲的一条命令。

2)git add

git add 文件名

或者:

git add .

执行后再看状态,常见会变成:

On branch main
Changes to be committed:
  modified:   src/login.js
  new file:   README-notes.txt

这说明内容已经进入暂存区了。

3)git commit

git commit -m "feat: 添加登录页面"

示例输出:

[main a1b2c3d] feat: 添加登录页面
 3 files changed, 45 insertions(+), 2 deletions(-)

这里的 a1b2c3d 就是这次提交的 commit ID。

4)git log

git log --oneline --graph --decorate

示例输出:

* a1b2c3d (HEAD -> main) feat: 添加登录页面
* e4f5g6h init project

最上面是最新提交,HEAD -> main 表示你当前在 main 分支最新位置。

5)git diff

git diff

示例输出:

- const title = "Login"
+ const title = "User Login"

如果你想看已经暂存、准备提交的内容,用:

git diff --cached

五、Git 最常见的一套工作流

日常使用 Git,最常见的流程其实非常固定:

修改文件
   ↓
git status
   ↓
git add
   ↓
git commit
   ↓
git push

对应命令通常就是:

git status
git add .
git commit -m "fix: 修复首页布局问题"
git push

更真实一点的终端过程可能长这样:

$ git status
On branch main
Changes not staged for commit:
  modified:   src/home.css

$ git add .

$ git commit -m "fix: 修复首页布局问题"
[main b7c8d9e] fix: 修复首页布局问题
 1 file changed, 8 insertions(+), 2 deletions(-)

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), done.
To github.com:user/repo.git
   a1b2c3d..b7c8d9e  main -> main

如果你只记一句话,就记这个:

先检查,再暂存,再提交,最后推送。

真正熟练以后,你会发现绝大多数日常 Git 操作,都只是在这条主线流程上做变化。


六、分支为什么这么重要

分支(branch)几乎是 Git 最强大的能力。

你可以把它理解成:

从主线拉出一条独立开发线,开发完成后再合并回去。

比如:

main:    A --- B --- C
                  \
feature:           D --- E

此时 feature 分支在独立开发,不会直接污染 main

常用命令:

git branch                   # 查看分支
git switch dev               # 切换分支
git switch -c feature/login  # 创建并切换分支

为什么不建议直接在 main 上做复杂开发?

因为这样更安全:

main
A --- B --- C ------------------

如果直接在 main 上开发:
A --- B --- C --- X --- Y --- Z
               ↑
          半成品也会混进去

如果新开分支:
main     A --- B --- C ----------
                    \
feature              X --- Y --- Z

结论很简单:

  • 小修小补也许可以直接做
  • 但稍微正式一点的功能开发,最好新开分支

七、merge 和 rebase 到底有什么区别

这是 Git 里另一个高频困惑点。

merge

把一个分支的改动合并到当前分支:

git switch main
git merge feature/login

图示:

A --- B --- C -------- M   main
           \        /
            D ---- E      feature/login

特点:

  • 历史完整
  • 比较安全
  • 对新手更友好

rebase

把当前分支接到另一个分支最新提交后面:

git switch feature/login
git rebase main

图示:

原来:
A --- B --- C   main
       \
        D --- E feature

rebase 后:
A --- B --- C --- D' --- E' feature

特点:

  • 历史更直
  • 看起来更整洁

一句话记住:

  • merge:两条线汇合
  • rebase:把支线接到主线末尾

如果你还是新手,优先用 merge 完全没问题。

千万别因为网上有人说 “rebase 更高级”,就强行在还没完全理解的情况下乱用。Git 里最好的操作,不是最炫的那个,而是你能稳定掌控的那个。


八、冲突怎么解决

冲突出现的本质原因很简单:

Git 发现两边都改了同一处,但它不知道该保留谁。

比如:

main 分支:     color = "blue"
feature 分支:  color = "red"

这时候就容易冲突。

冲突文件里通常会看到这样的标记:

<<<<<<< HEAD
当前分支内容
=======
另一个分支内容
>>>>>>> feature/login

你需要做的其实只有几步:

  1. 打开冲突文件
  2. 手动保留最终正确内容
  3. 删除冲突标记
  4. git add 冲突文件
  5. 完成 merge 或 rebase

一个真实点的冲突例子

假设 config.txt 初始内容是:

theme=light

现在:

  • main 改成 theme=blue
  • feature 改成 theme=dark

当你执行:

git merge main

可能会看到:

Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.

这时文件可能变成:

<<<<<<< HEAD
theme=dark
=======
theme=blue
>>>>>>> main

如果你决定保留 theme=dark,那就手动改成:

theme=dark

然后执行:

git add config.txt
git commit -m "merge: resolve conflict in config.txt"

如果是在 rebase 过程中,就换成:

git add config.txt
git rebase --continue

新手最常见的问题有两个:

  • 冲突标记没删干净
  • 改完文件后忘了 git add

如果你只记一句处理原则,那就是:

冲突本质上不是报错,而是 Git 把最终决定权交还给你。


九、远程仓库和 SSH 怎么理解

远程仓库就是托管在 GitHub、Gitee、GitLab 等平台上的仓库。

最常见命令:

git remote -v
git fetch
git pull
git push -u origin main

本地和远程的关系可以这样理解:

你的电脑                         GitHub / Gitee
┌──────────────┐                ┌──────────────┐
│ 工作区        │                │ 远程仓库      │
│ 暂存区        │ -- git push -->│              │
│ 本地仓库      │<-- git pull ---│              │
└──────────────┘                └──────────────┘

如果你不想每次 push 都输密码,建议用 SSH。

生成 SSH key:

ssh-keygen -t ed25519 -C "your_email@example.com"

查看公钥:

cat ~/.ssh/id_ed25519.pub

把它复制到 GitHub / Gitee 的 SSH Keys 页面。

测试连接:

ssh -T git@github.com
ssh -T git@gitee.com

成功时一般会看到欢迎信息。

SSH 这套机制你可以简单理解成:

  • 私钥留在你自己的电脑里
  • 公钥放到平台上
  • 平台通过公钥确认你是不是那台拥有私钥的机器

理解到这一步就够了,日常使用完全没问题。


十、多人协作时,一套很稳的 Git 流程

如果你和别人一起开发,一个非常常见、也很稳妥的流程是:

main
  ↓
拉最新代码
  ↓
新建功能分支
  ↓
开发 + 提交
  ↓
push 到远程分支
  ↓
发起 PR / MR
  ↓
代码审查通过
  ↓
合并回 main

实操命令大致是:

git switch main
git pull
git switch -c feature/login-button

# 修改代码后
git add .
git commit -m "feat: 添加登录按钮"
git push -u origin feature/login-button

然后你在 GitHub / Gitee 页面发起 PR / MR,审查通过后合并。

最后回到本地同步主分支:

git switch main
git pull

如果功能已经完成,也可以把分支删掉:

git branch -d feature/login-button
git push origin --delete feature/login-button

这套流程最大的好处就是:

  • 主分支更稳定
  • 每个功能边界更清晰
  • 更方便 review
  • 更容易回滚

如果你只打算记住一种团队开发方式,那就记这一套,足够用了。


十一、怎么把一个项目同时同步到 GitHub 和 Gitee

这是很多人非常关心的场景。

目标是:

一个项目,一次 git push,同时推送到 GitHub 和 Gitee。

原理其实不复杂:

origin
├─ fetch → GitHub
├─ push  → GitHub
└─ push  → Gitee

也就是说:

  • origin 还是同一个名字
  • 但它可以配置多个 push 地址

配置方法

先添加主远程:

git remote add origin git@github.com:用户名/仓库.git

然后给同一个 origin 配多个 push 地址:

git remote set-url --add --push origin git@github.com:用户名/仓库.git
git remote set-url --add --push origin git@gitee.com:用户名/仓库.git

查看结果:

git remote -v

理想输出类似:

origin  git@github.com:用户名/仓库.git (fetch)
origin  git@github.com:用户名/仓库.git (push)
origin  git@gitee.com:用户名/仓库.git (push)

之后你就可以直接:

git push

它会同时推送到两个平台。

如果 GitHub 和 Gitee 想用不同 SSH key

可以这样生成两个 key:

ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_key
ssh-keygen -t ed25519 -C "gitee" -f ~/.ssh/gitee_key

然后配置 ~/.ssh/config

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_key
    IdentitiesOnly yes

Host gitee.com
    HostName gitee.com
    User git
    IdentityFile ~/.ssh/gitee_key
    IdentitiesOnly yes

这样两个平台就能各用各的 key,互不影响。

对很多同时做国内外同步托管的人来说,这套配置会非常省心。


十二、stash、reset、revert 是最容易混淆的一组命令

stash:临时收起现场

当你代码改到一半,突然要切去处理别的问题,可以用:

git stash
git stash list
git stash pop
git stash apply

可以理解成:

当前改到一半
   ↓
git stash
   ↓
先把现场收起来
   ↓
处理别的事情
   ↓
git stash pop
   ↓
再把现场拿回来

reset:更偏“改历史”

比如撤销最近一次提交,但保留改动:

git reset --soft HEAD~1

如果你执行后再看状态,常见会看到:

On branch main
Changes to be committed:
  modified:   src/login.js

说明提交记录回退了,但内容还在。

revert:更偏“新增一个反向提交”

如果某个提交已经 push 给别人了,更推荐:

git revert 提交ID

因为它不会粗暴改公共历史,而是补一个撤销提交。

简单记:

  • 没 push:优先考虑 reset
  • 已 push:优先考虑 revert

这两条如果你记住了,已经能避开大多数初学者常犯的大坑。


十三、两个非常常见的回滚实战

场景一:刚提交错了,但还没 push

比如你刚提交:

git commit -m "feat: 添加登录页面"

后来发现:

  • 有文件不该提交
  • 提交信息写错了
  • 代码还没改完

这时就可以:

git reset --soft HEAD~1

然后重新整理后再提交。

场景二:已经 push 了,想安全撤回

先看历史:

git log --oneline --graph --decorate

如果你想撤销某次已经推上远程的提交:

git revert a1b2c3d

然后再正常:

git push

这样对团队协作更安全。

很多人第一次接触 Git 的回滚,会本能地想“把错误彻底抹掉”。

但在协作里,更重要的往往不是“看起来没发生过”,而是“安全、可追踪、不会坑到别人”。这也是为什么 revert 在公共历史里通常比 reset 更合适。


十四、最后给你一个真正实用的 Git 最佳实践清单

如果不想每次都踩坑,尽量遵守这几条:

  • 提交信息写清楚
  • 小步提交,不要把很多不相关改动塞进一个 commit
  • 不直接在 main 上做复杂开发
  • 提交前先看 git statusgit diff
  • 已 push 的公共历史,尽量不用 reset 硬改
  • 用 WSL 就尽量一直在 WSL 里操作,别混用 Windows 和 WSL

提交信息可以参考这种格式:

feat: 新功能
fix: 修复问题
docs: 文档更新
refactor: 重构
chore: 杂项维护

真正能让 Git 体验变好的,往往不是更复杂的技巧,而是这些看起来很普通、但长期非常有效的习惯。


十五、把 Git 真正学会,靠的不是背命令

学 Git 最重要的,不是死记硬背,而是建立下面这套理解:

  • 文件先在工作区修改
  • 再进入暂存区
  • 再提交到本地仓库
  • 最后推送到远程仓库

而双平台同步推送的本质,也只是:

  • 一个 origin
  • 多个 push URL
  • 一次 git push
  • 同步多个平台

如果你把这套逻辑真正吃透,后面的命令基本都只是这套模型的展开。

换句话说,真正让你不再怕 Git 的,不是你多背了多少条命令,而是你终于知道每一步到底在操作什么。

如果你过去总觉得 Git 难,不一定是你学不会,而是很多资料一上来就在讲命令,却没有先把底层逻辑讲透。

当你真正理解工作区、暂存区、本地仓库、远程仓库之间的关系后,Git 就不会再是一堆零散指令,而会变成一套你能掌控的工具。

这时候你再看 addcommitmergerevert,它们就不再只是需要死记硬背的命令,而是整条协作流程里各自承担职责的一环。

真正让你不再怕 Git 的,不是你多背了多少条命令,而是你终于知道每一步到底在操作什么。

如果这篇文章对你有帮助,也欢迎收藏、转发,或者留着当你以后排查 Git 问题时的一份长期参考。


十六、附:最常用 Git 命令速记

git status
git add .
git commit -m "说明"
git log --oneline --graph --decorate
git diff
git switch -c 新分支
git merge 分支名
git pull
git push
git stash
git reset --soft HEAD~1
git revert 提交ID

如果你只是想快速查命令,也可以配合这份速查表一起用: