Git 从入门到顺手 —— 版本控制看这一篇就够了

0 阅读12分钟

📌 声明:本文由作者独立整理编写,内容涵盖 Git 核心概念与日常操作指南,旨在为开发者提供一份清晰实用的 Git 速查手册。文章结构清晰、示例详实,适合从零开始的初学者,也适合需要随时查阅的熟手。


为什么你需要 Git?

想象一下这个场景:你正在写一个项目,今天加了个功能,跑得挺好。明天改了个配置,突然全崩了。你疯狂地 Ctrl+Z,发现回不去了……😭

或者更经典的——你和同事同时改一个文件,他改完上传,你改完上传,后上传的那个人把前一个人的覆盖了。俩人一整天白干。

Git 就是来解决这些问题的。

一句话概括:Git 是给代码做"存档"和"时间旅行"的工具 —— 让你随时可以回到任意历史版本,让多人协作变得井然有序。


🎯 Git 到底能做什么?

  • 版本控制 —— 每一次提交都是一次存档,随时可以回退
  • 备份同步 —— 推送到云端(GitHub/GitLab/Gitee),不怕本地硬盘坏了
  • 多人协作 —— 各改各的,合并时有冲突也能清晰解决
  • 分支管理 —— 并行开发多个功能,互不干扰
  • 追踪修改记录 —— 每一行代码谁写的、什么时候写的、为什么写的,清清楚楚

🧭 学习路线建议

别想一口吃成胖子。Git 命令很多,但日常用的就那几个

按照这个顺序学,效率最高:

  1. 先看「基本工作流程」+「查看历史」 —— 这两块够你日常开发用了
  2. 再看「分支用法」 —— 独立开发新功能时必须会
  3. 「撤销操作」只遇到问题时再翻 —— 不用提前背,知道有这些功能就行

📌 标 ⭐ 的是天天用的,其他遇到再查。


🧱 核心概念(先混个脸熟)

概念解释🍳 生活比喻
仓库(Repository)Git 管理的项目文件夹📦 档案室
工作区(Working Directory)你正在修改的文件📝 书桌
暂存区(Staging Area)git add 后的文件,准备提交🎒 书包
提交(Commit)一次正式存档,记录谁、什么时候、改了什么📸 存档快照
分支(Branch)从主线分叉的独立开发线🌌 平行宇宙
HEAD当前指向哪个版本的指针🧭 "你站在哪里"

⭐ 基本工作流程(天天用)

日常开发就这四步。第一步只在项目开始时做一次,后面三步每天循环。

# ========== 第0步:初始化仓库(只做一次)==========
git init                    # 在当前文件夹初始化一个 Git 仓库

# ========== 日常循环(天天做)==========
# 1. 改代码 ✏️
# 2. 添加到暂存区
git add .                   # . 表示添加所有改动,也可以指定具体文件名
# 3. 提交存档
git commit -m"feat: 添加用户登录功能"   # -m 是 message 缩写
# 不加 -m 会弹出一个文本编辑器让你写提交信息
# ========== 首次推送到云端(只做一次)==========
git remote add origin https://github.com/你的用户名/仓库名.git
git push -u origin master   # -u 是记住关联,以后直接 git push 就行

# ========== 之后推送(日常用)==========
git push                    # 因为 -u 记住了关联,直接敲
# ========== 从云端拉取最新代码(每天开始工作前)==========
git pull                    # 把队友的更新拉到本地

⭐ 查看历史和状态(救命用的)

当你忘了改了什么、想确认当前状态时:

git log --oneline           # 一行一条,简洁查看提交历史
# 输出示例:
# cf478d2 (HEAD -> master) feat: 添加 GPL 协议
# 40a5731 fix: 修复登录超时问题
# 2837804 init: 项目初始化

git log --oneline -5        # 只显示最近5条
git status                  # 查看当前状态:哪些改了、哪些暂存了

⚠️ 重要提醒git log 只显示从 HEAD 往历史方向能追溯到的提交。如果你用 git reset 回到了旧版本,被跳过的提交不会再出现在 git log 里——但提交本身还在,30 天内可以用提交 ID 找回。


🧭 HEAD 与版本导航(跳转必备)

当需要回到旧版本看看、或在版本间跳转时,先看这张图:

提交历史(从旧到新):

  2837804        40a5731        cf478d2
    ○     ←       ○      ←       ○  ← HEAD → master
  (第1次)       (第2次)        (第3次,你在这里)
    ↑              ↑              ↑
  HEAD~2         HEAD~1         HEAD(当前位置)
  HEAD^^         HEAD^

📌 关键概念速览

写法含义
HEAD当前所在位置
HEAD^上一个版本(父提交)
HEAD^^上上个版本
HEAD~2HEAD^^ 等价,数字更直观
HEAD~5往前数第 5 个版本

🔀 切换版本

# 切换到某个分支(正常开发)
git switch 分支名            # ✅ 推荐(Git 2.23+)
git checkout 分支名          # 旧版写法

# 切换到某个具体提交(进入"游离状态")
git checkout 提交ID          # 比如 git checkout cf478d2

⚠️ 游离 HEAD(detached HEAD)是什么?

当你 git checkout 提交ID 跳到某个具体提交时,HEAD 直接指向提交而不是分支。这时候你可以浏览旧代码,但不要在这里做新提交——否则新提交没有挂在任何分支上,很容易"迷路"。

# ❌ 不推荐:在游离状态下做新提交
git checkout cf478d2
git add .
git commit -m"在旧版本上改了点东西"   # 这个提交不在任何分支上!

# ✅ 正确姿势:基于旧版本创建新分支
git switch -c 新分支名 提交ID        # 基于旧提交建新分支,安全!
git switch master                    # 回到最新正常状态

🌿 分支基本用法(独立开发必备)

当你想尝试新功能又不想影响主线代码时,开个分支就对了。

# ========== 创建分支 ==========
git branch 分支名              # 只创建,不切换
git switch -c 功能名           # ✅ 创建并切换过去(推荐)

# ========== 查看所有分支 ==========
git branch                     # 当前分支前有 * 标记

# ========== 切换分支 ==========
git switch 分支名

# ========== 合并分支 ==========
git switch master              # 先切到目标分支(比如 master)
git merge 要合并的分支名        # 把其他分支的改动合并进来

# ========== 删除分支(合并完后清理)==========
git branch -d 分支名

📌 分支命名建议

分支名用途
main / master稳定版本,随时能跑
dev日常开发分支
feature/xxx某个具体功能(如 feature/login
fix/xxx修复某个 bug(如 fix/overflow

💡 工作流:新功能开新分支 → 写完测试通过 → 合并回 master → 最后删掉分支。这样 master 始终保持稳定。


↩️ 撤销操作(出问题了再翻)

撤销操作不要按"命令名"学,要按 "我想干嘛" 来找。

⚠️ 但在动手之前,先搞清楚这些命令都偷偷依赖了什么。

🔑 关键前提(必读!)

每个撤销命令背后都藏着一个**"恢复到哪"**的逻辑:

git restore 文件 / git checkout -- 文件
→ Git:好,找一下这个文件的最新版本……
→ 暂存区里有 → 恢复到暂存区里的版本(不是 HEAD!)
→ 暂存区没有 → 退而求其次,恢复到 HEAD 版本
→ HEAD 还没指向任何提交(项目还没 commit 过)→ 报错!

git restore --staged 文件
→ Git:把暂存区恢复到 HEAD 版本
   (这个才是从 HEAD 恢复)

📋 前提速查表

前提影响的命令后果
至少有一次 commitgit checkout --git restore(丢弃模式)、git resetgit log没有 commit = 没有"旧版本"可恢复,全部报错
暂存区还未清空git restore 文件git checkout -- 文件恢复到的是暂存区版本,不是 HEAD!
HEAD 指向的位置git reset 的移动基准、git restore --staged 恢复来源HEAD 指向哪,这些就"撤到哪"
暂存区没有东西restore --stagedgit reset 文件暂存区空的,撤了也白撤
文件曾经提交过git checkout -- 文件git restore 文件新建后从未 commit 的文件,Git 没有它的旧版本

🔥 每次操作前,先 git status 看一眼! 它能告诉你:当前在哪个分支、什么文件改了、什么文件暂存了。


第一层:撤销暂存(git add 后悔了)

你已经 git add 了文件,但还没提交,想拿出来重新改。文件内容不变,只是撤出暂存区。

# ✅ 新版(推荐)
git restore --staged 文件名      # 撤销单个文件
git restore --staged .           # 撤销全部

# 旧版写法
git reset 文件名                 # 单文件
git reset HEAD                   # 全部清空暂存区

前提:暂存区里确实有这个文件。如果暂存区是空的,执行也不会有任何变化。


第二层:丢弃工作区修改(文件改坏了)

文件改了半天发现不对,想扔掉修改。⚠️ 修改无法找回!

# ✅ 新版(推荐)
git restore 文件名
# restore 不加 --staged,默认就是作用于工作区(文件本身)

# 旧版写法
git checkout -- 文件名
# ↑ -- 是分隔符,强制告诉 Git "后面是文件名"

为什么需要 -- 因为 checkout 有双重身份:

  • git checkout 分支名 → 切换分支
  • git checkout -- 文件名 → 恢复文件

如果不加 --,Git 会优先匹配分支名,匹配不到才当文件名。

🔥 常见坑

场景结果
暂存区有东西,直接 git restore 文件恢复到的是刚刚 add 的版本,等于白干
正确做法git restore --staged 文件 清暂存区,再 git restore 文件
一步到位git restore --source=HEAD 文件
新建的文件(从未 commit 过)restore / checkout -- 全部报错 ❌
已删除的文件可以从 HEAD 版本恢复回来 ✅

第三层:撤销提交(commit 后悔了)

已经 git commit 了,想撤回。这里需要 git reset,它有三个模式:

改文件 → git add → git commit
                    ↑          ↑
                  --mixed    --soft
                  撤到这      撤到这

--hard → 全回退,代码也变回旧版本
模式HEAD暂存区工作区适用场景
--soft后移保留保留只撤 commit,代码还在暂存区,随时重交
--mixed(默认)后移清空→掉回工作区保留撤 commit+add,代码还在文件里
--hard后移销毁还原旧版全部回退,代码也被干掉 ⚠️
git reset --soft HEAD^      # 方案1:撤但保留一切,适合合并多个零碎提交
git reset --mixed HEAD^     # 方案2:撤 commit+add,从头整理(可省略 --mixed)
git reset --hard HEAD^      # 方案3:全撤,慎用!

🔥 常见坑

  • 只有1次提交时,HEAD^ 不存在:项目的第一个提交没有父提交,git reset HEAD^ 会报错
  • git reset 不加参数 = git reset --mixed HEAD:跟版本时等于原地不动;跟文件名时只操作该文件
  • --soft 必须跟目标:不跟会报错,没有默认值
  • reset 回旧版本后,git log 只显示当前位置往前的提交:被跳过的提交不显示,但还在(30天内可用 ID 找回)

💡 --hard 能找回来吗?

能! 如果你记得被删版本的提交ID,可以用 git reset --hard 提交ID 找回。

原理:reset --hard 只是"拔掉指针",珠子还在。只有 Git 垃圾回收(约30天后)才会真正清理。

reset 的两种用法对比

怎么用HEAD效果
git reset 目标版本后移撤销提交(上面三种模式)
git reset 文件名不动只撤销该文件的 add
git reset --soft 文件名不允许!--soft 不能跟文件
git reset --hard 文件名不动⚠️ 直接覆盖该文件,慎用!

第四层:从历史版本恢复

不同于第二层(恢复到 HEAD),这一步可以恢复到任意历史提交的版本。

# ✅ 新版
git restore --source=提交ID 文件名

# 旧版写法
git checkout 提交ID -- 文件名

和第二层的区别:第二层默认从暂存区/HEAD 恢复,而这层明确指定 --source / 提交ID不受暂存区干扰,直接恢复到任意历史版本。

注意:这个操作只改工作区的文件内容,不改暂存区、不改 HEAD。文件变成旧版本后,你可以 git add + git commit 把旧版本当作新提交。


📊 撤销速查总表

我想干嘛✅ 推荐(新版)旧版等价
撤销单个文件 addgit restore --staged 文件git reset 文件
撤销全部 addgit restore --staged .git reset HEAD
丢弃文件修改git restore 文件git checkout -- 文件
双重还原(add+修改都撤)git restore --staged --worktree 文件git checkout HEAD -- 文件
撤 commit,代码保留git reset --soft HEAD^
撤 commit+add,代码保留git reset --mixed HEAD^
彻底回退git reset --hard HEAD^
从旧版本取回文件git restore --source=ID 文件git checkout ID -- 文件

📝 规律总结

  • reset 管"提交层面"(动 HEAD)
  • restore 管"文件层面"(不动 HEAD)
  • 新版用 switch(换分支)+ restore(恢复文件),职责清晰
  • 旧版 checkout 两个都管,容易混淆

✨ 好习惯(少踩坑)

  • 小步提交 —— 每改一个小功能就交一次,不要攒一大堆
  • Commit Message 写清楚 —— 好:"feat: 修复登录闪退" / 差:"修bug"
  • 新功能开新分支 —— 不在 master 上直接改
  • 每天开始先 git pull —— 避免冲突堆积
  • .gitignore 排除不需要管理的文件

📄 .gitignore 示例

在项目根目录新建 .gitignore 文件,写入:

node_modules/    # 第三方依赖包(太大,不用管)
.env             # 环境变量(可能含密码,不能上传)
*.log            # 日志文件
dist/            # 编译输出
.DS_Store        # macOS 系统文件

这样 git add . 时会自动跳过这些文件 🎉


🗺️ 场景速查总表

学完了记不住?遇到问题回来翻这个表:

我遇到了什么怎么办频率去哪查
想用 Git 管项目git init工作流程
写好了,想存档git add .git commit -m"xxx"工作流程
忘了改了什么git status / git log --oneline查看历史
想试新功能,又怕搞砸git switch -c feature/xxx常用分支用法
分支写好了,合回去git switch mastergit merge feature/xxx常用分支用法
文件改坏了,想扔掉git restore 文件偶尔撤销-第二层
add 多了,想拿几个出来git restore --staged 文件偶尔撤销-第一层
commit 了才发现有 buggit reset --soft HEAD^偶尔撤销-第三层
彻底不想要最近的修改git reset --hard 提交ID罕见⚠️撤销-第三层
从旧版本抄代码回来git restore --source=ID 文件罕见撤销-第四层
备份到云端git push常用工作流程
换电脑继续写git clone 仓库地址罕见
拉取队友更新git pull常用工作流程

📚 写在最后

Git 是一个工具,不是考试。没有人能背下所有命令,连用了十年的老手也经常 git --help

💡 核心心法:记住 addcommitpush 这个流程,记住 statuslog 可以帮你查状态,剩下的遇到问题再查就好。

把这篇文章收藏起来,遇到问题回来翻翻,比死记硬背管用一万倍 🚀

有什么问题欢迎评论区交流,我会持续补充完善!