基本概念
在讲述命令的使用姿势之前,我们首先需要了解git仓库的组成。git仓库主要由三部分组成,分别是工作空间(workspace), 暂存区(stage), 本地仓库。
- 工作空间(workspace): 通过git进行版本管理的目录和文件
- 暂存区(stage): 所有更新都会先放到暂存区,直到我们把更新提交到仓库中
- 本地仓库: 存放在本地的版本库,HEAD指向当前本地仓库的最后一次提交
下图展示了文件如何在以上三个部分转换
git rebase
定义
rebase命令将某一个分支上的所有修改都转移至另一个分支上
操作示例
从下图中我们可以看到两个分支master与branch1,他们有相同的祖先节点C1,表示这两个分支都是基于C1这次提交进行修改的
如果我们使用rebase命令合并两个分支,命令如下,示意图如图
git checkout branch1
git rebase master
经过变基之后,在branch1的C3,C4提交将被删除,同时,在C2后面将生成C3’,C4’这两个提交,它们和C3,C4的提交内容一模一样,此时在合并branch1,即可以实行快进合并(fast-forword)
使用场景
适合场景
本地未提交至远程的分支上,例如从master上开出一个分支进行开发,开发过程中,其他人将一些提交合并到master分支,此时使用rebase,在进行merge,可以使master的变更历史沿着一条直线前进
不适合场景
已提交至远程仓库的分支上,若你push一个分支到远程仓库,此时其他人已经pull下这条分支进行开发,而你又执行rebase操作,则会使变更历史变得混乱。
git reset
定义
reset命令会移动HEAD到某个commit上
git reset可以用来移除当前分支上的一些提交
操作示例
git reset有三种模式,soft,mixed,hard
- soft:工作空间和暂停区的内容都不会改变
- mixed:默认模式,暂存区的内容将被指定的commit覆盖,而工作空间不受影响
- hard:暂存区和工作空间都被指定的commit覆盖
下面通过实际操作来看这三种模式的区别,首先创建一个git仓库,并新增一个文件file.txt,对文件进行了两次提交,最终log如下图所示
此时file的内容为
下面使用soft模式移除v2提交
git reset --soft dd0d9dbf23b79991536be42cd158538b98ecce37
此时log,git仓库状态以及file文件内容如下图所示
可以看到file文件的内容没有被修改,说明工作空间内容不受影响。
执行git diff可以看到结果为空,说明工作空间和暂存区的内容一致,暂存区也不受影响
下面使用mixed模式移除提交
下面使用hard模式移除提交
使用场景
soft模式
当你仅仅想修改commit msg,并想保留commit的内容时。
mixed模式
当你想在原来提交的基础上重新修改commit的内容时
hard模式(慎用)
当你想完全丢弃一些提交时
git revert
定义
git revert命令会撤销某次提交,但是该提交之前和之后的提交都不会被撤销。git会新生成一个提交来记录此次撤销
操作实例
下图是操作前,log的状态
可以看到总有了三次提交记录,此时我们通过revert操作,撤销v3这次提交
git revert c7c608e38a33c282aa3f08f857d4183b2f3c5575
此时在支持git log,可以看到新增了一次提交,此次提交的影响是回滚了v3提交的操作
总结
- git rebase和merge可以用来合并分支,只不过rebase可以master的提交历史始终沿着一条直线前进,使用rebase或者merge可以视情况而定,注意的是不要在已经push到远程仓库的分支上执行rebase操作
- 注意checkout与reset的区别,checkout某一个文件,会使文件从暂存区中移到工作空间中,checkout HEAD则是进行分支的切换。reset会删除提交历史,而checkout不会
- git revert是通过新生成一个提交来回滚之前提交造成的影响,它不会改变已有历史记录
- 从安全性的角度来看 revert > checkout > reset
#参考文献