当某个功能开发完毕之后,需要及时提交commit到当前分支。为了降低代码丢失的风险,需要在恰当的时候把当前分支推送到远程分支。然而,在某些场景下(比如:向分支提交了错误的代码),需要从分支中撤销某个commit的提交。 面对这种实际需求,Git提供了两个命令:git revert
和git reset
。下面详细介绍这两个命令的使用以及区别。
git revert
命令:git revert <commit id>
创建revert commit,其内容为反转某个要撤销commit所引入的更改,向当前分支添加该commit。
原理:不是真正地撤销某个commit,而是利用互补原理,反转该commit所引入的更改。
使用场景 - 撤销某个非merge commit的commit
初始commit log:
1 | B2(B2)---B3(B3)---B4(B4) |
初始文件index.js:
1 | B0 // you, 1 hours ago ∙ B0 |
撤销commit id为B5的commit,删除所提交的代码“B5”
找到提交代码“B5”的commit的commit id,然后执行revert命令:
1 | git revert B5 |
执行命令之后,会自动弹出编辑revert commit message:
1 | Revert "B5" |
保存&退出revert commit message之后,revert commit就会自动添加在当前分支的末端。
结果:在当前分支添加revert commit,“B5”代码被删除。
此时commit log被改为:
1 | B2(B2)---B3(B3)---B4(B4) |
1 | B0 // you, 1 hours ago ∙ B0 |
使用场景 - 撤销某个merge commit
初始commit log:
1 | B2(B2)---B3(B3)---B4(B4) |
B0 // you, 1 hours ago ∙ B0
B1 // you, 2 hours ago ∙ B1
B2 // you, 3 hours ago ∙ B2
B3 // you, 4 hours ago ∙ B3
B4 // you, 5 hours ago ∙ B4
B5 // you, 6 hours ago ∙ B5
1 |
|
git revert B4`
1 |
|
error: commit B4` is a merge but no -m option was given.
fatal: revert failed
1 |
|
git log B4`
commit B4`
Merge: B1 B4
Author: ……
Date: ……
Merge branch 'fix'
……
1 |
|
git revert B4` -m 1
1 |
|
B2(B2)---B3(B3)---B4(B4)
/ \
B0(B0)—B1(B1)—————–B4`(Merge branch ‘fix’)—B5(B5)—B6(Revert “Merge branch ‘fix’”)
1 |
B0 // you, 1 hours ago ∙ B0
B1 // you, 2 hours ago ∙ B1
B5 // you, 6 hours ago ∙ B5
1 |
|
B0(B0)—B1(B1)—B2(B2)—B3(B3)—B4(B4)—B5(B5)
1 |
|
git revert -n startCommitId^..endCommitId
1 |
|
git revert -n commitId1
git revert -n commitId5
git revert -n commitId9
…
1 |
|
B2(B2)---B3(B3)---B4(B4)
/ \
B0(B0)—B1(B1)—————–B4`(Merge branch ‘fix’)—B5(B5)
1 |
|
B0 // you, 1 hours ago ∙ B0
B1 // you, 2 hours ago ∙ B1
B2 // you, 3 hours ago ∙ B2
B3 // you, 4 hours ago ∙ B3
B4 // you, 5 hours ago ∙ B4
B5 // you, 6 hours ago ∙ B5
1 |
|
git reset –hard B4
1 |
|
B2(B2)---B3(B3)---B4(B4)
/ \
B0(B0)—B1(B1)—————–B4`(Merge branch ‘fix’)
1 |
B0 // you, 1 hours ago ∙ B0
B1 // you, 2 hours ago ∙ B1
B2 // you, 3 hours ago ∙ B2
B3 // you, 4 hours ago ∙ B3
B4 // you, 5 hours ago ∙ B4
## 总结:
git revert 和 get reset,这两个命令都可以达到撤销某个commit,删除该commit所提交更改的目的,但原理不一样:
* git revert通过反转的操作,达到目的;优点是,不改变commit log history,通过commit log可以清晰地看到撤销记录。
* git reset通过移除commit,达到目的;优点是,彻底删除某个commit;缺点是,改变了commit log history,不太适合在公共分支上进行操作,除非能承担git reset之后的风险。