reset与revert
异同点
共同点:
reset
和revert
都是用于回退已提交代码的命令。但在具体使用时又各有侧重
点。
区别:
-
revert
会反做指定的commit_id
的代码并生成一次新的commit提交记录,reset
会删除commit_id
前面的提交记录。 - 在
merge
老的代码时因为revert是提交撤回,所以合并后不会有撤回的内容,但reset是改变指针位置,所以撤回的内容依然存在。所以,reset
经常用于回退版本,revert
用于修改某次提交。 -
reset
是把HEAD向后移动了一下,而revert
是HEAD继续前进,增加一个撤销的commit。
使用方法
1. add 的回退
HEAD 表示当前版本 HEAD^
表示上一个版本,HEAD^^
表示上上个版本, HEAD~100
表示上100个版本。
$ git reset HEAD . // 撤回所有的add提交
$ git reset HEAD filename // 撤回某一个文件或文件夹
2. commit 回退
$ git reset --mixed commit_id // 默认 mixed 回退命令及stage(index)
$ git reset --soft commit_id // soft 只回退提交m信息,stage(index)仍然保留
$ git reset --hard commit_id // hard 回退命令及文件的修改内容
// 或者
$ git revert -n commit_id
commit_id 可以通过命令git log
来查看, 且commit_id不需要写全,只要写6位左右git就会自动找到了。
3. merge回退
执行以下合并命令
# git:(dev)
git checkout master
# git:(master)
git merge dev
合并后生成新的提交 branch_merge
, 后面又有人继续开发,形成了如下的提交历史记录
init -> v1 -> v2 -> v3 -- branch_merge -> v4 -> vc3 (master)
\ \ / /
\ d1 --> d2 --> d3 --> d4 (dev)/
\ /
c1 --> c2 -------------------c3 (other)
此时在master分支上发现一个bug,经检查是由d2造成的,需要回退代码。使用reset的话会把other分支上的合并提交页干掉,不行,那只能使用revert回退。已合并的分支直接回退会报错
git revert branch_merge
error: Commit faulty merge is a merge but no -m option was given.
fatal: revert failed
这是因为合并后的分支系统不知道该退回到哪一条分支的上一次提交,所以需要我们告诉要保留的主线-m(mainline)
是哪个
git revert -m 1 branch_merge
-m
后面带的参数值 可以是1或者2, merge 上来的分支(d2)是2,当前所在分支(v3)是1
4. 合并分支回退后再合并
当dev分支修改了bug时需要再合并,但是因为有回退的提交历史,所以d2将不会合并到master上。此时只要我们再次反向提交一次,把回退回退掉就可以了。
git revert rev3
git merge dev
此处rev3
是一个常规commit,其内容包含了之前在branch_merge撤销掉的dev合并过来的commit的【反操作】的合集。
撤销回退
撤销回退需要我们知道上一次的cmmit_id,只是这个已经无法在历史中看到了,这就需要我们使用另一个命令来查看
$ git reflog // 查看命令历史
丢弃工作区的修改
$ git checkout -- filename // -- 非常重要,如果没有它的话就变成了切换分支了