撤消在Git中的一个文件的工作副本修改?
在最后一次提交之后,我在工作副本中修改了一大堆文件,但是我想撤消对其中一个文件的更改,就像将其重置为与最近的提交一样的状态。
但是,我只想撤销只有这一个文件的工作副本的变化,没有别的。
我怎么做?
您可以使用
git checkout -- file
你可以不使用--
(如nimrodm所build议的),但是如果文件名看起来像一个分支或者标签(或者其他版本标识符),可能会感到困惑,所以最好使用--
。
您也可以检出文件的特定版本:
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
git checkout <commit> <filename>
我今天使用了这个,因为我意识到,当我升级到drupal 6.10时,我的图标已经被覆盖了一些提交,所以我不得不把它拿回来。 这是我做的:
git checkout 088ecd favicon.ico
只是使用
git checkout filename
这将取代当前分支的最新版本的文件名。
警告:您的更改将被丢弃 – 不保留备份。
如果你的文件已经上演(当你在编辑文件之后做了一个git add等等),你的文件就会被暂停。
使用
git reset HEAD <file>
然后
git checkout <file>
如果尚未上演,请使用
git checkout <file>
如果你只想撤消前一个提交对那个文件的更改,你可以试试这个:
git checkout branchname^ filename
这将在最后一次提交之前检出文件。 如果你想多做几次提交,请使用branchname~n
符号。
我使用SHA ID恢复我的文件,我做的是git checkout <sha hash id> <file name>
我总是对此感到困惑,所以这里是一个提醒testing用例。 比方说,我们有这个bash
脚本来testinggit
:
set -x rm -rf test mkdir test cd test git init git config user.name test git config user.email test@test.com 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
此时,更改不在caching中进行,因此git status
为:
$ 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
,结果是这样的:
$ git checkout HEAD -- b.txt $ git status On branch master nothing to commit, working directory clean
如果我们做git reset
,结果是:
$ 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
覆盖更改。
现在让我们假设上面脚本的最后一个变化是暂存/caching的,也就是说我们也在最后做了git add b.txt
。
在这种情况下,此时的git status
是:
$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: b.txt
如果从这一点来说,我们做git checkout
,结果是这样的:
$ git checkout HEAD -- b.txt $ git status On branch master nothing to commit, working directory clean
如果我们做git reset
,结果是:
$ 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 diff --stat HEAD^...HEAD | \ fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ -- git commit -a --amend
这个答案是用于取消在同一个或多个文件夹(或目录)中的多个特定文件中的本地更改所需的命令。 这个答案明确地解决了用户有多个文件但是用户不想撤销所有本地修改的问题:
如果你有一个或多个文件,你可以将samne命令(
git checkout -- file
)应用到每个文件中,通过列出每个文件的位置,如下所示:
git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext
介意name1 / name2 / fileOne.ext nameA / subFolder / fileTwo.ext之间的空格
对于同一文件夹中的多个文件:
如果您碰巧需要放弃某个目录中所有文件的更改,请按如下方式使用git checkout:
git checkout -- name1/name2/*
上面的星号代替了name1 / name2下那个位置的所有文件。
而且,类似地,以下可以撤消对多个文件夹的所有文件的更改:
git checkout -- name1/name2/* nameA/subFolder/*
再次介绍上面的name1 / name2 / * nameA / subFolder / *之间的空格。
注意:名称1,名称2,名称A,子文件夹 – 所有这些示例文件夹名称均指示相关文件所在的文件夹或包。
对我来说只有这个工作
git checkout -p filename
如果已提交,则可以恢复文件的更改并再次提交,然后使用上次提交压缩新提交。
对于特殊情况,你在哪里
-
正在使用Gerrit(或其他套件)进行代码审查
-
已经承诺你的改变
-
已经提交审查
-
只想撤销特定文件中的更改。
-
不想重置和调用全新的审阅会话
我发现以下顺序是最方便的:
-
获取特定文件的更改集git show HEAD [targe_file_name]> path / file.patch
-
反转对特定文件git apply -R path / file.patch所做的更改
-
提交和审查git add -u git commit –game git review