本节概览:通过git revert来实现线主干代码的回滚。如下命令
对于 merge类型的commit对象,还需要“-m”参数
git revert -m 1 commit-id
1
gitrevert-m1commit-id
对于普通的commtit对象
git revert commit-id
1
gitrevertcommit-id
1 问题描述
一个同事不小把自己代码合并 到了master生成C2。但是在该同事还没有回滚之前,又有其他同事合并到master生成了C3。现在问题是我们想要回滚到C1应该怎么做?
2 解决问题
1、选择git revert还是git reset?
git revert是生成新的commit对象,而git reset是删除commit对象,为了保留记录,使用git revert命令。
2、解决
按时间顺序,依次回滚每一个commit对象,直到自己想要的那个commit对象为准。如下:
# 回滚C3 ,c3-id是C3对应的那个commit-id
git revert -m 1 c3-id
# 回滚C2。其中c2-id是C2对应的那个commit-id
git revert -m 1 c2-id
1
2
3
4
5
# 回滚C3 ,c3-id是C3对应的那个commit-id
gitrevert-m1c3-id
# 回滚C2。其中c2-id是C2对应的那个commit-id
gitrevert-m1c2-id
3、上面的命令为什么有“-m 1”?
这是因为上面的C2和C3不是普通的commit对象,都是merge生成的commit对象。如下图,如果需要通过git revert回滚M3,那么此时会在M3后面生成一个新的commit节点R,那么这个新节点R是属于M分支(M1->M2->M3->R)还是D分支(D1->D2->D3->R)呢?此时可以通过“-m” 来指定,如果是1,表示的是当前所在的分支,如果是2表示的是另外的分支。
对于上面的问题,由于我们当前分支是master,我们希望revert之后生成的commit也在master这条分支上,所以指定“-m 1”。
这里需要注意的是,如果只是普通的commit 对象,不是merge类型commit对象(由merge产生commit对象),就不需要”-m 1″了
3 问题总结
后续再遇到代码回滚,通过哪些步骤来做呢?这里总结了一些步骤。
1、假设在master上C0后面有C1、C2、C3三次代码提交,此时需要回滚到C0。
2、回滚步骤如下
(1)第一步切到master代码,使用git log,如下图,获取到每一个commit对象对应的commit-id和commit对象类型(是普通类型还是merge类型)。
commit ee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d
Merge: 8397201 7dc873c
Author: jie01
Date: Thu Oct 12 20:27:33 +0800
Merge branch 'fweb_1-0-806_BRANCH' into master
commit 2f315650dff28e94d654309ed3230c34d32f1000
Author: shan03
Date: Tue Oct 17 14:33:16 +0800
commit 7dc873cd34b8bba1fab68635ddf8331ab2babc74
Merge: cbaf7d9 d24f133
Author: xu01
Date: Thu Oct 12 15:59:13 +0800
Merge branch 'web_1-0-790_BRANCH' into financeweb_1-0-806_BRANCH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
commitee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d
Merge:8397dc873c
Author:jie01
Date:ThuOct1220:27:33+0800
Mergebranch'fweb_1-0-806_BRANCH'intomaster
commit2f315650dff28e94d654309ed3230c34d32f1000
Author:shan03
Date:TueOct1714:33:16+0800
commit7dc873cd34b8bba1fab68635ddf8331ab2babc74
Merge:cbaf7d9d24f133
Author:xu01
Date:ThuOct1215:59:13+0800
Mergebranch'web_1-0-790_BRANCH'intofinanceweb_1-0-806_BRANCH
(2) 第二步按时间倒序,依次执行”git revert”回滚每一个commit对象
对于 merge类型的commit对象,需要“-m”参数
git revert -m 1 commit-id
1
gitrevert-m1commit-id
对于普通的commtit对象
git revert commit-id
1
gitrevertcommit-id
所以回滚命令如下
# 回滚C3,merge类型commit对象,需要-m
git revert -m 1 ee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d
# 回滚C2,普通commit对象
git revert 2f315650dff28e94d654309ed3230c34d32f1000
# 回滚C1,merge类型commit对象,需要-m
git revert -m 1 7dc873cd34b8bba1fab68635ddf8331ab2babc74
1
2
3
4
5
6
7
8
# 回滚C3,merge类型commit对象,需要-m
gitrevert-m1ee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d
# 回滚C2,普通commit对象
gitrevert2f315650dff28e94d654309ed3230c34d32f1000
# 回滚C1,merge类型commit对象,需要-m
gitrevert-m17dc873cd34b8bba1fab68635ddf8331ab2babc74
后续问题
比如说当M3执行了git revet生成RM3,此时在master上又有其他人提交了M4,我们还需要在dev上进行开发D4和D5,如下图
此时怎么合并D5到master的M4
(1)第一步 master合并到D5
因为master执行了git revert撤销操作,所以此时D1和D2的代码会被删除?
在master上执行git revert撤销 RM3
将master合并到dev的D5
(2)第二步 将dev的合并到master
附1 其他方法-通过覆盖方法来实现回滚主干
步骤如下:
第一步 分别拉两份代码。第一份代码上面基于master新建一个分支F1,作为发布分支;第二份代码可以通过git checkout切到自己想要回滚的那个版本上(切到某个commit对象上)。
第二步 删除分支F1对应的代码,把第二份代码拷贝到F1上面,即使用第二份代码覆盖F1的代码。。
第三步提交F1代码,并合并到master。
附2 git revert和git reset区别
1、git revert 。只是撤销某一次commit的操作,并没有删除commit对象;并且会生成一个新的commit对象。
假设分支为m1->m2->m3。当我们”git revet m2″生成m4,此时在m4里面只是把m2的操作撤销了而已,并没有撤销m2和m3对象。此时分支为“m1->m2->m3->m4”
2、git reset。删除某一个commit之后所有commit提交对象;不会产生新的commit对象。
假设m1->m2->m3,当我们git reset m2,此时并没有生成新的commit对象,并且删除了m2和m3两个commit对象,此时分分支为”m1->m2″。
附3 参考
(全文完)