惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
C
Check Point Blog
博客园 - Franky
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
V2EX - 技术
V2EX - 技术
AI
AI
Hacker News - Newest:
Hacker News - Newest: "LLM"
Jina AI
Jina AI
S
Security @ Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
H
Hacker News: Front Page
H
Hackread – Cybersecurity News, Data Breaches, AI and More
O
OpenAI News
Attack and Defense Labs
Attack and Defense Labs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
爱范儿
爱范儿
H
Heimdal Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
G
Google Developers Blog
G
GRAHAM CLULEY
V
V2EX
The Register - Security
The Register - Security
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
Schneier on Security
Schneier on Security
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
Help Net Security
Help Net Security
大猫的无限游戏
大猫的无限游戏
C
CERT Recently Published Vulnerability Notes
The GitHub Blog
The GitHub Blog
V
Vulnerabilities – Threatpost
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
S
Secure Thoughts
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
量子位
NISL@THU
NISL@THU
K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
T
Threatpost
Recent Commits to openclaw:main
Recent Commits to openclaw:main
宝玉的分享
宝玉的分享
Security Latest
Security Latest
T
The Exploit Database - CXSecurity.com
博客园_首页
A
Arctic Wolf

博客园 - xiashengwang

Rocky Linux 9 安装docker Rocky Linux 9 与Centos区别,以及软件安装dnf命令 《Linux 基础点滴》:(17)SSH 密钥生成与管理 – 免密登录的利器 Linux服务器安全登录:从入门到实践 putty 基础 《Linux 基础点滴》:(16)firewalld 防火墙管理命令 《Linux 基础点滴》:(15)用户管理 – 创建、删除、权限与 sudo 《Linux 基础点滴》:(14)定时任务 – 用 crontab 自动化 《Linux 基础点滴》:(13)文本编辑入门 – 使用 Vim 《Linux 基础点滴》:(12)tldr – 简化版命令手册 《Linux 基础点滴》:(11)系统信息与资源监控 – 掌握服务器状态 《Linux 基础点滴》:(10)压缩与打包 – tar 的艺术 《Linux 基础点滴》:(9)查找与过滤 – find, grep, 管道 《Linux 基础点滴》:(8)网络基础 – 查看 IP、连通性与端口 《Linux 基础点滴》:(7)进程管理 – 查看与控制运行中的程序 《Linux 基础点滴》:(6)文件权限与所有者 – 保护你的文件 《Linux 基础点滴》:(5)文件与目录操作 – 增删改查必会命令 《Linux 基础点滴》:(4)磁盘空间查看 – df 和 du 的妙用 《Linux 基础点滴》:(3)Linux 文件系统概览 – 一切皆文件 《Linux 基础点滴》:(2)SSH 连接与基础命令 – 从登录到第一次操作 《Linux 基础点滴》:(1)初识 Linux 大家族 – 发行版分类与选择 docker学习(7)-docker compose 文件 docker学习(11)- 容器的日志(log) docker学习(10)-利用Github Action 自动化部署 docker学习(9)-Docker Swarm + Nginx 跨机器负载均衡 docker学习(8)-从 Windows 开发到 Linux 部署 docker学习(6)-数据持久化与网络通信 学会 Git Tag,让版本管理不再混乱 docker学习(5)-Dockerfile docker学习(4)-Docker常用命令 docker学习(3)-一个简单的例子 docker学习(2)-安装 docker学习(1)-基本概念 Github 使用 Self-hosted Runner 实现服务器自动化部署 github创建分支 + Pull Request 合并 Git Rebase vs Git Merge:深入理解与实战选择 AI学习笔记(2)-OpenClaw安装 windbg分析dmp文件 docker desktop 和 Vmware冲突的解决办法
Git 系统学习教程:从零到团队协作
xiashengwang · 2026-04-15 · via 博客园 - xiashengwang

备注:Deepseek帮助下整理的学习内容。

看到 Git 报错就慌,这几乎是每个开发者都会经历的阶段。别担心,这不完全是基础不牢,更多是因为 Git 设计了一个复杂的 “三区(工作区-暂存区-版本库)模型” ,我们常常对命令执行的“副作用”感到未知和失控。

要打破这种不确定性,关键在于先理解这个三区模型,把抽象的 Git 命令和文件实际的状态变化对应起来,然后再去反复练习那些最核心、最常用的指令。

下面是一套完整的 Git 学习路线,我们一起从底层原理开始,逐步构建自信。

第一部分:准备工作与核心原理

1.1 安装与配置

  • 下载安装: 访问 Git 官网 下载最新版,Windows 用户建议安装 Git Bash。
  • 全局配置(最重要的一步): 设置用户名和邮箱,这是你代码的“身份证”,会记录在每一次提交里。这个邮箱和用户名仅仅是用作提交的标记,让团队知道是谁提交的修改,和github的认证没有任何关系,填错也不影响提交。 请在命令行中执行:
git config --global user.name "你的GitHub用户名"
git config --global user.email "你的GitHub注册邮箱"

你可以用 git config --global --list 来查看所有配置。

  • SSH 密钥: 为方便后续与 GitHub 交互,建议配置 SSH 免密登录。请按顺序执行:
ssh-keygen -t rsa -b 4096 -C "你的邮箱"
cat ~/.ssh/id_rsa.pub

将输出的公钥完整复制,然后添加到 GitHub 的 Settings → SSH and GPG keys → New SSH key 中。

1.2 核心概念与三个区域

Git 的核心工作流围绕着 工作区、暂存区、版本库 这三个区域展开,理解它们是避免混乱的基础。

  • 工作区 (Working Directory): 电脑里能看到的项目文件夹,你对文件的修改都在这里。
  • 暂存区 (Staging Area / Index): 一个临时存放的“待办清单”。git add 就是将工作区的修改放入暂存区,准备提交。
  • 版本库 (Repository): git commit 会将暂存区的修改打包成一个永久快照(commit)保存到版本库,并生成一个唯一的 SHA-1 哈希值(例如 f3b7c5d)作为标识。

1.3 单人项目基础操作

现在,我们来创建一个新项目,把这些命令和概念串联起来。

graph TD subgraph 本地 A[工作区 Working Directory] -- "git add" --> B[暂存区 Staging Area]; B -- "git commit" --> C[本地仓库 Local Repo]; end C -- "git push" --> D[远程仓库 GitHub]; D -- "git pull" --> C;

  1. 初始化项目与首次提交
mkdir git-practice
cd git-practice
git init                     # 初始化本地仓库
echo "# My Git Practice" > README.md
git status                   # 查看状态,文件标红表示未跟踪
git add README.md
git status                   # 文件变绿,表示已进入暂存区
git commit -m "first commit"
  1. 关联并推送到 GitHub
  • 在 GitHub 上创建一个同名空仓库(不要勾选 README),复制仓库地址。
git remote add origin git@github.com:你的用户名/git-practice.git
git branch -M main # 强制修改本地分支名master为main。本地git默认建立的默认分支名是master,而github上默认是main。
git push -u origin main      # 首次推送,-u 会建立关联。下次可以分支下直接用“git push”省略后面的参数推送。

关联后的分支,可以直接用简写命令git push推送。

  • 查看本地分支是否和服务器分支的关联
    git branch -vv
    这样就代表没有关联
    image
    关联了会显示origin/xxx。
    image

  • 如何手动设置远程分支和本地分支的关联?
    2种方法,在push的时候加-u
    git push -u origin main(推荐)
    或者
    git branch --set-upstream-to=origin/远程名 本地名

  • 取消本地分支和服务器分支的关联。
    git branch --unset-upstream

  • 如果本地分支名和github分支名不一样,每次推送需要带上本地名:远程名,不是很方便,所以尽量保证本地分支和服务器分支名一致:

#git push origin 本地名:远程名
git push origin master:main
  1. 查看历史与修改记录
git log --oneline            # 简洁地查看提交历史
git diff                     # 查看工作区与暂存区的差异
git diff --staged            # 查看暂存区与上次提交的差异
git show <commit-id>         # 查看某次提交的具体改动

第二部分:团队协作与分支模型

团队协作的本质,就是每个人在自己的分支上独立开发,最后通过合并请求(Pull Request / Merge Request)将功能安全地合入主分支。

2.1 为什么要用分支

分支提供了一个独立的环境,让你在开发新功能时完全不会干扰到 main(或 aster)分支上的稳定代码。这对于团队协作至关重要。

2.2 推荐分支模型:GitHub Flow

这是非常适合团队的标准模式。你可以在我们之前的项目 flask-ci-demo 中创建 dev 分支,然后开始练习:

git checkout -b dev             # 从 main 分支创建并切换到 dev 分支
git push origin dev             # 将 dev 分支推送到远程仓库

这个模型只有一条长期分支 main,所有开发都在短期分支上进行:

  1. main 拉出新分支:git checkout -b feature/add-login
  2. 在分支上开发、提交。
  3. 推送分支到 GitHub:git push origin feature/add-login
  4. 发起 Pull Request (PR),指定团队成员进行代码审查。
  5. 审查通过后,合并到 main 分支。
  6. 删除已合并的功能分支。

2.3 常用分支命令

git branch                     # 列出本地所有分支,当前分支前有 * 号
git branch -a                  # 列出本地和远程所有分支
git checkout main              # 切换到 main 分支
git checkout -b feature-xyz    # 创建并切换到新分支 feature-xyz
git branch -d feature-xyz      # 删除本地分支 feature-xyz(需先切换出去)
git push origin --delete feature-xyz  # 删除远程分支

第三部分:冲突解决实战

冲突是 Git 协作中最常见的拦路虎,但只要理解它,解决起来并不难。

3.1 冲突的产生与标准解决流程

当两个人修改了同一文件的同一区域,Git 无法自动决定保留谁的,便会抛出冲突。处理步骤如下:

  1. 发现冲突:执行 git mergegit pull 后,会看到类似 Automatic merge failed; fix conflicts 的提示。
  2. 定位冲突:执行 git status 查看哪些文件处于 both modified 状态。
  3. 解决冲突:手动打开冲突文件,查找 <<<<<<<, =======, >>>>>>> 标记。
    • <<<<<<< HEAD======= 之间是当前分支(接收方)的代码。
    • =======>>>>>>> branch-name 之间是另一分支(合并方)的代码。
    • 你需要手动删除这些标记,并决定最终保留的代码。可以参考这个示例流程:
# 在执行git merge后出现冲突,你想撤销此次合并,回到自己合并前的代码就用下面的命令
git merge --abort

# 解决冲突后,标记为已解决并完成合并
git add <冲突文件>
git commit -m "Merge branch 'feature-branch' into main"

3.2 模拟冲突实验

  1. 创建两个分支并修改:
git checkout -b feature-a main
echo "Line from feature A" > test.txt
git add test.txt && git commit -m "Add file from A"

git checkout main
git checkout -b feature-b main
echo "Line from feature B" > test.txt
git add test.txt && git commit -m "Add file from B"
  1. 模拟并发提交:
git checkout main
git merge feature-a   # 第一次合并成功
git merge feature-b   # 第二次合并时会产生冲突
  1. 解决冲突:
    打开 test.txt,按规则修改,然后继续:
git add test.txt
git commit -m "Merge feature-b and resolve conflict"

第四部分:回滚与撤销

很多人在面对复杂历史时不敢操作,核心是没分清场景。牢记这个原则:如果代码已经推送到远程,优先用 git revert;如果仅在本地,可用 git reset

4.1 场景区分与工具选择

使用场景 命令选择 原理 安全性
撤销本地修改(未 add) git restore <file> 用版本库的版本覆盖工作区 安全,无法恢复
撤销暂存区修改(已 add,未 commit) git restore --staged <file> 把文件从暂存区撤回工作区,修改保留 非常安全,文件不变
撤销本地提交(未 push) git reset --soft HEAD~1 撤销 commit,但保留修改 需谨慎,历史已变
撤销已推送的提交 git revert <commit-hash> 创建一个新提交来抵消旧提交 最安全,推荐

4.2 核心命令详解

git revert (最推荐)
原理: 通过创建一个新的 提交 来撤销某个历史提交的更改,是公共协作中最安全的操作。

用法:

# 先找到要撤销的 Commit ID
git log --oneline

# 使用 revert 创建一个反向提交来撤销它
git revert <commit-id>

# 推送到远程
git push origin main

git reset (需谨慎使用)

  • 原理: 直接移动 HEAD 指针到指定位置,历史会被修改。
  • 三种模式:
    • --soft:只撤销 git commit,修改保留在暂存区。
    • --mixed(默认):撤销 git addgit commit,修改保留在工作区。
    • --hard:危险! 完全丢弃所有修改,回到指定版本状态。

用法:

# 撤销最近一次提交,保留修改在工作区
git reset --soft HEAD~1

# 撤销最近3次提交,并丢弃所有修改(非常危险!)
git reset --hard HEAD~3

# 如果已经推送,必须强制推送(严禁在公共分支上执行)
git push --force-with-lease

紧急救援:git reflog
当你用 reset --hard 误删了提交,git reflog 是你最后的救命稻草,它记录了所有 HEAD 的移动历史。

用法:

git reflog
# 假设找到目标 Commit ID 是 abc1234
git reset --hard abc1234

4.3 实战演练:从错误中恢复

为了让你彻底掌握回滚与撤销,请在一个全新的、无风险的练习目录中按步骤操作。

步骤 1:创建一个新的 Git 仓库并模拟正常提交

cd ~/Desktop   # 或任意安全目录
mkdir git-rollback-practice
cd git-rollback-practice
git init

# 创建文件并提交 v1
echo "Version 1" > app.txt
git add app.txt
git commit -m "v1: initial app.txt"

# 提交 v2
echo "Version 2" >> app.txt
git commit -am "v2: add version 2 line"

# 提交 v3(最终正确版本)
echo "Version 3" >> app.txt
git commit -am "v3: add version 3 line"

# 查看提交历史
git log --oneline

此时历史应该有三条提交,假设它们的 ID 分别为 1111111 (v1), 2222222 (v2), 3333333 (v3)。

步骤 2:模拟错误提交(不小心提交了错误内容)

echo "This is a BUG" >> app.txt
git commit -am "BUG: wrong change"

现在有四个提交,最新的那个是错误提交。

步骤 3:使用 git reset 撤销本地错误提交(未推送)
假设你还没有推送到远程,想撤销最后一次提交但保留修改在工作区:

git reset --soft HEAD~1
git status

你会看到 app.txt 仍处于“Changes to be committed”状态(即暂存区)。你可以再次修改 app.txt,然后重新提交正确的版本。
主要的应用场景:

  • 发现写错了提交的message,重新git commit -m "新的注释",快速上传。
  • 发现前面3次改修都是同一个bug修改,想合并成一次提交可以:git reset --soft HEAD~3,然后git commit 提交。
  • 发现只有个别文件需要修改一行代码,修改后,可以单独git add 修改的文件,然后 git commit 快速上传。
  • 总之,如果git reset HEAD~1的话,那么全部的修改都要add一遍,然后git commit

如果想完全丢弃最后一次提交的所有修改(危险):

git reset --hard HEAD~1
git log --oneline   # 错误提交已经消失

步骤 4:模拟“已推送的错误提交”并使用 git revert 安全修复

# 重新制造一个错误提交并推送到远程(先添加一个远程仓库,例如 GitHub 上的空仓库)
git remote add origin git@github.com:你的用户名/git-rollback-practice.git
git branch -M main
git push -u origin main

# 现在制造一个错误提交
echo "Another bug" >> app.txt
git commit -am "BUG: another wrong change"
git push origin main

此时远程仓库已经包含了这个错误提交。要修复它,且不破坏公共历史:

# 找到错误提交的 commit ID
git log --oneline

# 使用 revert(假设错误提交 ID 是 a1b2c3d)
git revert a1b2c3d
# Git 会打开编辑器让你输入撤销的提交信息,按Esc,输入:wq保存并退出(其实是个vim)
git push origin main

现在查看远程仓库,你会发现多了一条“Revert”的提交,而历史中错误提交仍然存在,但已被逻辑撤销。这是团队协作中最安全的方式。

步骤 5:紧急救援——使用 git reflog 找回丢失的提交
假设你不小心执行了 git reset --hard HEAD~2,丢掉了两个提交。不要慌!

git reflog

你会看到一列 HEAD 移动记录,例如:

3333333 HEAD@{0}: reset: moving to HEAD~2
4444444 HEAD@{1}: commit: BUG: another wrong change
5555555 HEAD@{2}: commit: BUG: wrong change
...

找到你想要的提交 ID(例如 4444444),然后:

git reset --hard 4444444

丢失的提交就回来了。

我不要本地的新改动了,就让本地完全跟远程一样。
注意: 它会“丢弃”你本地未提交的修改和未推送的提交(如果有的话),所以别在有重要未提交改动时乱用。

# 1. 先把远程的最新信息拉下来
git fetch origin

# 2. 把本地 main 强行指到“跟 origin/main 一样”
git reset --hard origin/main

第五部分:常见场景速查与命令表

场景化命令速查

我想做的事... 命令
场景一:修代码
拉取最新代码 git pull origin main
把工作区的文件加入暂存区 git add <file> (或 git add . 添加所有)
把暂存区的修改提交到本地仓库 git commit -m "feat: 添加了xxx功能"
推送本地提交到远程仓库 git push origin main
场景二:代码冲突
合并时遇到冲突,想直接放弃合并 git merge --abort
解决冲突后,标记为已解决并完成合并 git add <file>git commit
场景三:撤销修改
放弃工作区所有未暂存的修改 git restore .
撤销暂存区的所有文件 git restore --staged .
场景四:版本回滚
安全撤销已推送的提交 git log --oneline (查ID) → git revert <commit-id>git push
撤销本地最近3次提交,但保留修改 git reset --soft HEAD~3
紧急恢复误删的提交 git reflog (找ID) → git reset --hard <commit-id>

常用命令速查表

分类 命令 作用
初始化与配置 git init 在当前目录创建一个新的 Git 仓库。
git clone <url> 克隆一个远程仓库到本地。
git config --global user.name "Your Name" 设置全局用户名。
基础操作 git status 查看工作区和暂存区的状态。
git add <file> 将指定文件加入暂存区。
git commit -m "message" 将暂存区的改动提交,并附上信息。
git push origin <branch> 将本地分支推送到远程仓库。
git pull origin <branch> 拉取远程分支的更新并与本地合并。
分支与合并 git branch 列出本地所有分支。
git checkout -b <branch> 创建并切换到一个新分支。
git merge <branch> 将指定分支合并到当前分支。
撤销与回滚 git restore <file> 丢弃工作区的修改。
git reset HEAD~1 撤销最近一次提交,改动回到工作区。
git revert <commit-id> 安全地撤销一个已推送的提交。
查看历史 git log --oneline 以一行的形式查看简洁的提交历史。
git diff 查看工作区与暂存区的差异。
git reflog 查看 HEAD 的移动历史,用于找回丢失的提交。

总结:从“用命令”到“用流程”

学好 Git,核心在于完成从“死记命令”到“理解流程”的转变。

  • 基础操作:深刻理解 工作区 → 暂存区 → 版本库 这个“三区模型”,所有的命令都是在这三个区域间移动数据。
  • 团队协作:遵循 PR + Code Review 的标准工作流,是保证代码质量和团队有序协作的核心。
  • 解决冲突:冲突不是灾难,而是沟通的契机。掌握标准的冲突解决流程,从“害怕冲突”转变为“从容解决”。
  • 版本回滚:牢记 git revert 用于远程git reset 用于本地 的原则。万一误操作,git reflog 是你最后的救星。
  • 提交规范:使用清晰的提交信息(如 feat:, fix: 前缀),不仅能让历史清晰,也便于未来高效地回滚。