checkout&&reset

git checkout指令是用来还原一个代码仓库中的文件的,例如笔者在前面的项目中,继续修改README文件,然后执行git checkout<file>指令,此时再查看当前代码仓库状态,如下所示。

  1. GradleTest git:(master) vim README
  2. GradleTest git:(master) git status
  3. On branch master
  4. Changes not staged for commit:
  5. (use "git add <file>..." to update what will be committed)
  6. (use "git checkout -- <file>..." to discard changes in working directory)
  7.  
  8. modified: README
  9.  
  10. no changes added to commit (use "git add" and/or "git commit -a")
  11. GradleTest git:(master) git checkout README
  12. GradleTest git:(master) git status
  13. On branch master
  14. nothing to commit, working directory clean

可以发现在修改文件之后,执行git add指令之前,如果执行checkout指令,则会抛弃当前本地的所有修改,恢复到上次最后的提交版本。

如果修改文件并执行git add指令后继续修改文件,此时再执行checkout指令,查看代码仓库状态,如下所示。

  1. GradleTest git:(master) vim README
  2. GradleTest git:(master) git status
  3. On branch master
  4. Changes not staged for commit:
  5. (use "git add <file>..." to update what will be committed)
  6. (use "git checkout -- <file>..." to discard changes in working directory)
  7.  
  8. modified: README
  9.  
  10. no changes added to commit (use "git add" and/or "git commit -a")
  11. GradleTest git:(master) git add README
  12. GradleTest git:(master) vim README
  13. GradleTest git:(master) git checkout README
  14. GradleTest git:(master) git status
  15. On branch master
  16. Changes to be committed:
  17. (use "git reset HEAD <file>..." to unstage)
  18.  
  19. modified: README

可以发现在执行add指令将代码提交到暂存区后,再修改该文件。此时如果继续执行checkout指令,则会将该文件恢复到执行add操作后的初始状态,即恢复add后的所有修改。因此,git checkout<file>指令其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除。

注意到执行git status后显示的一句话提示:(use"git reset HEAD<file>…"to unstage),Git告诉开发者可以通过该指令将一个文件移出暂存区。这也是回退的方法。而对于已经commit的提交,如果要进行回退,则可以使用git reset<last commit SHA><file>指令。它的原理就是reset掉提交记录,但不修改本地工作区,从而进行新的提交。