git撤销操作 - reset、revert、checkout

都是用来做撤销的,来详细看下怎么用。

命令 Scope 常用于
git reset Commit-level 丢弃私有分支上的提交,或丢弃未提交的修改
git reset File-level Unstage a file
git checkout Commit-level 分支间切换,或查看历史提交快照
git checkout File-level 丢弃工作目录的修改
git revert Commit-level 撤销公共分支的提交
git revert File-level 没有文件层级的操作

git revert <Commit-id> 是通过对指定的提交做反向的修改,然后提交一个新的提交。

git checkout <Commit-id> 切到指定的提交,进入“detached HEAD”状态,就是将 HEAD指针 指向指定的提交,可以基于这个节点作一些修改提交,不会影响到任何分支,直接切到原来的提交上去。如果想要保留这些提交,可以在以新的提交去创建一个新的分支 git checkout -b <new-branch-name>

1
2
3
4
5
6
7
8
9
10
11
12
13
robertdeMacBook-Pro% git checkout a378a93
Note: checking out 'a378a93'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

HEAD is now at a378a93 project initiate

git reset 是通过对指定的提交 改变”three trees“(工作目录、暂存区、提交历史),reset针对“three trees”有3种模式

1
2
3
4
5
6
7
git reset [--soft|--hard] HEAD~    
##仓库(提交历史)回到指定的提交
##--soft 工作目录和暂存区都不变
##--mixed 暂存区变成和指定的提交一致,工作目录不受影响
##--hard 暂存区和工作目录都回到指定提交,会直接覆盖工作目录
HEAD~x x是撤销的提交个数
<commitid> 提交hash

要搞清楚的一点的是,以上所说的变不变,指的是git reset前后的工作目录、暂存区相对于他们本身变不变,而不是,工作目录相对于暂存区,暂存区相对于仓库(最新提交,HEAD)。
比如,git reset --soft <commit-id>,操作前后,工作目录、暂存区的内容都是不变的,但是仓库(提交历史的最新提交,HEAD)回到了<commit-id>处,所以暂存区相对的仓库肯定是有修改的。

注意:checkoutreset通常用于作本地或者私有分支的撤销。它们修改提交历史和仓库,推送到共享的远程仓库时可能会导致冲突。revert被认为是针对“公共撤销”的安全操作,因为它创建一个新的提交,不会重写其他成员可能依赖的提交历史。

参考:reset/revert/checkout