Git 命令图解手册:写给实习生的 30 个高频命令

你以为自己在用 Git,其实你只是在用 add / commit / push。当你遇到分支冲突、reset --hard、误删文件时手足无措,说明你还没真正"看见"Git 内部的运作。

这篇博客的核心目的:用图把每个命令的作用讲清楚。建议你打开终端,跟着博客的命令一起敲一遍。


为什么需要图示?

很多 Git 教程是这么写的:

git reset --hard HEAD~1 表示回退到上一个版本。

你看完之后依然不知道会发生什么——是只动版本库?工作区的文件还在不在?我改了一半的代码会不会丢?

Git 的所有命令,本质上都是操作"对象":commit、分支指针、工作区文件、暂存区文件。图示能让你直接看到这些对象怎么变,比任何文字描述都清楚。

本博客约定:

  • * 表示一个 commit 节点
  • 括号里的 (HEAD -> main) 表示 HEAD 指针和 main 分支指针都指向这里
  • 箭头 表示命令的方向
  • ⚠️ 标记代表危险操作

入门:理解 Git 的三个区域

这是全篇的基石,所有命令都围绕这三个区域运作

区域含义类比
工作区(Working Directory)你实际编辑的文件办公桌上的草稿
暂存区(Stage / Index)准备提交的文件"中间站"待提交的文件夹
版本库(Repository)已提交的历史记录归档柜
┌─────────────┐     git add      ┌─────────────┐    git commit     ┌─────────────┐
│             │ ──────────────► │             │ ───────────────► │             │
│  工作区      │                 │   暂存区     │                  │   版本库     │
│ (Working)   │ ◄────────────── │  (Stage)    │                  │ (Repository)│
│             │   git checkout   │             │                  │             │
└─────────────┘                  └─────────────┘                  └─────────────┘
        ▲                                                                  │
        │                                                                  │
        └──────────────── git reset ──────────────────────────────────────┘

记住这张图,所有 Git 命令都是在这个图上画箭头。接下来每个命令都对应到这张图上。

辅助命令:

  • git status:看三个区域分别有什么文件
  • git diff:看工作区和暂存区的差异
  • git diff --staged:看暂存区和版本库的差异

第一章:基础工作流

1. git init — 初始化仓库

git init

把当前目录变成 Git 仓库(生成一个隐藏的 .git 文件夹)。

之前:                 之后:
my-project/            my-project/
├── src/               ├── .git/         ← 新增
├── README.md          ├── src/
└── main.py            ├── README.md
                       └── main.py

2. git clone <url> — 克隆远程仓库

git clone https://github.com/xxx/yyy.git

把远程仓库完整下载到本地(包含所有历史、分支、tag)。

3. git add <file> — 添加到暂存区

git add hello.txt       # 添加指定文件
git add .               # 添加当前目录所有变更
之前(hello.txt 是红色):       之后(hello.txt 是绿色):
工作区: hello.txt (未跟踪/修改)   工作区: hello.txt
暂存区: (空)                     暂存区: hello.txt  ← 新增
版本库: (旧版本)                 版本库: (旧版本)

4. git commit -m "msg" — 提交到版本库

git commit -m "feat: add login page"

把暂存区的内容保存为一个 commit,永久进入版本库。

每次 commit 都会生成一个节点:
*  c3 (HEAD -> main)  feat: add login page
*
*  c2                  fix: button style
*
*  c1                  init project

⚠️ 注意commit 只提交暂存区的内容。如果改了文件但没 add,改的内容不会被提交。

5. git log — 查看提交历史

git log                    # 详细
git log --oneline          # 简洁模式
git log --oneline --graph  # 图形化显示分支
$ git log --oneline --graph
* 8f3a21d (HEAD -> main) feat: add login page
* 3b2c109 fix: button style
* a1d4e88 init project

6. git push / git pull — 与远程同步

git push origin main    # 推送到远程 main
git pull origin main    # 拉取并合并远程 main
本地:  * c3 (HEAD -> main)      ← git push ───►  远程:* c3 (origin/main)
       *                              ◄── git pull ──  *
       * c2                                      * c2

7. .gitignore — 忽略文件

# .gitignore
target/
*.log
.idea/
.DS_Store

被忽略的文件不会出现在 git status 中,也不会被误提交。


第二章:分支管理(重点)

1. 核心认知:分支就是一个指针

很多人误以为"分支是一份代码拷贝"。不对。在 Git 里,分支只是一个指向某个 commit 的可移动指针,非常轻量。

              ┌── * c4 (feature)   feature 分支指针
              │
* c3 (HEAD -> main)                main 分支指针 + HEAD
*
* c2
*
* c1

2. git branch 系列

git branch                  # 查看所有本地分支
git branch feature-x        # 创建分支(指针指向当前 commit)
git branch -d feature-x     # 删除已合并的分支
git branch -D feature-x     # ⚠️ 强制删除(未合并也会删)

3. git checkout / git switch — 切换分支

git switch feature-x        # 推荐写法(语义清晰)
git checkout feature-x      # 老写法,也能切换分支
切换前:              切换后:
* c3 (HEAD -> main)   * c3 (HEAD -> feature-x)  ← HEAD 移动到 feature
|
* c2
|
* c1

4. git merge — 合并分支

合并有两种情况,结果完全不同

情况 a:快进合并(Fast-forward)

当 feature 分支没有"分叉"时(main 没新提交),合并只是把 main 指针前移。

合并前:                合并后:
* c4 (feature)          * c4 (HEAD -> main, feature)  指针前移
*
* c3 (main)
*
* c2
*
* c1
情况 b:三方合并(生成 merge commit)

当两个分支都有新提交时,Git 会生成一个特殊的 merge commit。

合并前:                       合并后:
      * c4 (feature)                * c5 (HEAD -> main)  merge commit
      |                            |\
* c3 (main)                    * c4 (feature)
|                                |
* c2                          * c3
|                                |
* c1                          * c2
                               |
                            * c1

5. git rebase — 变基

rebase 把当前分支的所有提交"摘下来",在目标分支的最新 commit 后面重新播放一遍。结果是一条直线

merge 后的历史(分叉):            rebase 后的历史(一条直线):
* c5 (merge)                       * c4' (HEAD -> feature)
|\                                 * c3'
* c4 (feature)                     * c2
|                                  * c1
* c3 (main)
|
* c2
|
* c1

什么时候用哪个?

场景推荐
团队协作的共享分支(如 main)merge(保留分叉历史)
自己的本地 feature 分支rebase(让历史更干净)

⚠️ 黄金法则永远不要对已经推送到远程的 commit 做 rebase,否则团队成员会陷入混乱。

6. 冲突解决

当两个分支改了同一文件的同一行,Git 会停下来让你手动解决:

<<<<<<< HEAD
这是 main 分支的写法
=======
这是 feature 分支的写法
>>>>>>> feature

解决步骤:

  1. 手动编辑文件,决定保留哪一段(或者合并)
  2. 删除 <<<<<<<=======>>>>>>> 标记
  3. git add <file> 标记冲突已解决
  4. git commit 完成合并

第三章:版本回退与恢复(最容易翻车)

1. git reset — 移动 HEAD 指针

⚠️ reset 会改写历史,已经 push 到远程的 commit 不要轻易 reset

reset 有三种模式,对应不同的"破坏力":

模式HEAD 移动暂存区重置工作区重置适用场景
--soft撤销 commit,但保留改动想重新提交
--mixed(默认)撤销 commit + 撤销 add,文件改动保留在工作区
--hard⚠️ 彻底回退,所有未提交的改动全丢
执行 git reset --hard HEAD~1 后:

之前:                        之后:
* c3 (HEAD -> main)           * c2 (HEAD -> main)  ← HEAD 回退
*                              *
* c2                          * c1
*                              *
* c1                          (c3 在 reflog 里还能找到)

⚠️ --hard 是不可逆的吗? 不一定,见后面的 git reflog

2. git revert — 安全的撤销

reset 是"删除历史",revert 是"新增一个反向 commit"。已 push 的提交撤销用 revert,不要用 reset

reset(删除 c3):              revert(新增 c3' 反向修改):
* c4                            * c4' (HEAD -> main)  新提交
*                               *
* c3 (被删除)                   * c3  ← 还在
*                               *
* c2                            * c2
*                               *
* c1                            * c1

用法:

git revert <commit-hash>
# 撤销 merge commit 时需要指定主分支:
git revert -m 1 <merge-commit-hash>

3. git stash — 暂存未提交的修改

场景:你正在改代码,突然需要切换分支处理紧急 bug,但当前改动还没写完不想 commit。

git stash                # 把当前工作区和暂存区的改动暂存起来
git stash pop            # 恢复最近一次 stash
git stash list           # 查看所有 stash
git stash drop stash@{0} # 删除指定 stash
git stash 后:              git stash pop 后:
工作区: (干净的旧版本)      工作区: (你的改动回来了)
暂存区: (空的)             暂存区: (你的改动)
版本库: (最新 commit)      版本库: (最新 commit)

4. git reflog — 救命稻草

reflog 记录了 HEAD 的所有移动。即使你 reset --hard 把 commit “弄丢了”,只要 reflog 还有记录,就能找回来。

场景:你误执行了 git reset --hard HEAD~5,5 个 commit 没了

$ git reflog
a1b2c3d (HEAD -> main) HEAD@{0} reset: moving to HEAD~5   ← 当前
f6e7d8c HEAD@{1} commit: feat: xxx    ← 这就是丢失的 commit
...

恢复方法:

git reset --hard f6e7d8c   # 把 HEAD 指回那个 commit

结论:reset --hard 不是 100% 不可逆,只要你还记得用 reflog

5. 误删文件恢复

# 工作区误删了 hello.txt,从版本库恢复:
git restore hello.txt              # Git 2.23+ 推荐
git checkout -- hello.txt          # 老写法

# 文件已被 add 到暂存区,想从暂存区撤回到工作区(未删):
git restore --staged hello.txt

第四章:多人协作与企业实战

1. 远程仓库相关

git remote -v                  # 查看远程仓库地址
git remote add origin <url>    # 添加远程仓库
git fetch origin               # 拉取远程所有信息(不合并)
git pull origin main           # 拉取并合并(= fetch + merge)
git push origin feature-x      # 推送本地分支到远程

2. git fetch vs git pull 的区别

很多人把这两个混着用,结果分支莫名其妙多了些 commit。

fetch:只是把远程的提交"下载"到本地,不影响你的工作
远程 main: * c5
            |
本地 main: * c4
            ↓ git fetch 后
本地 main: * c4  (main 指针没动)
            ↓ 但出现了一个 origin/main 指针
origin/main: * c5

pull:fetch + merge,本地 main 直接前进
本地 main: * c5 (HEAD -> main, origin/main)  ← 已经合并了

3. git tag — 版本标签

git tag v1.0.0                    # 给当前 commit 打标签
git tag -a v1.0.0 -m "release"    # 附注标签(推荐)
git push origin v1.0.0            # 推送标签到远程
git tag -d v1.0.0                 # 删除本地标签

常用于版本发布:v1.0.0v1.1.0-beta

4. git cherry-pick — 挑选特定 commit

场景:main 分支有个紧急修复,你想把那个 commit 单独拿到 release 分支上,但又不想合并整个分支。

从 feature 挑选 c3 到 main:

feature 分支:                  main 分支:
* c5                            * c3' (HEAD)  ← 新增,是 c3 的副本
|                               |
* c4                            * c2
|                               |
* c3 ←── cherry-pick ──►        * c1
|
* c2
|
* c1

用法:

git cherry-pick <commit-hash>
git cherry-pick <hash1> <hash2>      # 一次挑多个
git cherry-pick --abort              # 放弃 cherry-pick

5. 协作最佳实践

main(master)
  │
  ├── develop(开发主分支)
  │     ├── feature/login      功能开发
  │     ├── feature/payment
  │     └── feature/refund
  │
  └── hotfix/xxx               紧急修复
  • main:只用来发布稳定版本,绝不直接提交
  • develop:日常开发集成
  • feature/xxx:每个新功能一个分支,完成后 merge 回 develop
  • hotfix/xxx:紧急 bug 修复,从 main 拉,修复后同时合回 main 和 develop
  • 合并必须经过 PR/MR 评审

第五章:救命命令速查

┌─────────────────────────────────────────────────────────────┐
│  场景                              命令                     │
├─────────────────────────────────────────────────────────────┤
│  撤销 git add                      git restore --staged <f>  │
│  撤销工作区修改                    git restore <f>           │
│  修改最近一次 commit 信息          git commit --amend        │
│  找回 reset --hard 丢的 commit     git reflog                │
│  撤销已 push 的 commit             git revert <hash>         │
│  撤销未 push 的 merge              git reset --hard HEAD~1   │
│  撤销已 push 的 merge              git revert -m 1 <hash>    │
│  暂时保存改动                      git stash                 │
│  恢复保存的改动                    git stash pop             │
│  强制推送到远程(⚠️ 慎用)         git push -f               │
│  放弃当前合并                      git merge --abort         │
│  放弃当前 rebase                   git rebase --abort        │
└─────────────────────────────────────────────────────────────┘

⚠️ 核心警告

  • 绝对不要在 master/main 上 force push(除非团队所有人都明确知道)
  • 任何 reset --hard 之前,先看一眼 git statusgit diff,确认没未保存的改动
  • 已 push 的提交,优先用 revert,不要用 reset

结尾:Git 命令全景图

最后给你一张图,把所有命令都串起来:

                    ┌──────────────────────────────────────┐
                    │           远程仓库 (origin)          │
                    │                                      │
                    │  * c5 (origin/main)                  │
                    └───────────────┬──────────────────────┘
                                    │ git fetch / git pull
                                    │ git push
                                    ▼
┌─────────────┐  git add    ┌─────────────┐  git commit  ┌──────────────────────────────┐
│             │ ──────────► │             │ ───────────► │           版本库              │
│  工作区      │             │   暂存区     │             │                              │
│ (Working)   │             │  (Stage)    │             │  * c4 (HEAD -> main,         │
│             │ ◄────────── │             │             │  │    feature)                │
│             │ git restore │             │             │  * c3                       │
└─────────────┘             └─────────────┘             │  * c2                       │
        ▲                                                 │  * c1                       │
        │ git stash / git checkout                       │                              │
        │                                                 │  分支:main、feature、hotfix │
        └─────────────────────────────────────────────────└──────────────────────────────┘

  历史查看:git log / git reflog
  撤销安全:git revert
  撤销危险:git reset(--soft / --mixed / --hard)
  跨分支搬运:git cherry-pick / git rebase

记住这张图,你就掌握了 Git 的"心法"。剩下要做的,就是多敲、多踩坑、多用 reflog 救命

真正的 Git 高手,不是记住了多少命令,而是脑子里随时能画出一张分支图,清楚每个指针指向哪里

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐