📖 导读:这篇文章面向第一次接触 Git 的新手小白。我会从"版本控制到底是什么"讲起,把每个命令的作用、参数和实际使用场景都讲清楚。对出现的专业名词用
💡 注的形式补充通俗解释,命令都可以直接照抄使用。文末附一张速查表和几个实战场景——其中就包括用 Git 发布本博客的完整流程。
Git 是目前世界上最流行的分布式版本控制系统,由 Linux 之父 Linus Torvalds 在 2005 年创建。无论你是写代码、写博客(比如这个 Hugo 博客就是用 Git 管理并发布到 Cloudflare Pages 的),还是协作写任何文本文件,Git 都能帮你记录每一次修改、随时回到历史版本、和他人协同而不互相覆盖。
💡 注(版本控制系统,Version Control System):你可以把它理解成一个"无限次后悔药 + 时光机"。普通方式改文件,改错了就回不去了;用版本控制,每一次改动都会被存成一个"快照",你随时能回到任何一个历史时刻,也能对比两个时刻之间的差异。
💡 注(分布式 distributed):早期的版本控制系统是"集中式"的——有一台中央服务器存着所有历史,大家改完都传给它。分布式则是每台电脑上都存着完整的版本历史,不依赖中央服务器也能工作,更安全也更灵活。Git 就是分布式的代表。
1. 什么是 Git?为什么需要它?
在没有 Git 之前,人们管理文件版本常常是这样的:
论文.doc
论文-改.doc
论文-最终版.doc
论文-最终版2.doc
论文-真的最终版.doc
论文-打死不改版.doc
这种方式的问题显而易见:文件越来越多、不知道哪个是最新、不知道改了什么、和别人合并修改时一团糟。
Git 解决的正是这些问题。它给你带来的能力是:
- 记录历史:每一次提交(commit)都是一个存档点,能随时回到任意存档点。
- 对比差异:能查看任意两个版本之间改了哪些行。
- 分支并行:可以开一条"分支"去做实验性修改,不影响主干;实验成功再合并回来。
- 协作协同:多人同时开发,各自在本地改,最后通过远程仓库同步合并。
- 备份容灾:代码推送到 GitHub 等远程仓库后,本地丢了也能找回。
💡 注(提交 commit):commit 是 Git 里最核心的动作,意思是"把当前的一组改动正式记录成一个历史版本"。每个 commit 有一个唯一的 ID(一长串哈希字符),记录了谁、什么时候、改了什么、以及一句说明信息。
集中式 vs 分布式
| 类型 | 代表 | 历史存放 | 离线工作 | 服务器挂了 |
|---|---|---|---|---|
| 集中式 | SVN、CVS | 只在中央服务器 | 不行 | 全员瘫痪 |
| 分布式 | Git | 每台电脑都有完整历史 | 可以 | 只影响协作同步,本地照常用 |
2. 安装与初次配置
2.1 安装 Git
Windows:去官网下载安装包:https://git-scm.com/download/win,下载后一路"Next"默认安装即可。安装完成后会自带一个 Git Bash 终端(推荐在 Git Bash 里用 Git,体验最一致)。也可以直接用 PowerShell。
💡 注(GFW 访问提示):git-scm.com 官网在国内访问偶尔较慢,但通常能下到。如果实在打不开,可以用国内镜像站(如清华 TUNA 镜像、阿里云镜像)搜索 Git for Windows 安装包。
macOS:在终端输入 git --version,系统会自动提示安装 Xcode Command Line Tools,按提示装好即可。或用 Homebrew:brew install git。
Linux (Debian/Ubuntu):
sudo apt update
sudo apt install git
安装完成后,验证:
git --version
能打印出版本号(如 git version 2.47.x)就说明安装成功。
2.2 初次配置(必须做一次)
Git 每次提交都会记录"是谁提交的",所以第一次使用前要先告诉 Git 你的名字和邮箱。这台电脑只需配置一次:
git config --global user.name "EricZeng599"
git config --global user.email "EricZeng599@outlook.com"
💡 注(–global 参数):
--global表示"对当前用户的这台电脑上所有仓库生效",配置会写到~/.gitconfig文件里。如果不加--global(即git config user.name "..."),则只对当前这一个仓库生效,会写到仓库里的.git/config。
验证配置:
git config --list
其他几个实用配置(可选):
# 设置默认分支名为 main(新版规范,旧版默认是 master)
git config --global init.defaultBranch main
# 让 git 输出带颜色,更易读
git config --global color.ui auto
# 设置默认文本编辑器(写提交说明时用),可选 nano / vim / "code --wait"
git config --global core.editor "code --wait"
💡 注(main vs master):旧版 Git 创建仓库时默认分支叫
master,2020 年后社区为了使用更中性的词,默认改成了main。GitHub 现在默认也是main。两者技术上一模一样,只是名字不同。本博客用的就是main分支。
3. 核心概念:三个区域(最重要的心智模型)
学 Git 最关键的就是搞懂"三个区域"。一旦理解了它,绝大多数命令都有迹可循。
┌──────────────┐ git add ┌──────────────┐ git commit ┌──────────────┐
│ 工作区 │ ──────────▶ │ 暂存区 │ ──────────▶ │ 版本库 │
│ Working Dir │ │ Staging Area │ │ Repository │
└──────────────┘ └──────────────┘ └──────────────┘
你正在编辑的 下次要打包提交 已正式记录的
文件(硬盘上) 的改动(草稿箱) 历史(存档点)
- 工作区(Working Directory):你能在文件夹里直接看到、用编辑器直接改的文件。就是"正在干活的地方"。
- 暂存区(Staging Area / Index):你用
git add把工作区的改动"放进购物车"的地方。它像一个草稿箱,让你可以挑选"哪些改动要一起打包成一个提交"。 - 版本库(Repository):你用
git commit把暂存区的改动正式记录成历史存档的地方。存在隐藏的.git文件夹里。
💡 注(.git 文件夹):在一个用 Git 管理的文件夹里,会有一个隐藏的
.git子文件夹,Git 把所有的版本历史、配置、分支信息都存在这里。千万别手动改或删这个文件夹,删了就等于把整个项目历史删了。
一个完整改动流程就是这三步:
- 在工作区改文件。
git add把改动放到暂存区(装进购物车)。git commit把暂存区的改动存成版本库里的一个提交(结账存档)。
💡 注(为什么要有暂存区):有时候你一次改了好几个文件,但希望"文件 A 和 B 的改动算一个提交,文件 C 的改动算另一个提交"。暂存区就是让你有选择地分批提交,而不是一股脑全打包。这是 Git 比 SVN 优雅的地方之一。
4. 基础命令:从零记录一次修改
4.1 创建仓库:git init
把一个普通文件夹变成 Git 仓库:
cd my-project # 先进入你的项目文件夹
git init # 初始化,会生成 .git 隐藏文件夹
执行后会提示 Initialized empty Git repository in ...。从此这个文件夹就被 Git 管理了。
💡 注(仓库 repository):被 Git 管理的文件夹就叫"仓库"或"repo"。一个仓库 = 一个项目目录 + 它的
.git历史目录。
4.2 查看状态:git status(最常用,随时敲)
git status
这是你用得最多的命令,随时敲它看看当前是什么情况:哪些文件改了、哪些进了暂存区、哪些还没被 Git 跟踪。它的输出会用颜色和文字明确告诉你下一步该做什么。
On branch main
No commits yet
Changes to be committed: # 已在暂存区,等待 commit
(use "git rm --cached <file>..." to unstage)
new file: README.md
Changes not staged for commit: # 改了但还没 add
(use "git add <file>..." to update what will be committed)
modified: index.html
Untracked files: # Git 完全不认识的新文件
(use "git add <file>..." to include in what will be committed)
notes.txt
4.3 添加到暂存区:git add
git add README.md # 只添加一个文件
git add index.html notes.txt # 添加多个文件
git add . # 添加当前目录下所有改动(最常用)
git add *.md # 按通配符添加所有 .md 文件
git add -p # 交互式逐块挑选(高级,见下注)
💡 注(git add . 的坑):
git add .会把当前目录下所有改动(新增、修改、删除)都加进暂存区,很方便但也可能误加。如果想精细控制,用git add 文件名一个个加,或用git add -p逐块挑选。💡 注(git add -p 交互式暂存):一个文件里可能改了好几处,
-p(patch 模式)会一处一处地问你要不要加进暂存区,适合"一个文件里的改动想拆成两个提交"的场景。新手先了解即可。
4.4 提交:git commit
git commit -m "本次提交的说明"
-m 后面跟一句提交说明(message)。如果不加 -m,Git 会打开编辑器让你写长一点的说明。
# 常见好习惯:一行简短说明
git commit -m "修复登录页面按钮错位 bug"
# 更规范:标题 + 空行 + 详细正文(用多个 -m)
git commit -m "修复登录页面按钮错位 bug" -m "原因是 CSS 的 flex 容器没设置 align-items,在 Safari 下会错位。已修复并补充测试。"
💡 注(提交说明怎么写):好的提交说明能让以后回溯历史时一眼看懂"这次改了啥"。推荐用祈使句,如"修复 XX"“添加 XX"“重构 XX”,而不是"改了点东西”。本博客的提交就是
git commit -m "发布新文章:Git 使用命令完全指南"这种风格。
一步到位的快捷方式:把已跟踪文件的修改直接提交(跳过 add,但只对已跟踪文件有效,新文件还是要先 add):
git commit -am "说明" # 等于 git add 已跟踪文件 + git commit
4.5 查看提交历史:git log
git log # 完整历史
git log --oneline # 每个提交一行(最常用,简洁)
git log --oneline -5 # 只看最近 5 条
git log --graph --oneline --all # 带分支图,看分支合并关系
git log --stat # 额外显示每次提交改了哪些文件、增删几行
git log -p # 额外显示每次提交的具体代码差异
--oneline 的输出大概长这样:
a1b2c3d (HEAD -> main, origin/main) 发布新文章:Git 使用命令完全指南
d4e5f6g 添加 SSH 完全指南
7h8i9j0 init hugo blog: PaperMod + 2 posts
💡 注(HEAD):
HEAD是一个特殊指针,指向"你当前所在的位置"(当前分支的最新提交)。可以理解成"光标"。HEAD -> main表示你现在在 main 分支上、停在 main 的最新提交。💡 注(commit ID):每个提交都有一个唯一 ID,如
a1b2c3d...(完整是 40 位哈希)。--oneline里显示的是前 7 位缩写,日常足够用。
4.6 一个完整的最小流程
mkdir my-project && cd my-project # 建文件夹并进入
git init # 初始化仓库
echo "# 我的项目" > README.md # 创建一个文件
git status # 查看:README.md 是 Untracked
git add README.md # 加入暂存区
git status # 查看:已暂存,等待提交
git commit -m "初次提交:添加 README" # 正式提交
git log --oneline # 查看历史
5. 查看差异与历史详情
5.1 查看差异:git diff
git diff # 工作区 vs 暂存区:看还没 add 的改动
git diff --staged # 暂存区 vs 版本库:看已 add 待 commit 的改动(也叫 --cached)
git diff HEAD # 工作区 vs 版本库:看所有未提交的改动
git diff main feature # 两个分支之间的差异
git diff a1b2c3d d4e5f6g # 两个提交之间的差异
git diff --stat # 只看改了哪些文件、增删几行,不看具体内容
💡 注(diff 输出怎么读):diff 输出里,以
+开头的绿行是新增的,以-开头的红行是删除的,@@行标注的是改动所在的行号位置。
5.2 查看某次提交的详情:git show
git show # 查看最新一次提交的详情(改了什么)
git show a1b2c3d # 查看指定提交的详情
git show --stat a1b2c3d # 只看该提交改了哪些文件
5.3 搜索历史:git log 进阶
git log --author="EricZeng" # 只看某人提交的
git log --grep="修复" # 按提交说明关键词搜
git log --since="2 weeks ago" # 最近两周的
git log -- path/to/file # 只看改动过某文件的历史
git log -S "某个函数名" # 搜索"某段代码被增加或删除"的提交
6. 撤销操作(后悔药)
这是新手最容易迷糊的部分。记住一个原则:改动越靠后(越接近版本库),撤销越要小心。
6.1 撤销工作区的修改:git restore / git checkout --
git restore index.html # 丢弃工作区里 index.html 的未暂存改动(新版推荐)
git checkout -- index.html # 同样效果(旧版写法)
git restore . # 丢弃所有工作区未暂存改动(小心!)
💡 注:这个命令会把文件恢复成暂存区或版本库里的样子,工作区里没提交的改动会永久丢失,不可恢复。用之前确认好。
6.2 把暂存区的改动退回工作区:git restore --staged
git restore --staged index.html # 把 index.html 从暂存区撤回工作区(旧版:git reset HEAD index.html)
git restore --staged . # 撤回所有暂存的改动
改动并不会丢,只是从"已暂存"变回"未暂存",还能继续改或重新 add。
6.3 修改最近一次提交:git commit --amend
# 刚 commit 完发现说明写错了,或漏了文件,不想新增一个提交:
git add 漏掉的文件.txt
git commit --amend -m "新的提交说明" # 用新提交替换最近一次提交
💡 注(–amend 的风险):
--amend会改写历史。如果这个提交已经 push 到远程了,就别再 amend,否则会和远程冲突,需要强制推送,协作时很危险。只对"还没推送的本地提交"用 amend。
6.4 移动分支指针:git reset(谨慎)
git reset 可以把当前分支的指针往回挪到某个历史提交,有三种模式:
git reset --soft a1b2c3d # 指针回退,改动留在暂存区(可重新 commit)
git reset --mixed a1b2c3d # 指针回退,改动退回工作区(默认模式,可省略 --mixed)
git reset --hard a1b2c3d # 指针回退,改动【全部丢弃】(危险!不可逆)
| 模式 | 版本库指针 | 暂存区 | 工作区 |
|---|---|---|---|
--soft |
回退 | 保留 | 保留 |
--mixed(默认) |
回退 | 清空(改动回工作区) | 保留 |
--hard |
回退 | 清空 | 清空 |
💡 注(–hard 是核武器):
git reset --hard会把工作区和暂存区的改动全部永久删除。用之前务必三思。但它不会删除"已经 commit 过"的历史——只要提交过,哪怕被 reset 掉了,也能通过git reflog找回(见 6.6)。
6.5 安全地"反向提交":git revert(推荐用于已推送的提交)
git revert a1b2c3d # 生成一个新提交,内容是"撤销 a1b2c3d 的改动"
和 reset 不同,revert 不会改写历史,而是新增一个"反向操作"的提交。协作中、已推送的提交,用 revert 而不是 reset,更安全。
💡 注(reset vs revert 一句话):
reset是"穿越回去把历史抹掉重来"(改写历史,危险);revert是"在现在这个时间点新增一个撤销操作"(保留历史,安全)。已推送的用 revert,没推送的用 reset。
6.6 救命稻草:git reflog
git reflog # 记录所有 HEAD 的移动,包括被 reset 掉的提交
只要你 commit 过,哪怕后来 reset --hard 把它丢了,git reflog 里还能找到那个提交的 ID,再用 git reset --hard 那个ID 就能救回来。这是 Git 的"终极后悔药"。
7. 分支:并行开发的利器
分支是 Git 最强大的功能之一。它让你可以"不影响主干地去做实验性修改"。
💡 注(分支 branch):分支可以理解成"平行宇宙"。你在 main 分支上稳定开发,同时又开一条
feature-A分支去做新功能实验,两条线互不影响。等feature-A做好了,再把它合并回 main。
7.1 查看分支:git branch
git branch # 查看本地所有分支(* 标记当前所在分支)
git branch -a # 查看所有分支(含远程)
git branch -v # 额外显示每个分支最新提交
7.2 创建 / 切换分支
git branch feature-A # 创建分支 feature-A(但不切换过去)
git switch feature-A # 切换到 feature-A(新版推荐)
git checkout feature-A # 切换分支(旧版写法,同样有效)
git switch -c feature-A # 创建并切换到 feature-A(一步到位,新版)
git checkout -b feature-A # 创建并切换(旧版写法)
💡 注(switch vs checkout):
git checkout是老命令,既能切分支又能恢复文件,容易混淆。Git 2.23 起新增了语义更清晰的git switch(专管切换/创建分支)和git restore(专管恢复文件)。新项目推荐用switch/restore,但checkout仍然完全有效,老教程里全是它。
7.3 合并分支:git merge
git switch main # 先切回要合并到的目标分支(通常是 main)
git merge feature-A # 把 feature-A 合并进当前分支
git branch -d feature-A # 合并完,删掉不再需要的分支(-d 是安全删除)
7.4 变基:git rebase(进阶)
git switch feature-A
git rebase main # 把 feature-A 的提交"嫁接"到 main 最新提交之后
rebase 和 merge 都能合并分支,但方式不同:
merge:保留两条分支的真实历史,生成一个"合并提交",历史是网状的。rebase:把当前分支的提交一个个"重放"到目标分支顶端,历史变成一条直线,更干净,但改写了提交历史。
💡 注(黄金法则):永远不要 rebase 已经推送到公共分支的提交,否则会让协作者的历史混乱。rebase 只用于本地的、没推送过的提交整理。
7.5 解决合并冲突
当两条分支改了同一个文件的同一处,Git 无法自动合并,就会报"冲突(conflict)"。这时你需要手动解决:
git merge feature-A
# Auto-merging index.html
# CONFLICT (content): Merge conflict in index.html
# Automatic merge failed; fix conflicts and then commit the result.
打开冲突文件,会看到:
<<<<<<< HEAD
当前分支(main)的内容
=======
要合并进来分支(feature-A)的内容
>>>>>>> feature-A
你需要:编辑这个文件,决定保留哪部分(或合并两部分),删掉 <<<<<<<、=======、>>>>>>> 这些标记,保存。然后:
git add index.html # 标记冲突已解决
git commit # 完成合并提交
💡 注(冲突不可怕):冲突不是错误,是 Git 在说"这两处改动我拿不准,请你来决定"。解决冲突 = 手动编辑保留想要的内容 + 删标记 + add + commit,就这几步。也可以用编辑器或工具(VS Code 有可视化冲突解决)辅助。
8. 远程仓库:和 GitHub 同步
到目前为止都在本地操作。要和别人协作、或做云端备份,就需要远程仓库。
💡 注(远程仓库 remote):远程仓库就是存放在服务器(如 GitHub、Gitee、GitLab)上的仓库副本。它的作用是"中转站 + 备份":你把本地改动 push 上去,别人从那里 pull 下来。本博客的远程仓库就在 GitHub。
8.1 查看远程:git remote
git remote -v # 查看已配置的远程仓库地址
git remote add origin https://github.com/EricZeng599/my-blog.git # 添加远程并起名 origin
git remote remove origin # 删除远程
💡 注(origin):
origin是远程仓库的默认别名,不是关键字。你可以起别的名字,但大家约定俗成用 origin 指代"主远程仓库"。
8.2 克隆仓库:git clone
把远程仓库整个下载到本地(含全部历史):
git clone https://github.com/EricZeng599/my-blog.git
git clone https://github.com/EricZeng599/my-blog.git my-folder # 克隆到指定文件夹名
💡 注(HTTPS vs SSH 克隆地址):GitHub 仓库有两种克隆地址。HTTPS(
https://github.com/...)每次推送要输用户名和令牌;SSH(git@github.com:...)配置好密钥后免密推送,更方便。新手先用 HTTPS,熟悉后可切 SSH(参考本博客的 SSH 指南配置密钥)。
8.3 推送:git push
把本地提交上传到远程:
git push origin main # 把本地 main 推到远程 origin 的 main
git push -u origin main # 首次推送:-u 设置"上游关联",之后只敲 git push 即可
git push # 已关联上游后,直接推送当前分支
git push origin feature-A # 推送其他分支
💡 注(-u 是什么):
-u(--set-upstream)建立本地分支和远程分支的"绑定关系"。绑定一次后,以后在这个分支里直接git push/git pull不用再写远程名和分支名。首次推送一个分支时建议加 -u。
8.4 拉取:git pull 和 git fetch
git pull # 拉取远程更新并合并到当前分支(= fetch + merge,最常用)
git fetch # 只拉取远程更新到本地,但不合并(让你先看看再决定)
两者区别:
git fetch:只下载远程的新提交到本地,不动你的工作区。下载后你可以git log origin/main看看远程发生了什么,再决定要不要合并。git pull:相当于git fetch+git merge,直接把远程更新合并进当前分支。
💡 注(什么时候要 pull):如果你在多台电脑上操作同一个仓库(比如公司电脑和家里电脑),或者和别人协作,开始干活前先
git pull拉一下最新,能避免"本地落后远程导致 push 被拒绝"。本博客如果你在两台电脑上交替写文章,就要记得 push 之前先 pull。
8.5 推送被拒绝怎么办
如果远程有你本地没有的提交(比如别人推了、或你在另一台电脑推了),你的 push 会被拒绝:
! [rejected] main -> main (fetch first)
解决办法:先 pull 再 push:
git pull # 拉取并合并远程更新
# 如果有冲突,解决冲突后 git add + git commit
git push # 再推送
9. 标签:git tag
标签用来给某个提交打"标记",通常用于标记发布版本(如 v1.0.0)。
git tag v1.0.0 # 给当前提交打轻量标签
git tag -a v1.0.0 -m "正式版 1.0" # 打带说明的附注标签(推荐)
git tag # 列出所有标签
git show v1.0.0 # 查看标签详情
git tag v1.0.0 a1b2c3d # 给指定历史提交打标签
git push origin v1.0.0 # 推送单个标签到远程(tag 不会随 push 自动上传)
git push origin --tags # 推送所有标签
git tag -d v1.0.0 # 删除本地标签
git push origin :refs/tags/v1.0.0 # 删除远程标签
💡 注(轻量标签 vs 附注标签):轻量标签只是一个指向提交的"书签";附注标签(
-a)是 Git 里的一个独立对象,带说明、打标签人、时间等信息,更正式。发布版本建议用附注标签。
10. 忽略文件:.gitignore
有些文件不想让 Git 跟踪(如编译产物、密码文件、系统垃圾文件),用一个 .gitignore 文件列出它们即可。
在仓库根目录创建 .gitignore,内容示例:
# 编译产物
*.exe
*.o
*.class
# 依赖目录
node_modules/
venv/
__pycache__/
# 日志和临时文件
*.log
*.tmp
# 环境变量 / 密钥(千万别提交!)
.env
*.pem
id_rsa
# 系统文件
.DS_Store
Thumbs.db
# 编辑器目录
.vscode/
.idea/
# Hugo 博客的构建输出(本博客就是这么配的)
/public/
/.hugo_build.lock
💡 注(.gitignore 的坑):
.gitignore只对还没被 Git 跟踪的文件生效。如果文件已经被 add + commit 过了,再加进.gitignore不会让它停止跟踪。要先git rm --cached 文件名(从版本库移除但保留本地文件)再提交,之后.gitignore才生效。💡 注(千万别提交密钥):API key、密码、私钥(如
id_rsa、.env)一旦提交并推送到公开仓库,就等于泄露了。GitHub 甚至有机器人实时扫描公开仓库窃取密钥。敏感信息一律写进.gitignore。
11. 实战场景
场景一:把一个现有项目纳入 Git 管理
cd existing-project
git init
git add .
git commit -m "初次提交:导入现有项目"
# 然后到 GitHub 建一个空仓库,复制它的地址,关联并推送:
git remote add origin https://github.com/你的名/项目名.git
git branch -M main # 把当前分支改名为 main(如果原来是 master)
git push -u origin main
场景二:发布本博客(真实流程!)
这正是本博客的日常发布流程——写完一篇 Markdown 文章,推送到 GitHub,Cloudflare Pages 自动构建发布:
# 1. 在 content/posts/ 下写好文章,比如 git-commands-guide.md
cd C:\Users\EricZeng\Desktop\blog\my-blog
# 2. 查看改了什么
git status
# 3. 把新文章加入暂存区
git add content/posts/git-commands-guide.md
# 4. 提交
git commit -m "发布新文章:Git 使用命令完全指南"
# 5. 推送到 GitHub(main 分支),Cloudflare 会自动重新构建发布
git push
约一分钟后,blogvoyant.pages.dev 上就能看到新文章了。这就是 Git + Hugo + Cloudflare 的全自动发布链路。
场景三:误删了文件,想找回
git rm 重要文件.txt # 误删并暂存了
git restore --staged 重要文件.txt # 先撤出暂存区
git restore 重要文件.txt # 再从版本库恢复到工作区
# 或者文件是被 reset --hard 干掉的(已提交过):
git reflog # 找到删除前的提交 ID
git reset --hard 那个ID # 回到那个时间点
场景四:撤销已经 push 到远程的提交
# 不要用 reset --hard 然后强推!会搞乱协作者的历史。
# 用 revert 安全地"反向提交":
git revert 有问题的提交ID
git push # 推送这个撤销提交
场景五:只想暂存一部分改动,另一部分留到下次
git add -p # 交互式逐块选择要暂存的改动
git commit -m "第一批改动"
# 剩下的改动留在工作区,下次再 add + commit
场景六:临时切走去做别的事,手头改动先存起来
git stash # 把工作区改动"藏起来",工作区变干净
git switch main # 切到别的分支干活
# ...干完别的活...
git switch 原分支
git stash pop # 把刚才藏起来的改动恢复回来
💡 注(git stash):stash 像一个"临时抽屉",把没提交的改动塞进去,工作区就干净了,方便你切换上下文。
git stash list看抽屉里有几份,git stash pop取出最近一份。
12. 常见坑与最佳实践
- 提交粒度要小而完整:一次 commit 只做一件事(修一个 bug、加一个功能),别把十件事揉在一个提交里。说明信息写清楚。
- 先 pull 再 push:多人协作或跨设备时,push 前先
git pull,避免冲突和被拒绝。 - 别提交敏感信息:密码、密钥、
.env写进.gitignore。一旦推送到公开仓库,即使后续删除,历史里仍留有记录(需用git filter-branch或 BFG 工具清理)。 - 别用
push --force对公共分支:git push -f会强推覆盖远程历史,会把别人的提交冲掉。只对自己的私有分支用,公共分支用revert。 .gitignore越早建越好:项目一初始化就建好,免得垃圾文件被跟踪后再清理。- commit 前先
git status和git diff --staged:看一眼要提交什么,避免误提交。 - 善用分支:主分支(main)保持稳定可用,新功能在 feature 分支上做,做完合并。
- 已推送的提交不要 amend / reset / rebase:会改写公共历史,用 revert 代替。
13. 命令速查表
| 命令 | 作用 |
|---|---|
git init |
把当前文件夹初始化为 Git 仓库 |
git clone <url> |
克隆远程仓库到本地 |
git status |
查看工作区 / 暂存区状态 |
git add <file> / git add . |
把改动加入暂存区 |
git commit -m "说明" |
把暂存区改动提交成历史版本 |
git log --oneline |
简洁查看提交历史 |
git diff |
查看未暂存的改动 |
git diff --staged |
查看已暂存待提交的改动 |
git show <id> |
查看某次提交的详情 |
git restore <file> |
丢弃工作区的未暂存改动 |
git restore --staged <file> |
把文件从暂存区撤回工作区 |
git commit --amend -m "说明" |
修改最近一次提交(未推送时用) |
git reset --soft <id> |
回退指针,改动留暂存区 |
git reset --mixed <id> |
回退指针,改动回工作区(默认) |
git reset --hard <id> |
回退指针,改动全丢(危险) |
git revert <id> |
生成反向提交(安全撤销,已推送也能用) |
git reflog |
查看所有 HEAD 移动记录(救命稻草) |
git branch |
查看本地分支 |
git branch <名> |
创建分支 |
git switch <名> / git switch -c <名> |
切换 / 创建并切换分支 |
git merge <分支> |
把指定分支合并到当前分支 |
git branch -d <名> |
删除已合并的分支 |
git remote -v |
查看远程仓库 |
git remote add origin <url> |
添加远程仓库 |
git push -u origin main |
首次推送并关联上游 |
git push |
推送当前分支到远程 |
git pull |
拉取并合并远程更新 |
git fetch |
拉取远程更新但不合并 |
git tag -a v1.0 -m "说明" |
打附注标签 |
git stash / git stash pop |
临时藏起 / 恢复改动 |
git config --global user.name "..." |
设置全局用户名 |
git config --global user.email "..." |
设置全局邮箱 |
14. 学习建议
- 先用起来再深究:掌握
init / status / add / commit / log / push / pull这七个性命命令,就能应付 80% 的日常。其余的用到再查。 - 每个命令加
--help:如git commit --help会打开该命令的完整手册。 - 遇到冲突别慌:就是手动编辑保留想要的内容、删标记、add、commit。
- 多用
git status:它是你的指南针,随时敲它看下一步该干嘛。 - 图形化工具辅助:VS Code 自带 Git 支持、GitHub Desktop、Sourcetree、GitKraken 等可视化工具能降低心智负担,但底层还是这些命令,理解命令后用工具更得心应手。
💡 最后一句话:Git 的学习曲线前陡后平。三个区域、提交、分支、远程这几个概念吃透后,剩下的就是查参数。别怕犯错——只要你 commit 过,
git reflog都能救你回来。多在本地试验,很快就能上手。
祝版本控制愉快!🎉