Git学习(2)撤销与分支操作全指南

🔥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

它一次性做两件事:

  1. 删除工作区的 file5(如果还在的话)
  2. 把【删除 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 全程保持干净稳定,开发过程中的错误、半成品不会污染主分支
相关推荐
数字新视界2 小时前
模块化机房的设计与实施原理剖析
大数据·物联网·信息可视化·信息与通信·一体化机柜
用户3610588626123 小时前
Flink 注册Slot源码深度剖析:从TaskManager注册到Slot状态机的完整链路
大数据·flink
一线数智3 小时前
来腾讯云AI开放日 加入人类职业进化计划
大数据·人工智能·腾讯云
loulanyue_3 小时前
机器换人不是终点,混合智能体重塑制造范式:从自主四要素到组织扁平化破局——读周济李培根院士2026东湖论坛国际智能制造创新论坛演讲实录
大数据·人工智能·制造
西索斯coding4 小时前
Qwen3-Max 与 Qwen-Plus:60 个真实修复任务评测方案
大数据·网络·算法·ai
龙亘川4 小时前
适应人工智能发展、构建就业友好型发展方式
大数据·运维·人工智能·信息可视化·智慧城市
加洛斯4 小时前
万字推演Elasticsearch修炼方法,从炼气到元婴
后端·elasticsearch·面试
瓶瓶持续学习中4 小时前
数字孪生与空间智能技术架构解析:五类厂商路线及选型方法
大数据·网络·架构
实验室管理云平台4 小时前
某国家重点实验室应用经费合同管理系统,实现经费实时监控
大数据·人工智能