如何将文件重置或恢复到特定版本?
如何将修改后的文件恢复到特定提交哈希的先前版本(我通过 git log
和 git diff
)?
How can I revert a modified file to its previous revision at a specific commit hash (which I determined via git log
and git diff
)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
如果您知道需要返回多少次提交,则可以使用:
这假设您位于
master
分支上,并且您想要的版本是 5 次提交。If you know how many commits you need to go back, you can use:
This assumes that you're on the
master
branch, and the version you want is 5 commits back.我想我已经找到了......来自 http:// www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html
有时,您只想返回并忘记过去某个点之后的每项更改,因为它们都是错误的。
从以下内容开始:
$ git log
,它显示最近提交的列表及其 SHA1 哈希值。
接下来,输入:
$ git reset --hard SHA1_HASH
将状态恢复到给定的提交,并从记录中永久删除所有较新的提交。
I think I've found it....from http://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html
Sometimes you just want to go back and forget about every change past a certain point because they're all wrong.
Start with:
$ git log
which shows you a list of recent commits, and their SHA1 hashes.
Next, type:
$ git reset --hard SHA1_HASH
to restore the state to a given commit and erase all newer commits from the record permanently.
这对我有用:
然后提交更改:
This worked for me:
Then commit the change:
当你说“回滚”时,你必须小心。 如果您曾经在提交 $A 中拥有文件的一个版本,然后在两个单独的提交 $B 和 $C 中进行了两次更改(所以您看到的是文件的第三次迭代),并且如果您说“我想回滚到第一个”,你真的是这个意思吗?
如果您想在第二次和第三次迭代中删除更改,则非常简单:
然后提交结果。 该命令询问“我想从提交 $A 记录的状态中签出文件”。
另一方面,您的意思是摆脱第二次迭代(即提交 $B)带来的更改,同时保留提交 $C 对文件所做的操作,您希望恢复 $B 请
注意,无论谁创建了提交$B 可能没有非常遵守纪律,并且可能在同一次提交中提交了完全不相关的更改,并且此恢复可能会触及除您看到的违规更改之外的文件,因此您可能需要仔细检查结果这样做之后。
You have to be careful when you say "rollback". If you used to have one version of a file in commit $A, and then later made two changes in two separate commits $B and $C (so what you are seeing is the third iteration of the file), and if you say "I want to roll back to the first one", do you really mean it?
If you want to get rid of the changes both the second and the third iteration, it is very simple:
and then you commit the result. The command asks "I want to check out the file from the state recorded by the commit $A".
On the other hand, what you meant is to get rid of the change the second iteration (i.e. commit $B) brought in, while keeping what commit $C did to the file, you would want to revert $B
Note that whoever created commit $B may not have been very disciplined and may have committed totally unrelated change in the same commit, and this revert may touch files other than file you see offending changes, so you may want to check the result carefully after doing so.
2.Git将文件恢复到特定分支
2.Git revert file to a specific branch
有趣的是,如果工作副本位于名为
foo
的目录中,git checkout foo
将不起作用; 但是, git checkout HEAD foo 和 git checkout ./foo 都会:Amusingly,
git checkout foo
will not work if the working copy is in a directory namedfoo
; however, bothgit checkout HEAD foo
andgit checkout ./foo
will:rebase
的工作原理如下:假设你有
前两个命令...
犯罪
git 结账
git rebase master
... 查看您想要应用于
master
分支的更改分支。rebase
命令从
获取提交(在master
中找不到)并将它们重新应用到的头部>大师。 换句话说,
中第一次提交的父级不再是master
历史记录中的先前提交,而是master的当前头
。 这两个命令是相同的:由于“base”和“modify”分支都是明确的,因此可能更容易记住此命令。
。 最终历史结果为:
最后两个命令……
执行快进合并,将所有
更改应用到master
上。 如果没有此步骤,变基提交不会添加到master
中。 最终结果是:master
和
都引用B'
。 此外,从此时起,可以安全地删除
引用。Here's how
rebase
works:Assume you have
The first two commands ...
commit
git checkout
git rebase master
... check out the branch of changes you want to apply to the
master
branch. Therebase
command takes the commits from<my branch>
(that are not found inmaster
) and reapplies them to the head ofmaster
. In other words, the parent of the first commit in<my branch>
is no longer a previous commit in themaster
history, but the current head ofmaster
. The two commands are the same as:It might be easier to remember this command as both the "base" and "modify" branches are explicit.
. The final history result is:
The final two commands ...
... do a fast-forward merge to apply all
<my branch>
changes ontomaster
. Without this step, the rebase commit does not get added tomaster
. The final result is:master
and<my branch>
both referenceB'
. Also, from this point it is safe to delete the<my branch>
reference.首先重置目标文件的头,
然后检出该文件
First Reset Head For Target File
Second Checkout That File
如果您想要将文件恢复到以前的提交(以及要恢复的文件已提交),您可以使用
或
然后仅暂存并提交“新”版本。
了解提交在合并情况下可以有两个父级这一知识后,您应该知道 HEAD^1 是第一个父级,HEAD~1 是第二个父级。
如果树中只有一个父级,则任一方法都有效。
In the case that you want to revert a file to a previous commit (and the file you want to revert already committed) you can use
or
Then just stage and commit the "new" version.
Armed with the knowledge that a commit can have two parents in the case of a merge, you should know that HEAD^1 is the first parent and HEAD~1 is the second parent.
Either will work if there is only one parent in the tree.
其中
是要回滚的文件
的文件修订数量。例如,要查看单个文件
x/y/zc
的前一个版本,请运行git prevision 如何工作?
将以下内容添加到您的
gitconfig
基本上,在这种情况下,人们会手动执行所有操作,
包裹在一个漂亮、高效的 git-alias 中 - git-prevision
where
<N>
is the number of revisions of the file to rollback for file<filename>
.For example, to checkout the immediate previous revision of a single file
x/y/z.c
, runHow git prevision works?
Add the following to your
gitconfig
Essentially, all that one would manually do in this situation,
wrapped-up in one beautiful, efficient git-alias - git-prevision
这里有很多建议,大部分都是 git checkout $revision -- $file 的。 一些晦涩的替代方案:
而且,我经常使用它只是为了暂时查看特定版本:
或者
(OBS:
$file
需要以./
为前缀,如果它是 git show $revision:$file 工作的相对路径),更奇怪的是:
Many suggestions here, most along the lines of
git checkout $revision -- $file
. A couple of obscure alternatives:And also, I use this a lot just to see a particular version temporarily:
or
(OBS:
$file
needs to be prefixed with./
if it is a relative path forgit show $revision:$file
to work)And the even more weird:
我必须在这里插入 EasyGit ,它是一个包装器,使 git 更容易被新手使用,而无需让经验丰富的用户感到困惑。 它所做的事情之一是 赋予
更多含义git 恢复
。 在这种情况下,您只需说:eg revert foo/bar foo/baz
I have to plug EasyGit here, which is a wrapper to make git more approachable to novices without confusing seasoned users. One of the things it does is give more meanings to
git revert
. In this case, you would simply say:eg revert foo/bar foo/baz
但请注意,
git checkout ./foo
和git checkout HEAD ./foo
不完全是同一件事; 恰当的例子:(
第二个
add
将文件暂存在索引中,但它没有得到)
Git checkout ./foo
表示从索引恢复路径./foo
;添加
HEAD
指示 Git 将索引中的该路径恢复为其在此之前修改
HEAD
。Note, however, that
git checkout ./foo
andgit checkout HEAD ./foo
are not exactly the same thing; case in point:
(The second
add
stages the file in the index, but it does not getcommitted.)
Git checkout ./foo
means revert path./foo
from the index;adding
HEAD
instructs Git to revert that path in the index to itsHEAD
revision before doing so.对我来说,没有一个答复看起来很清楚,因此我想添加我的答复,这似乎非常简单。
我有一个提交
abc1
,之后我对文件file.txt
进行了多次(或一次修改)。现在假设我弄乱了文件
file.txt
中的某些内容,并且我想返回到之前的提交abc1
。1.
git checkout file.txt
:这将删除本地更改(如果您不需要)2.
git checkout abc1 file.txt
:这会将您的文件带到您的想要版本3。
git commit -m "Restored file.txt to version abc1"
:这将提交您的版本。git push
:这会将所有内容推送到远程存储库上。当然,在步骤 2 和 3 之间,您可以执行
git status
来了解发生了什么。 通常您应该看到已添加的file.txt
,这就是为什么不需要git add
的原因。For me none of the reply seemed really clear and therefore I would like to add mine which seems super easy.
I have a commit
abc1
and after it I have done several (or one modification) to a filefile.txt
.Now say that I messed up something in the file
file.txt
and I want to go back to a previous commitabc1
.1.
git checkout file.txt
: this will remove local changes, if you don't need them2.
git checkout abc1 file.txt
: this will bring your file to your wanted version3.
git commit -m "Restored file.txt to version abc1"
: this will commit your reversion.git push
: this will push everything on the remote repositoryBetween the step 2 and 3 of course you can do
git status
to understand what is going on. Usually you should see thefile.txt
already added and that is why there is no need of agit add
.这里的许多答案声称使用
git reset ...
或git checkout ...
但这样做,您将丢失对
在您要恢复的提交之后提交。如果您只想恢复单个文件上一次提交的更改,就像 git revert 所做的那样,但仅针对一个文件(或者说提交文件的子集),我建议同时使用 < code>git diff 和
git apply
类似(使用
= 你想要恢复的提交的哈希值):基本上,它会首先生成与要恢复的更改相对应的补丁,然后反向应用该补丁以删除这些更改。
当然,如果恢复的行已被
和HEAD
之间的任何提交(冲突)修改,则它将不起作用。Many answers here claims to use
git reset ... <file>
orgit checkout ... <file>
but by doing so, you will loose every modifications on<file>
committed after the commit you want to revert.If you want to revert changes from one commit on a single file only, just as
git revert
would do but only for one file (or say a subset of the commit files), I suggest to use bothgit diff
andgit apply
like that (with<sha>
= the hash of the commit you want to revert) :Basically, it will first generate a patch corresponding to the changes you want to revert, and then reverse-apply the patch to drop those changes.
Of course, it shall not work if reverted lines had been modified by any commit between
<sha1>
andHEAD
(conflict).Git 2.23.0+
将文件恢复为 origin/main 中的状态
将文件恢复为特定提交中的状态
Git 2.23.0 之前
将文件恢复为 origin/main 中的状态
将文件恢复为特定提交中的状态
Git 2.23.0+
Revert file to state as in origin/main
Revert file to state as in specific commit
Before Git 2.23.0
Revert file to state as in origin/main
Revert file to state as in specific commit
为了转到文件的先前提交版本,请获取提交号,例如 eb917a1
那么
如果您只需要返回到最后提交的版本
这将简单地将您带到文件的最后提交状态
In order to go to a previous commit version of the file, get the commit number, say eb917a1
then
If you just need to go back to the last commited version
This will simply take you to the last committed state of the file
git checkout ref|commitHash -- filePath
例如
git checkout ref|commitHash -- filePath
e.g.
这是一个非常简单的步骤。 将文件签出到我们想要的提交 ID,这里是之前的一个提交 ID,然后只需 git commit amend 即可完成。
这非常方便。 如果我们想将任何文件带到提交顶部的任何先前提交 ID,我们可以轻松做到。
This is a very simple step. Checkout file to the commit id we want, here one commit id before, and then just git commit amend and we are done.
This is very handy. If we want to bring any file to any prior commit id at the top of commit, we can easily do.
您可以通过 4 个步骤完成:
您需要在终端中输入的内容:
git revert
git reset HEAD~1
git add
&&git commit -m '恢复文件'
git checkout 。
祝你好运
You can do it in 4 steps:
What you need to type in your terminal:
git revert <commit_hash>
git reset HEAD~1
git add <file_i_want_to_revert>
&&git commit -m 'reverting file'
git checkout .
good luck
使用 git log 获取特定版本的哈希键,然后使用 git checkout
注意:不要忘记在最后一个之前输入哈希值。 最后一个散列指向您当前的位置(HEAD)并且不会改变任何内容。
Use
git log
to obtain the hash key for specific version and then usegit checkout <hashkey>
Note: Do not forget to type the hash before the last one. Last hash points your current position (HEAD) and changes nothing.
显然有人需要写一本关于 git 的易懂的书,或者需要在文档中更好地解释 git。 面对同样的问题,我猜想这
会撤消似乎所做的最后一次提交。
伊恩
Obviously someone either needs to write an intelligible book on git, or git needs to be better explained in the documentation. Faced with this same problem I guessed that
would undo the last commit which is seemed to do.
Ian
假设您想要的提交的哈希值是
c5f567
:git checkout 手册页提供了更多信息。
如果您想恢复到
c5f567
之前的提交,请附加~1
(其中 1 是您想要返回的提交数量,可以是任何值):旁注,我一直对这个命令感到不舒服,因为它既用于普通的事情(在分支之间更改),也用于不寻常的破坏性事情(丢弃工作目录中的更改)。
命令中
--
的含义可以参考在 Git 中,--
(破折号破折号)是什么意思?还有一个新的
git Restore
命令,专门用于恢复已修改的工作副本文件。 如果你的 git 足够新,你可以使用这个命令,但文档附带一个警告:由于 git Restore 是实验性的,因此尚不应该将其提升为该问题的主要答案。 当该命令不再标记为“实验性”时,可以修改此答案以推广 git Restore 的使用。 [在撰写本文时,
git Restore
命令已被标记为“实验性”至少四年。]Assuming the hash of the commit you want is
c5f567
:The git checkout man page gives more information.
If you want to revert to the commit before
c5f567
, append~1
(where 1 is the number of commits you want to go back, it can be anything):As a side note, I've always been uncomfortable with this command because it's used for both ordinary things (changing between branches) and unusual, destructive things (discarding changes in the working directory).
For the meaning of
--
in the command, refer to In Git, what does--
(dash dash) mean?There is also a new
git restore
command that is specifically designed for restoring working copy files that have been modified. If your git is new enough you can use this command, but the documentation comes with a warning:Because
git restore
is experimental, it should not yet be promoted as the primary answer to this question. When the command is no longer marked as "experimental", then this answer can be amended to promote the use ofgit restore
. [At the time of writing, thegit restore
command has been marked as "experimental" for at least four years.]您可以使用 diff 命令快速查看对文件所做的更改:
然后使用重置命令将特定文件恢复到该提交:
如果您有本地文件,则可能需要使用
--hard
选项修改。管理航路点的一个好的工作流程是使用标签在时间轴中清晰地标记点。 我不太明白你的最后一句话,但你可能想要的是从之前的时间点分出一个分支。 为此,请使用方便的签出命令:
然后,当您准备好合并这些更改时,可以根据主线重新调整基础:
You can quickly review the changes made to a file using the diff command:
Then to revert a specific file to that commit use the reset command:
You may need to use the
--hard
option if you have local modifications.A good workflow for managaging waypoints is to use tags to cleanly mark points in your timeline. I can't quite understand your last sentence but what you may want is diverge a branch from a previous point in time. To do this, use the handy checkout command:
You can then rebase that against your mainline when you are ready to merge those changes:
您可以使用对 git 提交的任何引用,包括 SHA-1(如果最方便的话)。 重点是该命令如下所示:
git checkout [commit-ref] -- [filename]
You can use any reference to a git commit, including the SHA-1 if that's most convenient. The point is that the command looks like this:
git checkout [commit-ref] -- [filename]
这会将 foo 重置为 HEAD。 您还可以:
进行一次修订,等等。
That will reset
foo
to HEAD. You can also:for one revision back, etc.
从 git v2.23.0 开始,有一个新的 git Restore 方法,该方法被认为是假设 git checkout 负责的部分内容(即使接受的答案也提到 git checkout 相当混乱)。 请在 github 博客上查看变更要点。
此命令的默认行为是使用来自
source
参数(在您的情况下将是提交哈希)的内容恢复工作树的状态。因此,根据 Greg Hewgill 的回答(假设提交哈希为
c5f567
),命令将如下所示:或者如果您想恢复到 c5f567 之前的一次提交的内容:
As of git v2.23.0 there's a new git restore method which is supposed to assume part of what
git checkout
was responsible for (even the accepted answer mentions thatgit checkout
is quite confusing). See highlights of changes on github blog.The default behaviour of this command is to restore the state of a working tree with the content coming from the
source
parameter (which in your case will be a commit hash).So based on Greg Hewgill's answer (assuming the commit hash is
c5f567
) the command would look like this:Or if you want to restore to the content of one commit before c5f567:
要恢复到最常需要的最后提交的版本,您可以使用这个更简单的命令。
And to revert to last committed version, which is most frequently needed, you can use this simpler command.
我刚才遇到了同样的问题,我发现 这个答案最容易理解(
commit-ref
是您想要返回的日志中更改的SHA值):这会将旧版本放入您的工作目录中,如果需要,您可以从那里提交它。
I had the same issue just now and I found this answer easiest to understand (
commit-ref
is the SHA value of the change in the log you want to go back to):This will put that old version in your working directory and from there you can commit it if you want.