这个问题同样也需要先了解 git 仓库的三个组成部分:⼯作区(Working Directory)、暂存区(Stage)和历史记录区 (History)。
- ⼯作区:在 git 管理下的正常⽬录都算是⼯作区,我们平时的编辑⼯作都是在⼯作区完成
- 暂存区:临时区域。⾥⾯存放将要提交⽂件的快照
- 历史记录区:git commit 后的记录区
三个区的转换关系以及转换所使⽤的命令:
git reset、git revert 和 git checkout的共同点:⽤来撤销代码仓库中的某些更改。
然后是不同点:
⾸先,从 commit 层⾯来说:
- git reset 可以将⼀个分⽀的末端指向之前的⼀个 commit。然后再下次 git 执⾏垃圾回收的时候,会把这个 commit之后的 commit 都扔掉。git reset 还⽀持三种标记,⽤来标记 reset 指令影响的范围:
- --mixed:会影响到暂存区和历史记录区。也是默认选项
- --soft:只影响历史记录区
- --hard:影响⼯作区、暂存区和历史记录区
注意:因为 git reset 是直接删除 commit 记录,从⽽会影响到其他开发⼈员的分⽀,所以不要在公共分⽀(⽐如develop)做这个操作。
- git checkout 可以将 HEAD 移到⼀个新的分⽀,并更新⼯作⽬录。因为可能会覆盖本地的修改,所以执⾏这个指令之前,你需要 stash 或者 commit 暂存区和⼯作区的更改。
- git revert 和 git reset 的⽬的是⼀样的,但是做法不同,它会以创建新的 commit 的⽅式来撤销 commit,这样能保 留之前的 commit 历史,⽐较安全。另外,同样因为可能会覆盖本地的修改,所以执⾏这个指令之前,你需要stash 或者 commit 暂存区和⼯作区的更改。
然后,从⽂件层⾯来说:
- git reset 只是把⽂件从历史记录区拿到暂存区,不影响⼯作区的内容,⽽且不⽀持 --mixed、--soft 和 --hard。
- git checkout 则是把⽂件从历史记录拿到⼯作区,不影响暂存区的内容。
- git revert 不⽀持⽂件层⾯的操作。