首先,Git
必须知道当前版本是哪个版本,在 Git
中,用 HEAD
表示当前版本,上一个版本就是 HEAD^
,上上一个版本就是 HEAD^^
,当然往上 100 个版本写 100 个 ^
比较容易数不过来,所以写成 HEAD~100
。
要让仓库的 HEAD
、暂存区、当前工作树回溯到指定状态,需要用到 git rest --hard
命令。只要提供目标时间点的哈希值 A,就可以完全恢复至该时间点的状态。
$ git reset --hard fd0cbf0d4a25f747230694d95cac1be72d33441d
HEAD is now at fd0cbf0 Add index
git log
命令只能查看以当前状态为终点的历史日志。所以这里要使用 git reflog
命令,查看当前仓库的所有操作日志。在日志中找出回溯历史之前的哈希值,通过 git reset --hard
命令恢复到回溯历史前的状态。
首先执行 git reflog
命令,查看当前仓库执行过的操作的日志。
$ git reflog
4096d9e HEAD@{0}: commit: Fix B
fd0cbf0 HEAD@{1}: checkout: moving from master to fix-B
fd0cbf0 HEAD@{2}: reset: moving to fd0cbf0d4a25f747230694d95cac1be72d33441d
83b0b94 HEAD@{3}: merge feature-A: Merge made by the 'recursive' strategy.
fd0cbf0 HEAD@{4}: checkout: moving from feature-A to master
8a6c8b9 HEAD@{5}: checkout: moving from master to feature-A
fd0cbf0 HEAD@{6}: checkout: moving from feature-A to master
8a6c8b9 HEAD@{7}: commit: Add feature-A
fd0cbf0 HEAD@{8}: checkout: moving from master to feature-A
fd0cbf0 HEAD@{9}: commit: Add index
9f129ba HEAD@{10}: commit (initial): First commit
从上面数第四行表示feature-A 特性分支合并后的状态,对应哈希值为83b0b94A。我们将HEAD、暂存区、工作树恢复到这个时间点的状态。
$ git checkout master
$ git reset --hard 83b0b94
HEAD is now at 83b0b94 Merge branch 'feature-A'
如果要把修改推送至远程,执行以下命令(切记:只能在个人分支操作,不要在集成分支操作):
git push -f -u origin master(master为指定分支)
如果你并不想保留对 readme.txt 文件的修改怎么办? 你该如何方便地撤消修改——将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)? 幸运的是,git status
也告诉了你应该如何做。 在最后一个例子中,未暂存区域是这样:
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.txt
它非常清楚地告诉了你如何撤消之前所做的修改。 让我们来按照提示执行:
$ git checkout -- readme.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
renamed: LICENSE -> LICENSE.md
请务必记得 git checkout --
是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git
会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。
以上这些就是 git
中关于撤销以及删除文件的相关内容了,让我们来回顾一下:
git checkout -- file
git reset HEAD
,就回到了场景1,第二步按场景1操作git reset --hard commit_id
,不过前提是没有推送到远程库