在Git中撤消一个文件的工作副本修改?

Undo working copy modifications of one file in Git?

在最后一次提交之后,我修改了工作副本中的一组文件,但是我想撤消对其中一个文件的更改,就像在将其重置为与最近提交相同的状态一样。

但是,我只想撤消仅此一个文件的工作副本更改,而不使用其他任何文件。

我该怎么做?


你可以用

1
git checkout -- file

您可以不使用--(如nimrodm建议的那样),但如果文件名看起来像分支或标记(或其他修订标识符),则可能会混淆,因此最好使用--

您还可以签出文件的特定版本:

1
2
3
4
5
git checkout v1.2.3 -- file         # tag v1.2.3
git checkout stable -- file         # stable branch
git checkout origin/master -- file  # upstream master
git checkout HEAD -- file           # the version from the most recent commit
git checkout HEAD^ -- file          # the version before the most recent commit


1
git checkout <commit> <filename>

我今天用这个是因为我意识到几天前当我升级到Drupal6.10的时候我的favicon被覆盖了,所以我不得不把它拿回来。以下是我所做的:

1
git checkout 088ecd favicon.ico


只是使用

1
git checkout filename

这将用当前分支的最新版本替换文件名。

警告:您的更改将被丢弃&mdash;不保留备份。


如果您的文件已被暂存(在编辑文件后执行git add等操作时发生),则取消对更改的保存。

使用

1
git reset HEAD <file>

然后

1
git checkout <file>

如果还没有准备好,只需使用

1
git checkout <file>


如果只想撤消以前提交对该文件所做的更改,可以尝试以下操作:

1
git checkout branchname^ filename

这将签出上次提交之前的文件。如果您想进行更多的提交,请使用branchname~n符号。


我通过Git Bash完成了:

埃多克斯1〔17〕

  • Git状态。[所以我们看到一个文件被修改。]
  • git checkout--index.html[我在index.html文件中已更改:
  • Git状态[现在这些更改被删除]
  • 氧化镁


    我总是对此感到困惑,所以这里有一个提醒测试案例;假设我们有一个用于测试gitbash脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    set -x
    rm -rf test
    mkdir test
    cd test
    git init
    git config user.name test
    git config user.email [email protected]
    echo 1 > a.txt
    echo 1 > b.txt
    git add *
    git commit -m"initial commit"
    echo 2 >> b.txt
    git add b.txt
    git commit -m"second commit"
    echo 3 >> b.txt

    此时,更改不在缓存中进行,因此git status是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git status
    On branch master
    Changes not staged for commit:
      (use"git add <file>..." to update what will be committed)
      (use"git checkout -- <file>..." to discard changes in working directory)

        modified:   b.txt

    no changes added to commit (use"git add" and/or"git commit -a")

    如果从这一点来看,我们做了git checkout,结果是:

    1
    2
    3
    4
    $ git checkout HEAD -- b.txt
    $ git status
    On branch master
    nothing to commit, working directory clean

    如果我们改为执行git reset,结果是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git reset HEAD -- b.txt
    Unstaged changes after reset:
    M   b.txt
    $ git status
    On branch master
    Changes not staged for commit:
      (use"git add <file>..." to update what will be committed)
      (use"git checkout -- <file>..." to discard changes in working directory)

        modified:   b.txt

    no changes added to commit (use"git add" and/or"git commit -a")

    因此,在这种情况下——如果更改不是分阶段进行的,那么git reset没有任何区别,而git checkout覆盖了更改。

    现在,假设上面脚本的最后一个更改是分阶段/缓存的,也就是说,我们最后也做了git add b.txt

    在这种情况下,此时的git status是:

    1
    2
    3
    4
    5
    6
    $ git status
    On branch master
    Changes to be committed:
      (use"git reset HEAD <file>..." to unstage)

        modified:   b.txt

    如果从这一点来看,我们做了git checkout,结果是:

    1
    2
    3
    4
    $ git checkout HEAD -- b.txt
    $ git status
    On branch master
    nothing to commit, working directory clean

    如果我们改为执行git reset,结果是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ git reset HEAD -- b.txt
    Unstaged changes after reset:
    M   b.txt
    $ git status
    On branch master
    Changes not staged for commit:
      (use"git add <file>..." to update what will be committed)
      (use"git checkout -- <file>..." to discard changes in working directory)

        modified:   b.txt

    no changes added to commit (use"git add" and/or"git commit -a")

    因此,在这种情况下,如果变更是阶段性的,那么git reset基本上会将阶段性的变更变成未经阶段性的变更,而git checkout会完全覆盖变更。


    此答案适用于撤消本地更改所需的命令,这些更改位于同一个或多个文件夹(或目录)中的多个特定文件中。此答案专门解决了一个用户有多个文件但不想撤消所有本地更改的问题:

    if you have one or more files you could apply the same command (git checkout -- file ) to
    each of those files by listing each of their location separated by
    space as in:

    1
    git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext

    mind the space above between name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext

    对于同一文件夹中的多个文件:

    If you happen to need to discard changes for all of the files in a
    certain directory, use the git checkout as follows:

    1
    git checkout -- name1/name2/*

    上面的星号完成了在name1/name2下撤消该位置上所有文件的技巧。

    And, similarly the following can undo changes in all files for
    multiple folders:

    1
    git checkout -- name1/name2/* nameA/subFolder/*

    again mind the space between name1/name2/* nameA/subFolder/* in the
    above.

    注意:名称1、名称2、名称A、子文件夹-所有这些示例文件夹名称都指示相关文件可能驻留的文件夹或包。


    我使用sha id恢复文件,我所做的是git checkout


    对我来说只有这个有效

    1
    git checkout -p filename

    enter image description here


    如果您尚未推动或以其他方式共享您的承诺:

    1
    2
    3
    git diff --stat HEAD^...HEAD | \
    fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
    git commit -a --amend


    我不知道为什么,但当我尝试输入代码时,它会显示为图像。

    氧化镁


    如果已经提交了该文件,则可以恢复对该文件的更改并再次提交,然后使用最后一次提交挤压新提交。