引入
使用Git过程中,任何时候,你都有可能需要撤消刚才所做的某些操作,为此该章节,汇总了一些基本的撤消操作相关的命令。专门解决这些困惑。
声明
本文只阐述如何解决问题,不会对git的各种概念多做介绍,如果有兴趣可以点击下面的链接,进行详细的学习:
Pro Git
另外请注意,有些撤销操作是不可逆的,所以请务必谨慎小心,一旦失误,就有可能丢失部分工作成果。
1. 取消对本地文件的修改
问题:如果觉得对某些local files的修改完全没有必要,该如何取消修改,回到之前的状态(也就是修改之前的版本)呢?
方法:其实git status 提示了具体的撤消方法,可以直接git status查看,如下
git checkout — <bad filename>
原理:git checkout 会把工作目录里的文件修改到 Git 之前记录的某个状态。你可以提供一个你想返回的分支名或特定 SHA ,或者在缺省情况下,Git 会认为你希望 checkout 的是HEAD,当前 checkout 分支的最后一次 commit。
记住:你用这种方法“撤销”的任何修改真的会完全消失。因为它们从来没有被提交过,所以之后 Git 也无法帮助我们恢复它们。你要确保自己了解你在这个操作里扔掉的东西是什么!(也许可以先利用git diff来确认一下)
git status 先看一下add 中的文件 状态(养成这个习惯,保证万无一失)
git reset HEAD 撤销本地所有add操作
git reset HEAD <file/folder name> 撤销add操作的某个文件或目录
3. git 取消本地 commit (未push)
方法:git reset –soft HEAD^
原理:这样就成功的撤销了你的commit。注意,仅仅是撤回commit操作,您写的代码仍然保留。
延伸,以下command参数也是可以使用的,只是略有差别,可以根据具体场景选择:
参数1选择: –soft:不删除工作空间改动代码,撤销commit,不撤销git add .
–mixed:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作。这个为默认参数,git reset –mixed HEAD^ 和 git reset HEAD^ 效果是一样的
–hard :删除工作空间改动代码,撤销commit,撤销git add .。完成这个操作后,就恢复到了上一次的commit状态。
参数2选择: HEAD^ 等同于HEAD~1 ,相当与回退到上几个版本;所以,如果是回退两个版本,也可以是HEAD~2 or HEAD^^
补充:如果commit注释写错了,只是想改一下注释,可使用:
git commit –amend or git commit –amend -m “new commit info”
前者会进入默认vim编辑器,修改注释完毕后保存就好了,后者则是新的info会直接替换掉旧的info。
原理:git commit –amend 会用一个新的 commit 更新并替换最近的 commit ,这个新的 commit 会把任何修改内容和上一个 commit 的内容结合起来。如果当前没有提出任何修改,这个操作就只会把上次的 commit 消息重写一遍。
但是万一万一,你用git reset –hard撤销了commit修改只够,有后悔了后悔了。。。怎么办?
方法: git reflog
原理: git reflog 对于恢复项目历史是一个超棒的资源。你可以恢复几乎任何你 commit过的东西,只要通过reflog。你可能已经熟悉了git log命令,它会显示commit的列表。git reflog也是类似的,不过它显示的是一个HEAD发生改变的时间列表.
一些注意事项:
- 它涉及的只是 HEAD 的改变。在你切换分支、用git commit 进行提交、以及用git reset 撤销 commit 时,HEAD会改变,但当你用git checkout — <bad filename> 撤销时(正如我们在前面讲到的情况),HEAD并不会改变 — 如前所述,这些修改从来没有被提交过,因此 reflog也无法帮助我们恢复它们。
- git reflog不会永远保持。Git会定期清理那些“用不到的”对象。不要指望几个月前的提交还一直躺在那里。
- 你的reflog就是你的,只是你的。你不能用git reflog来恢复另一个开发者没有 push 过的 commit。
那么…你怎么利用 reflog 来“恢复”之前“撤销”的 commit 呢?它取决于你想做到的到底是什么:
- 如果你希望准确地恢复项目的历史到某个时间点,用git reset –hard <SHA>
- 如果你希望重建工作目录里的一个或多个文件,让它们恢复到某个时间点的状态,用git checkout <SHA> — <filename>
- 如果你希望把这些 commit 里的某一个重新提交到你的代码库里,用git cherry-pick <SHA>
4. git push提交成功后如何撤销回退
问题:同样,git push后发现提交的内容不是想要的,这时候我们怎么做呢,提交上去的内容是没有删除按钮的(比如github,或码云)。所以我们需要一些手段将提交上去内容撤销下来。
方法1:git revert <SHA>
原理: git revert 会产生一个新的 commit,它和指定 SHA 对应的 commit 是相反的(或者说是反转的)。如果原先的 commit 是“物质”,新的 commit 就是“反物质” — 任何从原先的 commit 里删除的内容会在新的 commit 里被加回去,任何在原先的 commit 里加入的内容会在新的 commit 里被删除。
这是 Git 最安全、最基本的撤销场景,因为它并不会改变历史,所以你现在可以git push新的“反转”commit 来抵消你错误提交的commit。
方法2:先回退版本 用git reset –hard/soft,直接修改代码,然后git commit,最后git push origin 分支 –force
注意:提交失败,因为当前分支的版本低于远程分支的版本,所以要想覆盖掉它,必须使用force
以上只是一些使用经验总结,如有不妥之处,请提出,多多讨论,感谢