🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 撤销操作 撤销是 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](https://box.kancloud.cn/2016-05-04_572967dedd267.png) 如果想要撤销已提交的改动,你只需要简单地给出这个提交的 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 <support@learn-git.com> 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](https://box.kancloud.cn/2016-05-04_572967df05bb3.png) 如果在这个命令上使用 “--hard” 参数则一定要小心,Git 将会丢弃所有你当前可能拥有的本地改动。整个项目将会被恢复成一个之前的旧版本。 如果你使用 “--keep” 参数来替代 “--hard” 参数,那么在 “回滚” 到的版本之后的所有改动将会转换成本地改动,并保留在你的工作目录中。 ##### 注释 和 “revert” 命令一样, “reset” 命令也不会删除任何已存在的提交。这些操作仅仅是做得好像这个提交不存在似的,并从历史记录中删除它们。无论如何,提交会被保存在 Git 的数据库中至少30天。因此,如果你发现你曾经不小心删除了一个仍然有用的提交,任何一个精通 Git 的同事都能为你恢复它们。 这两个命令(revert and reset)只是工作于当前 HEAD 分支上。因此在你执行这些操作之前,你必须要切换到正确的分支上去。