常用的回滚:
-
取消暂存文件;当前分支已经add修改内容到缓存区,相当于remove这次<file>的add
git reset HEAD <file>...
-
撤销对文件的修改;本地修改文件后,放弃该修改的保存;将会被最近的一个提交覆盖了。
git checkout -- <file>...
-
重置回到之前commit的结点;将会把切换到的目标结点之后的提交给丢弃掉(常用于本地提交还未push到远程仓库)
git reset <commit>
-
撤销之前commit的某个结点;将会把某个结点的提交内容丢弃,然后将这个丢弃的修改commit;(实际上就是相当于我们手动把之前的提交内容删除,然后commit重新生成一个新的结点。所以如果是涉及到撤销分支合并的话在撤销后,想再重新把撤销的分支合并回来的话,使用merge的话是会提示:“Already up-to-date”的,此时只需要revert之前的那个revert的结点就可以了)
git revert [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<keyid>]] <commit>… git revert (--continue | --skip | --abort | --quit)
首先我们需要了解下Git的四个工作区域:
- 工作区
也称工作目录、工作副本,简单来说就是clone后我们看到的包含项目文件的目录。
我们日常开发操作就是在工作区中进行的 - 本地仓库(.git)
我们check本地分支/commit到本地仓库,这个本地仓库就是.git文件了。当我们手动删除了.git文件就相当于把项目取消git的版本控制了。 - 暂存区
里面就是存放我们git add 的内容,或者说是下一次commit的内容(实际上我们commit的并不是工作区中我们看到的修改内容,而是暂存区的内容) - 远端仓库
就是我们的git服务器中的仓库,是我们不同开发本地项目共同关联协作的一个仓库。也是不同开发协同开发的一个关联协同的地方。
tree | 用途 |
---|---|
HEAD《当前分支的最后一次提交》 | 上一次提交的快照,下一个提交的父结点 |
Index《暂存区》 | 预期下一次提交的快照 |
Working Directory《工作区》 | 沙盒 |
工作流程图:
- 当我们执行了git reset <commit>命令后会以特定的顺序重写这三棵树:
- 移动 HEAD 分支的指向 (若指定了 --soft,则到此停止)
- 使索引看起来像 HEAD (若未指定 --hard,则到此停止)
- 使工作目录看起来像索引
- 当我们执行了git reset <file>命令后会:(本质上只是将 file从 HEAD 复制到索引中)
- 移动 HEAD 分支的指向 (已跳过)
- 让索引看起来像 HEAD (到此处停止)
- 为什么有些人说当我们在commit还没push到远程仓库的时候可以使用reset去做这个回滚操作呢?而当我们已经push到远程仓库后就不要再使用reset去实现这个回滚的操作,而是改用revert来实现这个回滚的操作呢???
简单地说reset重置是将之前的commit在仓库中进行丢弃,并没有任何关于这个重置的提交记录(reflog可以看到操作记录除外),由于没有新的提交记录故远程仓库以及其他同学的本地仓库都是无感知的对于这个reset动作,对于他们来说你本地仓库只是没有updata新的那些commit而已;所以以reset点为父结点进行提交然后push到远程仓库时,远程仓库依然还是会有回滚的那些内容,甚至会与回滚内容出现冲突现象。
revert撤销某个commit的内容,它只是相当于把需要撤销的结点的修改内容以HEAD为父结点然后移除撤销的内容我们再commit这个修改,之后再将这个commit push到远程仓库就可以将这撤销回滚同步给其他同学了