关于使用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