Git 工具使用之项目版本回退与修改备份:stash、reset、reflog 常用指令详解

在项目开发中,我们经常需要将代码恢复到某个历史版本。但工作区里可能还有尚未提交的修改,直接回退容易导致代码丢失。

一个比较稳妥的操作流程是:

  1. 查看仓库当前状态;
  2. 使用 git stash 备份未提交修改;
  3. 使用 git reset --hard 回退到指定提交;
  4. 验证回退结果;
  5. 必要时恢复之前暂存的修改。

一、查看当前仓库状态

进入项目目录:

复制代码
cd 项目目录

查看当前分支、已修改文件和未跟踪文件:

复制代码
git status

简洁显示:

复制代码
git status --short

常见状态标记:

标记 含义
M 文件已修改
A 文件已加入暂存区
D 文件已删除
?? 未被 Git 跟踪的文件或目录

查看当前提交:

复制代码
git rev-parse HEAD

查看最近几次提交:

复制代码
git log --oneline -5

其中 -5 表示只显示最近 5 条提交记录。

二、确认目标提交是否存在

回退前,可以检查目标提交哈希是否有效:

复制代码
git rev-parse --verify "65f2d202ad1feb4c786616018e5681a8338236c0^{commit}"

如果指令输出提交哈希,说明该提交存在;如果提示 fatal,说明提交不存在于当前仓库,或者哈希输入错误。

三、使用 git stash 备份未提交修改

执行:

复制代码
git stash push -m "回退前备份"

这条指令会:

  • 保存已跟踪文件中尚未提交的修改;
  • 包括暂存区和工作区中的修改;
  • 将这些文件恢复到当前提交对应的状态;
  • 为备份添加说明"回退前备份"。

-m 用来给这次 stash 添加备注,方便以后识别。

stash 保存在哪里?

stash 保存在当前项目的本地 Git 数据库中,也就是项目的 .git 目录内部。

它:

  • 不是项目目录中的普通备份文件;
  • 默认不会上传到 GitHub、Gitee 或远端服务器;
  • 只存在于当前本地仓库中;
  • 删除整个 .git 目录或重新克隆仓库后通常无法保留。

查看全部 stash:

复制代码
git stash list

输出示例:

复制代码
stash@{0}: On main: 回退前备份
stash@{1}: On main: 修改配置文件

stash@{0} 表示最新的一次备份。

默认不会备份未跟踪文件

普通的 git stash push 默认不会保存 ?? 标记的未跟踪文件。

如果还要备份未跟踪文件,需要添加 -u

复制代码
git stash push -u -m "回退前完整备份"

其中:

复制代码
-u = --include-untracked

如果连 .gitignore 忽略的文件也需要备份,可以使用:

复制代码
git stash push -a -m "包含忽略文件的完整备份"

-a 的范围较大,可能包含数据集、模型权重和构建产物,使用前应注意文件体积。

四、回退到指定 Git 版本

假设目标提交为:

复制代码
65f2d202ad1feb4c786616018e5681a8338236c0

执行:

复制代码
git reset --hard 65f2d202ad1feb4c786616018e5681a8338236c0

这条指令会同时修改三个位置:

位置 作用
当前分支指针 移动到目标提交
暂存区 恢复为目标提交的内容
工作区 恢复为目标提交的内容

执行后,当前分支会指向指定提交,已跟踪文件也会恢复到该版本。

需要注意

git reset --hard 会清除已跟踪文件中尚未保存的修改。因此,执行前应先提交代码或使用 git stash 备份。

它通常不会删除普通的未跟踪文件,例如:

复制代码
?? analysis/

如果未跟踪文件与目标提交中的文件发生路径冲突,Git 可能拒绝操作或对相关文件进行处理,因此仍应提前检查:

复制代码
git status --short

五、验证是否回退成功

查看当前提交哈希:

复制代码
git rev-parse HEAD

如果输出:

复制代码
65f2d202ad1feb4c786616018e5681a8338236c0

说明当前分支已经指向目标版本。

也可以执行:

复制代码
git log -1 --oneline

查看当前提交信息。

最后检查工作区:

复制代码
git status --short

如果没有输出,表示工作区干净。

如果只出现:

复制代码
?? analysis/

说明已跟踪代码已经恢复完成,但 analysis/ 是未被 Git 跟踪的目录,因此被保留了下来。

六、查看和恢复 stash 备份

查看某次 stash 修改了哪些文件:

复制代码
git stash show "stash@{0}"

查看完整代码差异:

复制代码
git stash show -p "stash@{0}"

使用 apply 恢复

复制代码
git stash apply "stash@{0}"

apply 会把修改恢复到工作区,同时继续保留 stash 备份。

适合希望先恢复并检查代码、暂时不删除备份的情况。

使用 pop 恢复

复制代码
git stash pop "stash@{0}"

pop 相当于恢复修改,并在成功后删除对应 stash。

为了避免误删备份,更稳妥的方式是先使用:

复制代码
git stash apply "stash@{0}"

确认代码恢复正确后,再手动删除:

复制代码
git stash drop "stash@{0}"

为什么 PowerShell 中建议加引号?

在 PowerShell 中,@{} 有特殊语法含义,因此建议给 stash@{0} 加上引号:

复制代码
git stash apply "stash@{0}"

在 Bash、Git Bash 或 Linux 终端中也可以加引号,写法更加通用。

七、完整的安全回退流程

复制代码
# 1. 进入项目目录
cd 项目目录

# 2. 查看当前状态
git status --short

# 3. 查看最近提交
git log --oneline -5

# 4. 验证目标提交
git rev-parse --verify "65f2d202ad1feb4c786616018e5681a8338236c0^{commit}"

# 5. 备份已跟踪文件和未跟踪文件
git stash push -u -m "回退到65f2d20前的备份"

# 6. 回退到指定提交
git reset --hard 65f2d202ad1feb4c786616018e5681a8338236c0

# 7. 验证当前版本
git rev-parse HEAD
git log -1 --oneline
git status --short

需要恢复回退前的修改时:

复制代码
git stash list
git stash show -p "stash@{0}"
git stash apply "stash@{0}"

八、本地回退会影响远端仓库吗?

不会。

git reset --hard 默认只修改本地仓库。GitHub、Gitee 等远端仓库不会自动变化。

如果需要让远端分支也回退到相同版本,通常需要强制推送:

复制代码
git push --force-with-lease origin 分支名

例如:

复制代码
git push --force-with-lease origin main

强制推送会重写远端分支历史,可能影响其他开发者。在多人协作项目中,应先确认是否允许改写历史。

相比 --force,建议优先使用:

复制代码
--force-with-lease

它会检查远端分支是否已被其他人更新,可以减少覆盖他人提交的风险。

九、reset、checkout/switch 和 revert 的区别

git reset --hard

复制代码
git reset --hard 提交哈希

将当前分支直接移动到历史提交,并恢复暂存区和工作区。适合本地分支回退,或者确定可以重写历史的情况。

临时查看历史版本

如果只是想查看或测试旧版本,不需要移动当前分支,可以执行:

复制代码
git switch --detach 提交哈希

返回原分支:

复制代码
git switch main

如果要基于旧版本继续开发,可以创建新分支:

复制代码
git switch -c 新分支名 提交哈希

git revert

复制代码
git revert 提交哈希

revert 不会删除历史提交,而是创建一个新提交来撤销指定提交的修改。

它更适合已经推送到远端、多人共同使用的分支。

十、误执行 reset 后如何恢复

如果执行 git reset --hard 后发现回退错了,可以查看 Git 操作记录:

复制代码
git reflog

输出示例:

复制代码
65f2d20 HEAD@{0}: reset: moving to 65f2d20
abcdef1 HEAD@{1}: commit: 修改训练逻辑

找到回退前的提交后,可以恢复:

复制代码
git reset --hard abcdef1

reflog 是重要的恢复手段,但其记录并非永久保存,因此发现误操作后应尽快处理。

常用指令速查

指令 作用
git status --short 查看工作区简洁状态
git log --oneline -5 查看最近 5 次提交
git rev-parse HEAD 查看当前提交哈希
git stash push -m "备注" 备份已跟踪文件的未提交修改
git stash push -u -m "备注" 同时备份未跟踪文件
git stash list 查看 stash 列表
git stash show -p "stash@{0}" 查看 stash 的完整差异
git stash apply "stash@{0}" 恢复修改并保留 stash
git stash pop "stash@{0}" 恢复修改并删除 stash
git stash drop "stash@{0}" 删除指定 stash
git reset --hard 提交哈希 将当前分支和代码回退到指定提交
git switch --detach 提交哈希 临时查看历史版本
git revert 提交哈希 创建新提交以撤销历史修改
git reflog 查看本地 HEAD 移动记录
git push --force-with-lease 较安全地强制更新远端历史
相关推荐
尚雷55804 小时前
避坑指南:从零搭建 openGauss oGRAC 双节点集群,这些细节要注意
github·ograc
妙码生花5 小时前
GIT 提交规范
git
TunerT_TQ6 小时前
GitHub每日热评|用写HTML的方式生成确定性MP4:HeyGen开源的HyperFrames到底强在哪?
开源·github·资讯
楠楠子呀6 小时前
给 GitHub Pages 这类纯静态站加 WhatsApp 入口:三种不引后端的写法
github
lindd9119117 小时前
github项目Readme文档制作与远程推送(全自动化上传)
ai·github·ai的skill使用
毕竟是shy哥7 小时前
远程服务器使用github代理
github
云雀衔光7 小时前
多个 MCP Server 怎么编排:数据库 / Redis / Git / 飞书一把梭
java·数据库·人工智能·redis·git·语言模型·飞书
EAIReport8 小时前
GitHub 超全使用指南|托管、协作、开源实战教程
开源·github
乱码三千8 小时前
密码管理工具站正式上线啦
前端·html·github