关于使用git过程中关于撤回的操作的一些记录,涉及到三个指令,checkout
、reset
和revert
。
代码状态
任何的文件修改(包括增删等)都会经历四个阶段:
工作目录(Working Directory):所进行的任何改动,都是工作区中的改动
暂存区(Index):文件改动通过
add
指令进入暂存区;HEAD:HEAD可以理解为一个指针,通常会指向当前分支的最后一次提交(也可以指向当前分支的历史提交)。Index中的文件改动通过执行
commit
完成提交;远端仓库:本地提交记录,通过
push
推送到远端仓库;
撤回操作
对于处于不同状态的文件,撤回的操作也完全不同,先从我们经常看到的一句提示说起。在输入git status
之后,可能会看到下边的提示:
1 | On branch master |
大概意思就是说,将要被commit的修改,有file1,可以通过git reset ...
来unstage(即从暂存区Index移除回到工作区)。对于file2,可以使用add
将其暂存,或者checkout
丢弃工作区中的所有修改。下边就主要记录一下关于checkout
和reset
的一些操作,以及保留提交历史记录的撤回revert
指令(如果已经把代码修改推到远端仓库就必须使用这个撤回了)。
checkout系列
checkout
指令的作用是切换分支或撤回工作区中的修改。下边是一些经常会用到的指令组合:
1 | git checkout <branch> |
指定分支的名字,切换到对应的分支,如果此时工作区有代码修改,可以stash或者先提交。如果是无关的改动,并不会在checkout时将改动丢弃。
1 | git checkout -- <file> |
对于指定的文件HEAD
所在的commit的版本状态。
1 | git checkout <commit> <file> |
对于指定的文件
可以使用HEAD~
或HEAD~1
表示HEAD
的前一次提交(HEAD
的第一个父节点),使用HEAD~2
表示HEAD
向前的第二次提交(HEAD
的第一个父节点的第一个父节点),等等。
可以使用HEAD^
或HEAD^1
表示HEAD
的前一次提交(HEAD
的第一个父节点),如果当前的HEAD
是由一次merge产生,可以使用HEAD~2
表示HEAD
的第二个父节点提交版本,等等。
1 | git checkout . |
对于当前工作区中的所有文件,丢弃修改,将其撤回到HEAD
所在的commit的版本状态。
reset系列
reset
用于将当前HEAD置为指定的状态(target),配合不同的参数可以实现不同的对文件状态的操作,这里直接使用文档里给的示例。A、B、C和D分别表示的是文件的四个状态。其中target代表想要将HEAD指向到哪个commit,命令行参数中的<commit>
,working、index、HEAD分别就是工作区、暂存区和HEAD
,
使用git reset
命令时,常常可以配合参数soft
、mixed
和hard
,如果缺省的话相当于使用的是mixed
,以下是一些命令对文件状态修改的示例,注意这里都是只使用了一个参数<commit>
(缺省为HEAD
),没有配合<file>
参数:
1 | working index HEAD target working index HEAD |
1 | working index HEAD target working index HEAD |
1 | working index HEAD target working index HEAD |
soft
只会影响到HEAD
,它将HEAD
指向指定的target;mixed
除了将HEAD
指向target之外,还会将暂存区中的文件状态重置为新的HEAD
的状态;hard
将HEAD
指向target,然后将暂存区和工作区都重置为新的HEAD
的状态;
注意注意,上边这么多说的都是不带<file>
参数的情况,如果参数中指定了文件,则相当于对暂存区中的该文件的状态执行了重置,此时不会修改HEAD
指向的位置(即使指定了别的<commit>
),只修改暂存区,并且保留工作区中的文件状态。
用一个表格来整理一下这一组命令,其中模式一列如果空缺表示--mixed
,target一列如果空缺表示HEAD
:
命令 | 模式 | target参数 | 文件参数 | HEAD | 工作区 | 暂存区 |
---|---|---|---|---|---|---|
git reset |
--soft |
<commit> |
指向target | 保留状态 | 保留状态 | |
git reset |
--mixed |
<commit> |
指向target | 保留状态 | 和新的HEAD 一致 |
|
git reset |
--hard |
<commit> |
指向target | 和新的HEAD 一致 |
和新的HEAD 一致 |
|
git reset |
--mixed |
<commit> |
<file> |
不变 | 保留状态 | 和target一致 |
git reset |
--mixed |
<commit> |
<file> |
不变 | 保留状态 | 和target一致 |
revert系列
保证之前提交历史记录的基础上,创建新的提交记录,其中的改动为对应的<commit>
中的逆操作:
1 | git revert <commit> |
REFERENCE
https://git-scm.com/docs/git-reset