如何在Git中将以前的版本恢复为新的提交?

21
首先,我之前在这里看到过这个问题的答案,但是被很多不正确回答我的问题的“答案”埋没了,以至于我再也找不到它了。
所以问题来了:如何在Git中恢复到历史的先前版本,使其成为我当前历史记录的新提交?
基本上,这是我想要在版本控制系统中做的最基本的事情。简单地进行重置不起作用,因为它会丢弃我的历史记录,简单的还原也不起作用,因为有时会出现错误消息(我想要做的应该可以在没有任何错误消息的情况下完成)。
如果我只是执行git revert,会出现以下错误:
git revert HEAD~1
error: could not revert f1b44e3... Towards translating API to kernel.
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

回滚时有什么错误? - Julian
1
git revert 的意思是“撤销一个单独的、具体的提交”,而不是“返回先前的版本”。Mercurial 的这个操作的名称更好:hg backout。Mercurial 有一个带有您在此期望的含义的 hg revert!同时,Dai's answer 是正确的。 - torek
4个回答

38
只需“checkout提交”。这将用历史记录中指定的快照(提交)覆盖您当前的工作目录,并将其作为新的工作集,您可以根据需要进行暂存和提交。
cd ~/git/your-repo-root
git log
# find the commit id you want
git checkout <commitId> .

重要提示:前一行中的末尾句点很重要!如果你省略它,你将会处于一个“分离的HEAD”状态,这是你不想要的。
如果你紧接着进行提交,那么你的仓库将与你执行checkout操作的提交具有相同的文件系统内容(假设你没有其他未暂存或已暂存的更改)。
git commit -m "Restoring old source code"

这不会改写历史,也不会编辑或删除任何先前的提交 - 因此它类似于Mediawiki上的“回滚”操作:
另请参阅:在公共存储库中回滚到旧的Git提交 关于“.”(点)的说明:
“.”(点)字符表示“当前目录” - 它不是Git特有的,它是一个标准的命令行文件系统约定,在Windows、Linux、macOS甚至MS-DOS上都是相同的。它的工作方式类似于“..”表示“父目录”。我建议阅读以下内容:

关于checkout的事项

注意:`checkout` 是 git 中一个重载的命令 - 它可以表示切换分支(类似于 `svn switch`),也可以表示从历史记录中获取特定文件或提交并放入你的工作区(类似于 `svn update -r `)。它还可以表示其他意思:https://git-scm.com/docs/git-checkout - 我明白它可能会让人困惑,尤其是当我在使用 TFS 多年后开始使用 git 时(在 TFS 中,“Checkout”表示完全不同的事情)。

2
啊,这也不行。我想把旧的东西提交到我的最后一次提交之上。请大家,如果你不知道我想要做什么,请不要用错误的答案来垃圾邮件轰炸我。 - Steven Obua
1
@StevenObua 但这就是它的功能 - 它会获取旧快照,然后当您提交时,它将成为新的HEAD。我已经修改了我的回答,包括最终的git commit - Dai
在结账中,.有什么作用?你有没有想过要在谷歌上搜索这个问题是多么困难? - Joe Phillips
1
这正是我想要的,Dai。非常感谢你,很抱歉我没有仔细阅读你的答案。在我的印象中,checkout 命令总是为指定版本创建一个新分支,我不知道它还有其他含义。 - Steven Obua
3
如果你和我一样错过了结尾的 .,导致进入了分离 HEAD 状态,那么执行 git checkout master 命令(或者替换成你正在工作的分支)将会撤销该命令。 - Andrew
显示剩余3条评论

2

编辑:我看到您想要保留历史记录,因此我下面的答案无效。但是,它仍然有用。您可以在编辑器中重新排序行,然后继续。

现在,回到原始答案。

您可以尝试使用rebase命令。

git rebase -i HEAD~n

当你想要回退到之前的某个提交时,n 大约是当前提交和目标提交之间的提交数量再加一。比如说,如果你想要回退最近的 3 个提交:

git rebase -i HEAD~4

一旦你到了那里,它将在VIM或Nano(或其他编辑器)中打开。只需删除要删除的提交行,然后退出编辑器即可。

在VIM中,这将是esc并键入:exitenter

现在,只需推送它。 这将导致错误,因此进行强制推送。

git push -f

您可能需要指定分支名称和上游,这样就可以解决问题了!

此方法完全删除了错误提交,因此它不仅会添加一个新的提交来还原更改。

以下是文档:https://git-scm.com/docs/rebase


1

记录当前 HEAD 的提交哈希值

  1. git reset --hard <old-commit>
  2. git reset --soft <previous-HEAD>
  3. git add . && git commit -m "message"

完成!


0

使用 git revert https://git-scm.com/docs/git-revert

git revert HEAD~1

不行。那个命令有时会出错,需要进一步处理。我不想这样。 - Steven Obua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接