撤销操作

优质
小牛编辑
126浏览
2023-12-01

撤销是 Git 提供的一个非常优秀的功能,它可以允许你撤消刚刚所做的操作。这就意味着你不必害怕搞砸你正在工作的项目: Git 一直会让你的项目处于一个安全的状态。

修改最后一次提交

无论你如何精心地推敲你的提交,你总是有可能出错的。比如忘记了把一个改动过的文件添加到提交中,或者是输入了错误的提交注释等等。当你认为提交有问题时,你都可以使用 “git commit” 命令,并附带上 “--amend” 参数,这个操作可以非常轻松地来修改你的最后一次提交。 如果你仅仅是想修改上一次的提交注释,你并不需要操作暂存区,简单地再次输入 “git commit --amend” 并附带上正确的注释就可以了:

$ git commit --amend -m "This is the correct message"

如果你想要添加更多的改动到上一次提交中,你可以像平常一样把这些新的改动添加到暂存区。然后再次使用 “--amend” 参数进行提交:

$ git add some/changed/file.ext
$ git commit --amend -m "commit message"
黄金法则

#5: 不要修改已经被发布的提交

“amend” 操作是一个非常强大的小帮手,这点你会很快地领会到。但是在你使用它的同时,你一定要考虑到以下一些方面:

  • (a) 你只能使用它来修正你的上一次提交。更早的提交是不能使用 “amend” 来进行操作的。
  • (b) 你不要对一个已经在远程仓库上被发布,或者说已经被共享的提交进行 “amend” 操作!这是因为 “amend” 操作实际上在后台打包了一个全新的提交来替换旧的提交。如果在这个远程仓库里仅仅只有你一个人在工作,那么这种操作是没有问题的。但是在团队工作中,如果开发团队的其他人员已经得到了你所发布的改动,并且在此基础之上进行了他自己的改动,再次整合一个被修改过的(amended)提交就会出现很多麻烦。

撤销本地改动

当改动还没有被提交之前,它们仍然被称之为 “本地” 改动。这些在你的工作目录(working directory)的修改还仍然在本地,它们属于未被提交的改动(uncommitted changes)。 有时候你对代码进行了一些修改,但是发现这些改动带来的问题比之前还要多。在这种情况下,你可能想要放弃你刚刚的改动,让代码恢复到你改动之前的版本,也就是上次提交之后的状态。

恢复一个文件到上次提交之后的状态,你可以使用 “git checkout” 命令:

$ git checkout -- file/to/restore.ext

我们已经知道了 “checkout” 命令主要是用来切换分支用的。但是你同样可以给这个命令附带上 “--” 参数,并加上用一个空格来分隔的文件路径。这个操作将撤销在特定文件上所有的未提交的改动。

如果你想要放弃你在工作副本(working copy)中的所有本地改动,并让你的本地副本恢复到上次提交之后的版本,你可以使用 “git reset” 命令:

$ git reset --hard HEAD

上面这个操作会通知 Git 将你本地副本上的所有文件替换到和 “HEAD” 分支一致的版本(也就是上次提交之后的版本状态)上,并放弃所有的本地改动。

注释

放弃本地未被提交的改动是不能被撤销的。这是因为这些改动还没有保存在你的仓库中。因此,Git 也就没有任何机会来挽回这种操作带来的改动。 请在你撤销本地改动时始终牢记这一点。

撤销已提交的改动

有时你也许想撤销某一个之前的提交。例如当你发现你的改动存在错误,或是整个改动就是错误的,又或者你的客户决定不需要这个改动了等等。

使用 “git revert” 命令可以撤销某个之前的提交。但是这个命令并不是删除那个提交,相反的,它是恢复那个提交的改动,这只是看起来像是撤销而已。这个操作实际上会自动产生一个新的提交。在提交中包括了你想要撤销的那个提交的所有反向改动。例如在原始提交中,你在某一个位置添加一些字符,那么这个恢复提交(reverting commit)就会把这些字符删除掉。

revert-concept

如果想要撤销已提交的改动,你只需要简单地给出这个提交的 commit hash:

$ git revert 2b504be
[master 364d412] Revert "Change headlines for about and imprint"
 2 files changed, 2 insertions(+), 2 deletions (-)

$ git log
commit 364d412a25ddce997ce76230598aaa7b9759f434
Author: Tobias Günther <[email protected]>
Date: Tue Aug 6 10:23:57 2013 +0200

    Revert "Change headlines for about and imprint"

    This reverts commit 2b504bee4083a20e0ef1e037eea0bd913a4d56b6.

另外一种撤销提交的方法是使用 “git reset” 命令。这个操作不会自动产生一个新的提交,或是删除你要撤销的提交,它会重置你当前的 HEAD 分支到一个特定旧的版本,也被称作 “回滚(rolling back)” 到旧的版本:

$ git reset --hard 2be18d9

在执行了这个操作之后,你当前签出的分支将被重置为版本 2be18d9。在这个版本之后的一个或者多个版本将被真正的放弃,它们也不会显示在分支的历史记录中。

reset-concept

如果在这个命令上使用 “--hard” 参数则一定要小心,Git 将会丢弃所有你当前可能拥有的本地改动。整个项目将会被恢复成一个之前的旧版本。 如果你使用 “--keep” 参数来替代 “--hard” 参数,那么在 “回滚” 到的版本之后的所有改动将会转换成本地改动,并保留在你的工作目录中。

注释

和 “revert” 命令一样, “reset” 命令也不会删除任何已存在的提交。这些操作仅仅是做得好像这个提交不存在似的,并从历史记录中删除它们。无论如何,提交会被保存在 Git 的数据库中至少30天。因此,如果你发现你曾经不小心删除了一个仍然有用的提交,任何一个精通 Git 的同事都能为你恢复它们。

这两个命令(revert and reset)只是工作于当前 HEAD 分支上。因此在你执行这些操作之前,你必须要切换到正确的分支上去。