回滚到之前的 Git 提交记录

61

我有三个提交,试图清理一些代码。不管怎样,我成功地摧毁了我正在努力的东西。我想删除过去的三个提交并返回到特定的提交SHA1。

如何恢复到以前的提交并删除这三个提交的历史记录?(删除历史记录部分不是很重要)。这些提交已经推送,所以我有点迷惑。

谢谢!


你有3个本地提交,想要回退并永久删除它们吗?这些提交已经被推送到远程了吗? - Pablo Fernandez
是的,它们是远程推送的。这就是为什么我感到困惑。我希望它们永远消失。 - Steven
通常这不是一个好主意,如果你犯了一个错误,你可能会删除你的同事提交的代码。当然,如果你是独自工作,这应该不是问题。为了安全起见,最好只做一个 git revert,提交记录仍将存在,但代码将恢复到正确状态。 - Dimas Kotvan
可能是回滚到以前的Git提交的重复问题。 - Brad Werth
6个回答

81

找到你想要重置到的提交:

git log

一旦你拥有了哈希值:

git reset --hard <hash>

然后将其推送到远程仓库:

git push -f <remote> <branch>

41
由于你的提交已在远程推送,你需要将其删除。我假设你的分支是master并且它被推送到origin
首先,你需要从origin移除master分支: git push origin :master (注意冒号)
然后,你需要将master恢复到想要的状态,我假设这个提交哈希值是ABCDEgit reset --hard ABCDE 最后,再次推送mastergit push origin master 就这样!请注意,如果有人已经从origin下载了你的更改,这将使他们的本地仓库不稳定。

6
我试着操作了一下,输入命令 git clone git@github.com:dandv/reveal.js.gitgit push origin :master 后出现了错误:> remote: error: refusing to delete the current branch: refs/heads/master To git@github.com:dandv/reveal.js.git
! [remote rejected] master (deletion of the current branch prohibited) error: failed to push some refs to 'git@github.com:dandv/reveal.js.git'
- Dan Dascalescu
1
你不需要执行 git push -f origin master 吗?你说“注意冒号”,但它是做什么用的? - Erick Maynard

22

在git中,一般的想法是你永远不删除一个提交记录。你只需将它们留下没有名称。那些既没有名称也没有被其他命名的提交记录所引用的提交记录,最终会自动消失。

例如,假设你开始的记录如下:

$ git checkout my_work_branch
<do some editing>
$ git commit -m "attempt #1, so far so good"
<do more editing>
$ git commit -m "attempt #2, getting a little hazier"
<do more editing>
$ git commit -m "attempt #3, looking bleak now"

此时,git log --graph --decorate --pretty=oneline --abbrev-commit 命令可能会输出以下内容:

* d97de0e (HEAD, my_work_branch) attempt #3, looking bleak now
* 9a3efe3 attempt #2, getting a little hazier
* 9e80936 attempt #1, so far so good
* a1d6424 here's where you started

现在你有一个名为my_work_branch(之前给的名字)的分支,它“指向”提交版本d97de0e,而该版本又指向9a3efe3,9a3efe3又指向9e80936,最后指向a1d6424。(这也是特殊名称HEAD所指的位置。)

您可以使用任何旧的git checkout将HEAD移动到其他位置。但是,请注意:您还可以将名称my_work_branch移到指向a1d6424的位置:

$ git reset --hard a1d6424
或者
$ git reset --hard HEAD~3  # use at most one of these
如果您这样做,您会发现名称为my_work_branch的分支也已移动:
$ git rev-parse my_work_branch
a1d6424e5afcda475910084720c9aa26e3528618

你添加的提交仍然存在:

$ git log d97de0e

会将它们展示给你:

$ git log --graph --decorate --pretty=oneline --abbrev-commit d79de0e
* d97de0e attempt #3, looking bleak now
* 9a3efe3 attempt #2, getting a little hazier
* 9e80936 attempt #1, so far so good
* a1d6424 (HEAD, my_work_branch) here's where you started
它们只是不再有名字了,如果你做了一些工作并且使用git addgit commit,那么这将在一个名为my_work_branch的新分支上。旧的那个有三个额外提交的分支现在是一个“垃圾”分支。(如果你决定尽管很糟糕但仍想要它们,你只需要在它们大约3个月后过期之前给它们命名。你必须以某种方式找到或记住那个数字,在上面的示例中是d97de0e。)
更新:啊,你已经推送了它们并且希望它们从远程存储库中消失。

你不必删除远程分支。在执行倒带(git reset --hard)操作后,你可以使用git push -f。只需记住,任何已获取你推送的更改的其他人都会继续拥有它们,并可能因其存在而容易混淆。你必须警告任何此类人注意你已经“撤回”的提交。


15

好的,这里有两个解决方案。

无论哪种解决方案,都要使用git log找到要回溯的提交哈希值。

1)通过自动创建补丁来撤消更改。

什么? 自动创建一个反向补丁来撤消您的更改。提交并推送补丁。您原来的更改仍在git日志中,但是它们被这个反向补丁“撤消”了。

如何? git revert [hash] && git push

为什么? 因为你是一位与其他友好的开发人员合作的好开发人员,不想破坏他们的本地库。

为什么不? 因为以后“合并”您的更改会更难。撤消补丁比您的更改“新”,因此重新应用您的更改比“git merge”要困难。

2)强制推送到之前的提交

什么? 分支是指向提交的指针。将该指针硬重置为以前的提交,然后将该指针强制推送到服务器。您的更改(和其他人的更改)从git历史记录中删除。

如何? git reset --hard [hash] && git push -f

为什么? 因为你是一个野生的牛仔/女牛仔,你的更改在一个功能分支中,你想保留该分支以便稍后轻松合并。

为什么不呢? 如果你重置并推送了代码,那么已经拉取过你更改的团队成员的本地仓库就会被搞乱(例如丢失他们的提交记录,必须重新提交工作)。如果你还没有推送(或者他们还没有拉取),那就没问题。


2

使用 git revert

-- 你可以还原一个、两个或一段范围内的提交

-- 它也会删除提交历史记录

1) git revert 175a25

2) git status / git log (确认是否已还原)

3) git push


这将创建一个反向补丁来撤销更改。该补丁对其他开发者(例如,拉取您要还原的更改的任何人)更好,但这也意味着您以后无法合并更改(因为反向补丁是“更新的”)。 - Michael Cole

0
例如,如果您想要摆脱最后两个提交,可以这样做:
git log -3
commit 7e83c9fa5dc1a1914847bfccfe9d2da14f845070
Author: Jaime Montoya <webmaster@jaimemontoya.com>
Date:   Fri Sep 28 05:58:58 2018 -0600

    Add new background image to the header of the website.

commit b84b0c38df2f876d1c1f5657e6e452b5689c2d80
Author: Shannon Hall <s.hall@example.net>
Date:   Thu Sep 27 21:35:48 2018 -0400

    Include code for Google Maps.

commit 40e82f46c1d523cb07abb6abe9f8c64f2b4fe0f7
Author: Jaime Montoya <webmaster@jaimemontoya.com>
Date:   Thu Sep 27 18:57:45 2018 -0600

    Update links to copyright messages.

在这种情况下,我们试图摆脱这两个提交:7e83c9fa5dc1a1914847bfccfe9d2da13f845070b84b0c38df2f876d1c1f5657e6e255b5689c2d80。我们希望将此作为我们的最新提交:40e82f46c1d523cb07abb6abe9f8c64f2b4fe0f7。我们需要执行以下操作:

git reset --hard 40e82f46c1d523cb07abb6abe9f8c64f2b4fe0f7

这是一种从本地代码库撤销提交的方法。
完成上述步骤后,您可以使用git push <remote> <branch>将更改推送到远程代码库。

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