Git Restore 命令教程

Git Restore 命令教程

简介

git restore 是 Git 2.23 版本引入的一个相对新的命令,用于恢复工作目录或暂存区中的文件。它提供了一个直观的方式来撤销更改,取代了之前使用 git checkout 的一些用法。

这个命令的推出使得 Git 的命令更加清晰和易用,将原本由 git checkoutgit reset 承担的多个职责分离开来,让开发者能够更直观地表达自己的意图。

Git 版本要求

git restore 命令需要 Git 2.23.0 或更高版本

可以使用以下命令查看当前的 Git 版本:

bash 复制代码
git --version

如果你的 Git 版本过旧,请升级到最新版本:

bash 复制代码
# macOS (使用 Homebrew)
brew upgrade git

# Ubuntu/Debian
sudo apt-get update
sudo apt-get upgrade git

# Windows (使用 Git for Windows 官方安装程序)
# 或使用 chocolatey: choco upgrade git

基础概念

在深入学习 git restore 之前,我们需要理解 Git 中的几个关键概念。

工作目录 vs 暂存区 vs 版本库

工作目录(Working Directory)
  • 你在本地电脑上实际编辑的文件所在的位置
  • 这些文件的更改还没有被 Git 追踪
  • 这是你日常工作的区域
暂存区(Staging Area / Index)
  • 通过 git add 命令添加的文件所在的逻辑区域
  • 这些更改已经准备好被提交,但还没有被正式提交到版本库
  • 也被称为 "索引"
版本库(Repository / Commit History)
  • 通过 git commit 命令提交的文件和历史
  • 这是 .git 目录中永久保存的历史记录
  • 包含所有的提交、分支和标签信息

三个区域的关系

复制代码
                    git add           git commit
工作目录  ---------> 暂存区  --------> 版本库
   ↑                   ↑                 ↑
   |                   |                 |
   +-- git restore ----+                 |
   |                                     |
   +---------- git restore --staged -----+
   |
   +--- git restore --source=HEAD~1 ----+

文件的四种状态

  1. Untracked(未追踪) - 文件存在于工作目录但从未被 Git 追踪
  2. Unmodified(未修改) - 文件已提交且没有被修改
  3. Modified(已修改) - 文件已修改但未暂存
  4. Staged(已暂存) - 文件已修改且已暂存,等待提交

Git Restore 概述

命令语法

bash 复制代码
git restore [选项] <文件路径>

核心用途

git restore 命令主要用于以下几个方面:

  • ✅ 恢复工作目录中被修改的文件到最后一次提交的状态
  • ✅ 从暂存区中移除已暂存的更改(保留工作目录的修改)
  • ✅ 从指定的提交历史中恢复文件
  • ✅ 恢复已删除的文件
  • ✅ 选择性恢复文件的特定部分

为什么使用 git restore?

相比使用 git checkoutgit resetgit restore 的优势包括:

  1. 语义清晰 - 命令的目的一目了然
  2. 选项统一 - 相关的选项都在一个命令下
  3. 易于学习 - 新手更容易理解
  4. 更加安全 - 明确的操作目标减少误操作

常用选项详解

主要选项

选项 长选项 说明
-s --source 指定恢复源,如分支名、标签或提交哈希
-S --staged 从暂存区恢复文件,不影响工作目录
-W --worktree 恢复工作目录中的文件(默认行为)
-p --patch 交互式选择要恢复的文件块
-q --quiet 抑制输出信息
-v --verbose 显示详细的处理信息

详细说明

--staged / -S

从暂存区恢复文件,这意味着:

  • 工作目录中的修改保持不变
  • 暂存区中的更改被撤销
  • 文件状态变为"已修改但未暂存"
bash 复制代码
# 单个文件
git restore --staged file.txt

# 多个文件
git restore --staged file1.txt file2.txt

# 所有文件
git restore --staged .
--source / -s

指定恢复的源,可以是:

  • 分支名:maindevelop
  • 标签:v1.0.0
  • 提交哈希:abc1234567
  • 相对引用:HEAD~3HEAD^2
bash 复制代码
# 从 main 分支恢复文件
git restore --source=main file.txt

# 从 3 个提交前恢复文件
git restore --source=HEAD~3 file.txt

# 从特定的提交哈希恢复
git restore --source=abc1234 file.txt
--worktree / -W

恢复工作目录中的文件(这是默认行为)。通常在与 --staged 一起使用时需要显式指定。

bash 复制代码
# 同时恢复工作目录和暂存区
git restore --staged --worktree file.txt

# 等价于
git restore --staged file.txt
git restore file.txt
--patch / -p

以交互式的方式选择要恢复的文件块。这对于只想恢复部分更改很有用。

bash 复制代码
git restore -p file.txt

# 或与 --staged 结合
git restore --staged -p file.txt

交互式模式下的选项:

  • y - 恢复此块
  • n - 不恢复此块
  • q - 退出,不恢复任何内容
  • a - 恢复此块和之后的所有块
  • d - 不恢复此块和之后的所有块
  • s - 将当前块拆分为更小的块
  • k - 不恢复此块,转到上一块
  • j - 不恢复此块,转到下一块
  • ? - 显示帮助

常见使用场景

场景 1:撤销工作目录中的修改

情况:你在工作目录中修改了一个文件,但想放弃这些修改,恢复到最后一次提交的状态。

命令

bash 复制代码
git restore file.txt

效果

  • 文件被恢复到 HEAD(最后一次提交)的状态
  • 工作目录中的所有更改都被放弃
  • 该文件如果已暂存,暂存状态保持不变

示例

bash 复制代码
# 编辑了 app.js,想放弃修改
git restore app.js

# 确认修改已撤销
git status

场景 2:撤销多个文件的修改

情况:多个文件都被修改了,想一次性撤销所有修改。

命令

bash 复制代码
# 方式 1:列出所有文件
git restore file1.txt file2.txt file3.txt

# 方式 2:使用通配符恢复特定类型的文件
git restore *.js

# 方式 3:恢复整个目录
git restore src/

# 方式 4:恢复所有修改
git restore .

示例

bash 复制代码
# 恢复整个 src 目录下的所有 JavaScript 文件
git restore src/*.js

# 恢复整个项目的所有修改
git restore .

场景 3:撤销暂存区中的修改

情况 :用 git add 添加到暂存区后,改变主意,想取消暂存,但保留工作目录中的修改。

命令

bash 复制代码
git restore --staged file.txt

效果

  • 文件从暂存区移除
  • 工作目录中的修改保留不变
  • 文件状态变为"已修改但未暂存"

示例

bash 复制代码
# 修改了 config.js 并暂存
git add config.js

# 改变主意,取消暂存
git restore --staged config.js

# 检查状态
git status
# 输出:config.js 被列在 "Changes not staged for commit" 下

场景 4:从特定分支恢复文件

情况:想从另一个分支恢复特定文件到当前工作目录。

命令

bash 复制代码
git restore --source=branch-name file.txt

效果

  • 获取指定分支中的文件版本
  • 将其放在工作目录中
  • 可以选择是否暂存

示例

bash 复制代码
# 从 main 分支恢复 package.json
git restore --source=main package.json

# 从 develop 分支恢复整个 config 目录
git restore --source=develop config/

# 从特定提交恢复文件
git restore --source=abc1234 README.md

场景 5:恢复已删除的文件

情况 :不小心删除了一个文件(使用 rm 命令),想恢复它。

命令

bash 复制代码
# 从 HEAD 恢复已删除的文件
git restore file.txt

# 或显式指定源
git restore --source=HEAD file.txt

效果

  • 文件被从版本库中恢复
  • 文件重新出现在工作目录中
  • 如果需要提交,使用 git addgit commit

示例

bash 复制代码
# 误删了 important_file.js
rm important_file.js

# 恢复文件
git restore important_file.js

# 文件已恢复
ls important_file.js  # 文件存在

场景 6:交互式恢复文件块

情况:文件中有多个修改,但只想恢复其中的某些部分。

命令

bash 复制代码
git restore -p file.txt

效果

  • Git 会显示每个更改块
  • 你可以交互式地选择恢复哪些块
  • 其他块保持修改状态

示例

bash 复制代码
# 交互式恢复工作目录中的修改
git restore -p app.js

# 交互式从暂存区恢复
git restore --staged -p app.js

场景 7:恢复暂存区中的文件到工作目录

情况:某个文件既在暂存区有更改,又在工作目录有更改,想同时恢复两者。

命令

bash 复制代码
git restore --staged --worktree file.txt

# 或简化形式
git restore --staged file.txt && git restore file.txt

效果

  • 暂存区中的更改被撤销
  • 工作目录中的更改也被撤销
  • 文件恢复到 HEAD 的状态

高级用法

从特定提交恢复文件

使用提交哈希或相对引用从历史中恢复文件。

bash 复制代码
# 使用完整哈希
git restore --source=abc1234567890def file.txt

# 使用短哈希
git restore --source=abc1234 file.txt

# 使用相对引用
git restore --source=HEAD~3 file.txt
git restore --source=HEAD^2 file.txt

# 使用 @{}@ 语法查看最近的提交
git restore --source=@{0} file.txt

从远程分支恢复文件

bash 复制代码
# 恢复远程分支上的文件
git restore --source=origin/main file.txt

# 注意:需要先使用 git fetch 更新远程分支信息
git fetch origin
git restore --source=origin/feature-branch README.md

恢复已删除的文件到不同位置

bash 复制代码
# 在删除前的状态下恢复文件
git restore --source=HEAD file.txt

# 如果需要将文件恢复到特定提交时的状态
git restore --source=HEAD~5 old_file.txt

批量恢复满足条件的文件

bash 复制代码
# 恢复所有 .js 文件
git restore *.js

# 恢复特定目录下的所有文件
git restore src/ config/

# 恢复除了某些文件外的所有修改
git restore . --exclude=.env

# 恢复从暂存区中排除某些文件
git restore --staged . --exclude=package-lock.json

在脚本中使用 git restore

bash 复制代码
#!/bin/bash

# 安全地恢复文件,带确认
read -p "确定要恢复 $1 吗?(y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    git restore "$1"
    echo "文件已恢复"
else
    echo "操作已取消"
fi

git restore vs git checkout

git restore 是对 git checkout 的改进和简化。虽然 git checkout 仍然可用,但 git restore 提供了更清晰的语义和更直观的命令选项。

功能对比表

功能 git restore git checkout 说明
撤销工作目录修改 两者都支持
撤销暂存 --staged ⚠️ 需要 reset restore 更直观
切换分支 这是 checkout 的专长
创建新分支 -b 这是 checkout 的专长
恢复文件 两者都支持
交互式选择 -p -p 两者都支持

命令对应关系

bash 复制代码
# 撤销工作目录修改
git checkout file.txt
git restore file.txt  # 更清晰

# 从暂存区撤销
git reset HEAD file.txt
git restore --staged file.txt  # 更清晰

# 同时撤销暂存和工作目录
git checkout HEAD file.txt
git restore --staged --worktree file.txt  # 更清晰

# 从特定提交恢复
git checkout abc1234 -- file.txt
git restore --source=abc1234 file.txt  # 更清晰

何时使用哪个命令

操作 使用命令 原因
撤销文件修改 git restore 语义清晰
撤销暂存 git restore --staged 更直观
切换分支 git checkout restore 不支持
创建并切换分支 git checkout -b restore 不支持
查看历史版本 git checkout restore 不支持

实战演练

例子 1:修改文件后的悔棋

场景 :你修改了 app.js 文件并保存,但随后意识到修改有问题,想完全放弃。

步骤

bash 复制代码
# 1. 查看当前状态
git status
# 输出:modified: app.js

# 2. 查看具体修改
git diff app.js

# 3. 确认不需要这些修改后,撤销
git restore app.js

# 4. 确认撤销成功
git status
# 输出:working tree clean

结果

  • app.js 恢复到最后一次提交的状态
  • 所有修改都被放弃
  • 工作目录清洁

例子 2:处理意外暂存

场景 :你不小心执行了 git add . 并暂存了所有文件,但只想提交部分文件。

步骤

bash 复制代码
# 1. 查看暂存区中的文件
git status
# 输出:Changes to be committed (staged)

# 2. 取消所有暂存
git restore --staged .

# 3. 确认所有文件都被取消暂存
git status
# 输出:Changes not staged for commit (所有文件)

# 4. 重新选择性地暂存需要的文件
git add src/main.js
git add src/utils.js

# 5. 检查暂存区
git status
# 输出:只有这两个文件被暂存

# 6. 提交
git commit -m "Update main and utils modules"

结果

  • 只有选中的文件被提交
  • 其他修改保留在工作目录,可以继续编辑或单独提交

例子 3:恢复被错误删除的文件

场景 :你不小心用 rm 命令删除了 config.json,现在需要恢复它。

步骤

bash 复制代码
# 1. 意外删除了文件
rm config.json

# 2. 检查状态
git status
# 输出:deleted: config.json

# 3. 恢复删除的文件
git restore config.json

# 4. 确认文件已恢复
ls config.json  # 文件存在
git status      # working tree clean

# 5. 如果文件本应被删除,那就暂存删除
git add config.json
git commit -m "Remove config.json"

结果

  • 删除的文件被恢复
  • 可以继续使用或正式提交删除操作

例子 4:选择性恢复修改

场景styles.css 中有多个修改,但只想保留其中一部分。

步骤

bash 复制代码
# 1. 查看文件的修改
git diff styles.css

# 2. 交互式地选择要恢复的部分
git restore -p styles.css

# Git 会依次显示每个修改块,你可以选择:
# - y: 恢复此块
# - n: 保留此块
# - q: 退出
# - s: 将块分割成更小的片段

# 3. 操作完成后检查
git diff styles.css

# 4. 剩余的修改仍在工作目录中

结果

  • 选定的修改被撤销
  • 保留了你想要的修改
  • 精细控制你的工作

例子 5:从其他分支同步文件

场景 :你想从 main 分支获取最新的 package.json,但保留当前分支的其他修改。

步骤

bash 复制代码
# 1. 确保在正确的分支上
git branch
# 输出:* feature/new-feature

# 2. 从 main 分支恢复 package.json
git restore --source=main package.json

# 3. 检查文件
git status
# 输出:modified: package.json (Changes not staged)

# 4. 查看具体变更
git diff package.json

# 5. 如果满意,暂存并提交
git add package.json
git commit -m "Sync package.json from main"

# 6. 如果不满意,恢复
git restore package.json

结果

  • 从其他分支同步了特定文件
  • 保留了当前分支的其他工作
  • 可以灵活地管理多分支开发

最佳实践

1. 经常检查状态

在执行任何恢复操作前,总是先运行 git status 查看当前状态。这可以帮助你了解哪些文件被修改、哪些被暂存。

bash 复制代码
# 养成习惯:执行 restore 前先查看状态
git status
git diff  # 查看具体修改
git restore file.txt

2. 使用 diff 预览修改

在撤销修改之前,使用 git diff 查看具体内容,确保这是你真正想要放弃的修改。

bash 复制代码
# 查看工作目录的修改
git diff file.txt

# 查看暂存区的修改
git diff --staged file.txt

# 比较两个文件的差异
git diff HEAD file.txt

3. 选择性恢复而非批量恢复

尽可能只恢复需要的文件,而非整个目录或所有文件。这样可以减少意外丢失有用修改的风险。

bash 复制代码
# 好的做法:明确指定文件
git restore src/main.js src/utils.js

# 不太好:一次性恢复所有
git restore .

4. 使用交互模式处理复杂改动

对于包含多个修改的复杂文件,使用 -p 选项进行交互式选择。

bash 复制代码
# 交互式恢复部分修改
git restore -p file.js

# 交互式从暂存区撤销
git restore --staged -p file.js

5. 创建备份分支

如果担心丢失重要内容,先创建一个临时分支来保存你的修改。

bash 复制代码
# 创建备份分支
git branch backup-branch

# 现在可以安心地恢复文件
git restore file.txt

# 如果需要,可以从备份分支恢复
git restore --source=backup-branch file.txt

6. 充分利用 reflog

即使你已经执行了恢复操作,git reflog 也可能帮你找回更改。

bash 复制代码
# 查看历史操作
git reflog

# 找到之前的状态
git restore --source=abc@{5} file.txt

7. 在提交前进行最终检查

在提交前,再次检查你的修改,确保没有遗漏。

bash 复制代码
# 提交前的检查流程
git status
git diff --staged
git commit -m "Clear commit message"

8. 使用有意义的提交消息

配合 git restore,在提交时使用清晰的消息,这样将来需要回溯时会更容易。

bash 复制代码
# 好的提交消息
git commit -m "Fix: 修复用户认证逻辑"
git commit -m "Feature: 添加黑暗模式支持"

# 不好的提交消息
git commit -m "update"
git commit -m "fix bug"

常见错误与解决方案

错误 1:提示文件不存在

错误信息

复制代码
git restore: pathspec 'file.txt' did not match any files

可能原因

  • 文件路径不正确
  • 文件不存在于 Git 仓库中
  • 文件名包含特殊字符或空格

解决方案

bash 复制代码
# 1. 检查文件是否在仓库中
git ls-files | grep file.txt

# 2. 检查正确的文件路径
ls -la file.txt

# 3. 如果文件包含空格,使用正确的路径
git restore "path/to/my file.txt"

# 4. 从另一个分支查找文件
git ls-tree -r main | grep filename

错误 2:--source 参数无法识别

错误信息

复制代码
fatal: unknown option `--source=...'

可能原因

  • Git 版本低于 2.23
  • 拼写错误

解决方案

bash 复制代码
# 检查 Git 版本
git --version

# 如果版本低于 2.23,使用 checkout 替代
git checkout -- file.txt

# 或升级 Git
# macOS: brew upgrade git
# Ubuntu: sudo apt-get upgrade git

错误 3:误删了文件但无法恢复

情况 :使用 git restore 恢复文件时收到错误。

错误信息

复制代码
git restore: pathspec 'file.txt' did not match any files

解决方案

bash 复制代码
# 1. 查看提交历史
git log --follow -- file.txt

# 2. 找到文件最后出现的提交
git show abc1234:path/to/file.txt > file.txt

# 3. 或使用 reflog 找回
git reflog
git restore --source=abc@{0} file.txt

# 4. 如果所有都失败,从远程仓库恢复
git restore --source=origin/main file.txt

错误 4:暂存区和工作目录状态混乱

情况:不清楚哪些更改在暂存区,哪些在工作目录。

解决方案

bash 复制代码
# 1. 使用 git status 获得清晰的概览
git status

# 2. 使用 git diff 查看工作目录修改
git diff

# 3. 使用 git diff --staged 查看暂存区修改
git diff --staged

# 4. 使用 git diff HEAD 查看所有未提交的修改
git diff HEAD

# 5. 重新整理
git restore --staged .  # 清空暂存区
git restore .           # 恢复工作目录
git status              # 应该是 clean

错误 5:恢复了不想恢复的文件

情况 :执行了 git restore,但后来发现恢复了不想恢复的文件。

解决方案

bash 复制代码
# 1. 使用 reflog 查看历史
git reflog

# 2. 找到被恢复前的状态
git restore --source=abc@{0} file.txt

# 或者重新编辑文件,然后 add 和 commit

# 提示:下次使用 -p 选项进行交互式选择
git restore -p file.txt

错误 6:--staged 和 --worktree 冲突

情况 :不清楚 --staged--worktree 的区别。

解决方案

bash 复制代码
# --staged:只处理暂存区
git restore --staged file.txt
# 结果:暂存区清空,工作目录不变

# --worktree:只处理工作目录(默认)
git restore file.txt
# 结果:工作目录恢复,暂存区不变

# 都处理:显式指定两者
git restore --staged --worktree file.txt
# 结果:暂存区和工作目录都恢复

总结

git restore 是现代 Git 工作流中的一个强大工具。通过理解其核心概念和各种选项,你可以更有效地管理版本控制。

核心要点

  1. 理解三个区域:工作目录、暂存区和版本库是理解 Git 的基础
  2. 掌握基本语法git restore [选项] <文件>
  3. 学会常用选项--staged--source-p 是最常用的
  4. 实践各种场景:从简单的撤销修改到复杂的交互式恢复
  5. 遵循最佳实践:检查状态、预览修改、选择性操作
  6. 了解相关命令 :知道何时使用 git restore、何时使用其他命令

常见命令速记

bash 复制代码
# 撤销工作目录修改
git restore file.txt

# 取消暂存
git restore --staged file.txt

# 同时撤销暂存和工作目录
git restore --staged --worktree file.txt

# 从其他分支恢复
git restore --source=main file.txt

# 交互式恢复
git restore -p file.txt

# 恢复删除的文件
git restore --source=HEAD file.txt

学习路径建议

  1. 初级 :学会 git restore 的基本用法
  2. 中级 :掌握 --staged--source 选项
  3. 高级 :使用 -p 选项和复杂的恢复场景
  4. 精通 :结合 refloglog 等工具的高级用法

参考资源

官方文档

在线学习资源

相关命令文档

推荐的最佳实践指南


常见问题 FAQ

Q1:git restore 和 git reset 的区别是什么?

A

  • git restore 专注于恢复文件
  • git reset 用于改变提交历史和暂存区状态

简单来说,如果你想恢复文件,使用 git restore;如果你想修改提交历史,使用 git reset

Q2:我可以恢复已经提交的内容吗?

Agit restore 无法恢复已提交的内容。对于已提交的内容,你需要:

  • 创建新提交来修复:git revert
  • 修改提交历史:git commit --amend
  • 回退到之前的提交:git reset

Q3:误用 git restore 删除了重要文件怎么办?

A:你有以下选项:

  1. 使用 git reflog 查找历史状态
  2. 使用 git restore --source=<commit> 从特定提交恢复
  3. 联系 Git 服务器管理员恢复

Q4:在处理冲突时如何使用 git restore?

A

bash 复制代码
# 保留我们的版本
git restore --ours file.txt

# 保留他们的版本
git restore --theirs file.txt

# 手动解决冲突后
git add file.txt
git commit

Q5:可以恢复子模块中的文件吗?

A:可以的,但需要进入子模块目录:

bash 复制代码
cd submodule-path
git restore file.txt
cd ..
相关推荐
雪兽软件6 小时前
您需要了解的顶级大数据技术
大数据
2501_941871457 小时前
面向微服务链路追踪与全局上下文管理的互联网系统可观测性设计与多语言工程实践分享
大数据·数据库·python
XC131489082677 小时前
ToB获客破局:精准数据+AI外呼,重构效率新模式
大数据·人工智能·重构
小龙7 小时前
[Git 报错解决]本地分支落后于远程分支(`non-fast-forward`)
大数据·git·elasticsearch·github
2501_941809147 小时前
在圣保罗智能物流场景中构建快递实时调度与高并发任务管理平台的工程设计实践经验分享
大数据·人工智能
爱敲代码的婷婷婷.8 小时前
git 指定版本回退、临时保存 等操作
git
QYZL_AIGC8 小时前
全域众链AI赋能实体,开启数字化转型新生态
大数据·人工智能
SCKJAI8 小时前
推出高效能机器人边缘人工智能(AI)平台 ARC6N0 T5X
大数据·人工智能
TTBIGDATA8 小时前
【Knox编译】webhdfs-test 依赖收敛冲突问题处理
大数据·hadoop·ambari·hdp·kerberos·knox·bigtop
金融小师妹9 小时前
机器学习捕捉地缘溢价:黄金突破一周高位,AI预测模型验证趋势强度
大数据·人工智能·深度学习