乐趣区

使用git-checkout和git-reset覆盖本地修改

我们在本地修改文件、或者删除文件后,如果想恢复这些文件内容为 git 仓库保存的版本,可以使用下面几个命令:

  • git checkout [--] <filepath>:可以恢复还没有执行 git add 的文件,但不能恢复已经执行过 git add 的文件
  • git reset [--] <filepath>:把文件从 git 的 staged 区域移除,即取消 git add,再使用 git checkout 进行恢复
  • git reset --hard:恢复整个 git 仓库的文件内容为当前分支的最新版本

git checkout [–] <filepath>

当修改文件内容、或者删除本地文件后,如果还没有执行 git add 命令添加改动,可以执行 git checkout [--] <filepath> 命令来把 filepath 指定的文件恢复成当前 git 分支的最新版本。对该命令的参数说明如下:

  • [--]:表示 -- 是可选参数,该参数用于指定后面跟着的参数只是文件路径,而不是 branch 分支名或者 commit 信息。

如果当前有一个 branch 分支名是 hello.c,且当前目录下有一个 hello.c 文件,那么不加 -- 参数时,git checkout hello.c 表示切换到 hello.c 分支,而不是覆盖 hello.c 文件的改动。这种场景下,必须用 git checkout -- hello.c 指定覆盖 hello.c 文件的改动,-- 参数可以消除歧义。
在没有名称歧义的情况下,可以不提供 -- 参数。例如使用 git checkout hello.c 覆盖 hello.c 文件。

  • <filepath>:filepath 指定要被覆盖的文件路径,基于当前 shell 工作目录进行寻址。例如要覆盖当前目录下 src 子目录的 utils.c 文件,要写为 src/utils.c.

虽然 filepath 参数提供的文件路径是基于当前 shell 工作目录进行寻址,但这只是描述文件目录结构关系,并不代表在当前工作目录底下一定存在这个文件。例如删除本地的 src/utils.c 文件后,可以用 git checkout src/utils.c 命令恢复这个文件,但是执行这个命令时,本地并不存在 src/utils.c 文件,执行之后才会重新生成。

  • 注意:这里的 [] 表示是可选参数,<>限定非命令选项的参数名,它们都不是参数自身的内容,在输入的时候不要加 [] 或者<>
  • 在 Bash shell 下面,. 表示当前目录路径。当不提供 -- 参数、filepath 参数写为 . 时,git checkout . 命令表示覆盖当前目录及其子目录的改动。这是 git checkout 命令常用的形式。

注意:当不带有 -- 参数时,在 bash shell 下使用 Tab 键补全,默认只会列出本地分支名、远端分支名、和 git refs,不会列出本地文件名。即,默认无法用 Tab 键来补全文件名,即使当前目录下只有一个文件也无法补全,可以先输入文件名开头的部分,才能用 Tab 键补全。
当带有 -- 参数时,在 bash shell 下使用 Tab 键补全,默认只会列出本地文件名,不会列出分支名和 git refs,方便补全本地文件名。

git reset

当修改文件内容、或者删除本地文件后,如果已经执行过 git add 命令来添加该文件的改动,那么用 git checkout 命令无法恢复这个文件为当前 git 分支的最新版本,需要使用下面的 git reset 命令进行处理:

  • git reset [--] <filepath>:把 filepath 文件从 git 的 staged 区域移除,相当于还没有执行 git add 命令。该命令不会恢复文件内容,需要再使用上面描述的 git checkout 命令来恢复文件。

当使用已删除的文件路径作为参数时,git checkout 命令可以不加 -- 参数,但是 git reset 不加 -- 参数会报错,必须使用 -- 来表示后面跟着的是文件路径。例如 hello.c 文件被删除,git checkout hello.c 可以正常恢复该文件,而 git reset hello.c 会报错,git reset — hello.c 不会报错。

  • git reset --hard:将整个 git 仓库的文件都恢复成当前分支的最新版本,会直接恢复文件内容,不需要再执行 git checkout 命令。

该命令不需要传入任何文件路径,默认对 git 仓库跟踪的工作目录、所有子目录、以及所有文件都生效。例如,当前 shell 的工作目录位于某个子目录下,要恢复其父目录下的改动,不需要先执行 cd 命令切换到父目录,直接在子目录下执行 git reset --hard 命令就能恢复父目录下的改动。

退出移动版