git reset
git reset
:命令用于回退版本,可以指定退回某一次提交的版本。
语法
git reset [–soft |--mixed |--hard] [HEAD]
HEAD 说明:
HEAD
:表示当前版本。HEAD^
:上一个版本。HEAD^^
:上上一个版本。HEAD^^^
:上上上一个版本。
以此类推…
可以使用~数字
表示:
HEAD~0
:表示当前版本。HEAD~1
:上一个版本。HEAD~2
:上上一个版本。HEAD~3
:上上上一个版本。
以此类推…
git reset --mixed
默认模式,可以直接写git reset
,HEAD 引用指向给定提交,并且索引(暂存区)内容也跟着改变,工作目录内容不变。这个命令会将索引(暂存区)变成你刚刚暂存该提交全部变化时的状态,会显示工作目录中有什么修改。(就是用本地仓库的版本覆盖了暂存区的,回退的那些版本的修改会放在工作目录,可以先加到暂存区,然后再提交)。
git reset HEAD^ # 回退所有内容到上一个版本git reset HEAD^ helloworld.html # 回退 hello.php 文件的版本到上一个版本git reset 052e # 回退到指定版本
git reset --soft
将 HEAD 引用指向给定提交。索引(暂存区)和工作目录的内容是不变的,在三个命令中对现有版本库状态改动最小。(改变本地仓库中的版本,被回退的那些版本的修改会被放在暂存区,可以再次提交)
git reset --soft HEAD
git reset --hard
HEAD 引用指向给定提交,索引(暂存区)内容和工作目录内容都会改变给定提交时的状态。也就是在给定提交后所修改的内容都会丢失(新文件会被删除,不在工作目录中的文件恢复,未清除回收站的前提)。(就是用本地仓库的版本覆盖暂存区与工作目录,被回退的那些版本的修改会直接舍弃,好像它们没有来过一样)
git reflog
当一不小心执行了 hard 模式,想要进行版本回退。
git reflog # 获得commit_idgit reset --hard commit_id # 就能回到对应的版本
选项 | 本地仓库(HEAD) | 暂存区 | 工作目录 |
---|---|---|---|
--mixed(默认) | 有 | 有 | 无 |
--soft | 有 | 无 | 无 |
--hard | 有 | 有 | 有 |
示例
假设你修改了两个文件,想要将它们记录到两个不同的提交中去。你应该缓存并提交一个,再缓存并提交另外一个。如果你不小心两个都缓存了,那要如何才能取消缓存呢?
git reset HEAD -- file
技术上说,在这里你可以不需要使用--
,它用来告诉 Git 这时你已经不再列选项。file:是文件路径了。
好,让我们看看取消缓存是什么样子的。这里我们有两个最近提交之后又有所改动的文件。我们将两个都缓存,并取消缓存其中一个。
git status -s M README M hello.rbgit add .git status -s M README M hello.rbgit reset HEAD -- hello.rb Unstaged changes after reset: M hello.rbgit status -s M README M hello.rb
现在你执行git commit
将只记录 README 文件的改动,并不含现在并不在缓存中的 hello.rb。
它实际的操作是将该文件在“索引”中的校验和重置为最近一次提交中的值。git add
会计算一个文件的校验和,将它添加到“索引”中,而git reset HEAD
将它改写回原先的,从而取消缓存操作。
如果你想直接执行git unstage
,你可以在 Git 中配置个别名。执行git config --global alias.unstage "reset HEAD"
即可。一旦执行完它,你就可以直接用
如果你忘了取消缓存的命令,Git 的常规git status
输出的提示会很有帮助。例如,在你有已缓存的文件时,如果你不带-s
执行git status
,它将告诉你怎样取消缓存:
git status # On branch master # Changes to be committed: # (use "git reset HEAD..." to unstage) # # modified: README # modified: hello.rb #
简而言之,执行git reset HEAD
以取消之前git add
添加,但不希望包含在下一提交快照中的缓存。