
🔥keyipatience:个人主页
🎬作者简介:C/C++后端开发学习者
🌟专栏传送门:《c++》《linux》《c++高阶数据结构》《c++数据结构与算法》《前端学习》
⭐️patience is key in life
Git 撤销修改
情况 1:只改了文件,没有 add(修改只在工作区)
文件改坏了,还没 add,想撤销这一轮改动,恢复到最近一次 add /commit 的样子 命令:
git checkout -- ReadMe
# 新版git等价推荐写法
git restore ReadMe
重点:-- 不能省! 如果写成 git checkout ReadMe,git 会理解成【切换到名叫 ReadMe 的分支】,含义完全变了。
作用: 直接把工作区的改动抹掉,文件变回暂存区 / 版本库里保存的样子,刚才新增的内容直接消失。
风险:这个操作直接丢掉你工作区的修改,无法找回,谨慎使用!
情况 2:已经 add,但是还没有 commit(修改在暂存区)
你已经 git add ReadMe,修改进到暂存区了,现在后悔,想撤出来 分两步走:
先把修改从暂存区撤回到工作区
git reset HEAD ReadMe
# 等价 git reset --mixed HEAD ReadMe,--mixed是默认参数,可以省略
//底层理解HEAD:代表当前最新的 commit 版本库快照,因为还有没有commit所以回退到当前最新的commit版本就是把 暂存区(stage)清空
执行后效果:
暂存区清空 文件的内容不变!改动重新回到工作区
接下来二选一:
- 改一改,重新
git add - 不想要了,用
git checkout -- ReadMe/git restore ReadMe删掉工作区改动
情况 3:已经 add + commit(修改提交进版本库了)
已经 commit,生成一条版本记录,现在想要撤销这次提交
重要前提:这个 commit 还没有 push 推送到远程仓库! 如果已经 push 到远端,不能随便用
--hard回退!(后面学远程会讲)
命令:
git reset --hard HEAD^
HEAD^当前版本的上一个 commit--hard:同时改动三处:版本库指针、暂存区、工作区 执行完:HEAD 指针挪到上一个版本,暂存区清空,工作区直接变成上个版本的样子,本次 commit 写的内容本地消失。
一张汇总表
| 场景 | 状态 | 目标 | 命令 |
|---|---|---|---|
| 1 | 修改仅在工作区,未 add | 丢掉工作区修改 | git checkout -- 文件名 / git restore 文件名 |
| 2 | 已经 add,未 commit | 取消暂存(退回工作区) | git reset HEAD 文件名 |
| 2 续 | 取消暂存后,想彻底删掉修改 | 丢掉工作区修改 | git checkout -- 文件名 |
| 3 | add + commit,未 push 远程 | 回退到上一个版本,删掉本次提交 | git reset --hard HEAD^ |
Git 删除文件
在 git 眼里,删除文件 = 也是一种修改,需要 add /commit 记录这个删除动作
直接用 linux 的 rm file5(只删工作区)
rm file5
效果:
- 本地磁盘(工作区)file5 删掉了
- 版本库、暂存区里还保留这个文件
git status提示:deleted: file5(红色,Changes not staged for commit)
问题:git 只是发现你在本地删了,但是还没有把 "删除这件事" 登记到版本库里。 现在分两条路:删错了 | 确实要删掉
情况 A:删错了!想要恢复回来
刚才只是 rm file5,还没执行 git rm、没 commit 用之前学过的撤销工作区修改命令:
git checkout -- file5
# 新版等价:git restore file5
从版本库把 file5 拿回来,恢复到工作区,ls 又能看到 file5 了。
情况 B:确实想要把文件从版本库删掉
git rm file5
它一次性做两件事:
- 删除工作区的 file5(如果还在的话)
- 把【删除 file5】这个动作加到暂存区
git rm≠ linux 的 rm linux rm:只动本地磁盘,git 不知情 git rm:同时操作工作区 + 暂存区,告诉 git:我要删除这个文件此时如果还要恢复就要 git reset HEAD --hard才行
然后必须 commit,这个删除才正式写入版本库:
git commit -m "deleted file5"
文件已经加到暂存,想只从暂存区删掉、本地保留(不是真删文件)
git rm 会把本地的文件也一起删除
git rm --cached file5
- 本地磁盘 file5 还在
- 只把它从暂存区 / 版本追踪里移除(一般用来取消跟踪,比如误 add 了大文件)
Git 分支基础
分支 = 平行宇宙
主线(master)是一条时间线;从某个提交点分出新分支,就开出一条独立时间线,分支之间互不干扰,可以在不同分支写不同代码,后面还能合并。
例子:master 主线正常开发;开新分支写新功能,写完再合并回主线。
master和HEAD
master指向最新提交HEAD指向当前所在分支(只有一个)
master 是主分支指针 ,指向这个分支上最新的一次提交 。每 commit 一次,master 就自动向后移动一步。HEAD 是当前所在分支的标记, 先指向 master,再由 master 指向最新提交。
HEAD → master → 最新提交

Git 创建分支
git branch # 查看本地所有分支,带 * 的是当前分支
git branch dev # 新建 dev 分支(只创建,不切换过去)
执行完 git branch dev 之后:
-
分支列表:
dev、* master→*代表 HEAD 当前在 master -
去
.git/refs/heads/目录下看:会多出一个dev文件ls .git/refs/heads/
cat .git/refs/heads/*
master 和 dev 两个文件里存的 commit hash 值一模一样 ,说明:刚创建出来的 dev 和 master 指向同一个提交节点


git branch dev只是新增一个指针,不会复制文件、不会新建提交,非常轻量,这是 Git 分支高效的核心原因。
Git 切换分支 + 分支独立提交
切换分支命令
git checkout dev
# 等价新版推荐写法:git switch dev
执行后输出:Switched to branch 'dev'
-
查看分支:
git branch,*跑到 dev 前面,代表当前分支是 dev -
底层验证 HEAD:
cat .git/HEAD
输出 ref: refs/heads/dev
原理:HEAD 指针移动,指向 dev 分支
原理图变化:HEAD → dev,master 指针还停留在原来那个提交上不动。

在 dev 分支做修改并提交
vim ReadMe # 修改文件,新增一行 write aaa for new branch
git add .
git commit -m "modify ReadMe"
提交成功提示:[dev 274bdce] modify ReadMe
- 这个提交只会让 dev 分支指针向前移动一步
- master 指针原地不动,不会跟着更新
底层查看两个分支指向的 commit 哈希:
cat .git/refs/heads/dev # 拿到新的 commit id(刚提交的)
cat .git/refs/heads/master # 还是原来旧的 commit id
核心:两个分支指针现在指向不同提交节点,两条分支历史开始分叉

切回 master 分支,现象:新增内容消失
git checkout master
注意:如果dev 改了文件,不 add、不 commit,切回 master,新加内容还在!
因为这个改动还没有存入 Git 的版本库,不在任何分支、不在任何提交里,它只躺在你的本地工作目录。 Git 在切换分支的时候:
- 先检查:工作区有没有未暂存、未提交的修改
- 如果:切换前后的两个分支,这个文件没有版本差异 Git 就不会覆盖你的改动,直接把这份修改保留、带到目标分支
查看 ReadMe:刚才新增那一行不见了! 再切回去 dev:
git checkout dev
ReadMe 新增内容又回来了
为什么会这样?
- 这次提交是在 dev 分支上做的,master 分支根本没有包含这次提交;
- 切换到 master 时,Git 将工作区恢复成 master 指向的那个旧提交对应的文件版本;
- 切换回 dev,Git 又把工作区换回 dev 最新提交的文件快照。
Git 合并分支(Fast-forward 快进合并)
承接前面流程:dev 分支比 master 多了一次提交,现在要把 dev 的改动合并进 master。
整套命令流程
git branch # 查看当前分支,现在在 dev
git checkout master # 先切到 master,合并是【把别的分支合并到当前分支】
git merge dev # 将 dev 合并到 master
输出关键信息:
Updating 16623e1..3740dce
Fast-forward
ReadMe | 1 +
1 file changed, 1 insertion(+)
查看 ReadMe:master 里面也出现了 dev 新增的那一行内容。
重点规则:
git merge [分支名]的含义:把指定分支合并到【你现在所在的分支】,所以合并前一定要先切到目标分支(这里是 master)。
Fast-forward(快进模式)是什么
原理图变化: 合并前:
- master 停在旧提交点
- dev 在 master 的正前方,顺着一条线往前走了一次提交
快进合并的时候:Git 不产生新的提交记录,只是直接移动 master 指针(所以我们不好区分到底是merge让指针移动一步还是在master分支上commit一次让指针移动),让 master 指向和 dev 同一个提交节点。

所以快进合并没有生成新提交 ,merge 命令执行完就结束了,不用再敲 git commit。
Git 删除分支
命令
git branch -d dev
d = --delete,安全删除分支。
两个硬性规则
**1.不能删除当前所在的分支 * 例子:现在在 dev(* dev),执行 git branch -d dev
error: Cannot delete branch 'dev' checked out at 'xxx'
2.正确做法:先切到别的分支(一般切 master/main),再删
git checkout master
git branch -d dev
-d 安全删除的底层限制
git branch -d 是安全模式:Git 会检查:这个分支的所有提交,是不是已经被别的分支合并、能访问到了。
- 像如果:dev 已经合并进 master → 可以
-d删除 - 如果 dev 独有的提交,还没有合并进主分支,直接
-d会拒绝删除,防止你丢提交!
大写 -D 强制删除(危险!)
git branch -D dev
-D = --delete --force
不管分支有没有合并、有没有独有的提交,直接删掉分支指针。
Git 鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在 master 分支上工作效果是一样的,但过程更安全。
即:
- 开发新功能、改 bug:新建 dev 分支干活
- 测试没问题,合并到主分支 master
- 合并完成,dev 使命结束,删除它 好处:master 全程保持干净稳定,开发过程中的错误、半成品不会污染主分支
