一篇讲透 Git:从原理到实战,顺手搞定 GitHub / Gitee 双平台同步
很多人学 Git,卡住的从来不是命令太多,而是一直没真正理解 Git 在做什么。于是
add、commit、merge、rebase、reset、revert看起来都会,一到真实场景就容易乱。这篇文章会用一条清晰主线,把 Git 最核心的原理、最常用的工作流、分支与冲突处理、回滚思路,以及 GitHub / Gitee 双平台同步一次讲透。看完之后,你不只是会敲命令,而是真的知道每一步到底在操作什么。
很多人学 Git,卡住的从来不是命令不够熟。
真正难的,往往是这些时刻:
- 不知道
git add到底在干嘛 - 暂存区总是似懂非懂
merge、rebase、reset、revert一到实战就乱- 想同步 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 add 和 git 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 addUntracked 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
你需要做的其实只有几步:
- 打开冲突文件
- 手动保留最终正确内容
- 删除冲突标记
git add 冲突文件- 完成 merge 或 rebase
一个真实点的冲突例子
假设 config.txt 初始内容是:
theme=light
现在:
main改成theme=bluefeature改成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 status和git diff - 已 push 的公共历史,尽量不用
reset硬改 - 用 WSL 就尽量一直在 WSL 里操作,别混用 Windows 和 WSL
提交信息可以参考这种格式:
feat: 新功能
fix: 修复问题
docs: 文档更新
refactor: 重构
chore: 杂项维护
真正能让 Git 体验变好的,往往不是更复杂的技巧,而是这些看起来很普通、但长期非常有效的习惯。
十五、把 Git 真正学会,靠的不是背命令
学 Git 最重要的,不是死记硬背,而是建立下面这套理解:
- 文件先在工作区修改
- 再进入暂存区
- 再提交到本地仓库
- 最后推送到远程仓库
而双平台同步推送的本质,也只是:
- 一个
origin - 多个
push URL - 一次
git push - 同步多个平台
如果你把这套逻辑真正吃透,后面的命令基本都只是这套模型的展开。
换句话说,真正让你不再怕 Git 的,不是你多背了多少条命令,而是你终于知道每一步到底在操作什么。
如果你过去总觉得 Git 难,不一定是你学不会,而是很多资料一上来就在讲命令,却没有先把底层逻辑讲透。
当你真正理解工作区、暂存区、本地仓库、远程仓库之间的关系后,Git 就不会再是一堆零散指令,而会变成一套你能掌控的工具。
这时候你再看 add、commit、merge、revert,它们就不再只是需要死记硬背的命令,而是整条协作流程里各自承担职责的一环。
真正让你不再怕 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
如果你只是想快速查命令,也可以配合这份速查表一起用: