在咱们的一个项目中,有3-4我的在同时开发,目前采用的是AoneFlow的变体进行分支管理,简单来讲,分为四种类型的分支:主干分支(master)、特性分支(feature)、发布分支(release)、开发分支(develop/test)。git
每当新功能需求过来后,会从master切出feature分支进行开发,开发完成后合并到test分支中进行测试。多个功能需求测试完成后,将对应的feature分支合并到release分支,再合并到master分支进行发布。如图: shell
在最近一次项目代码合并的时候发现了两个问题:编辑器
在发现问题后, 通过一个小时的排查,终于发如今某次提交过程当中,咱们的一位开发不当心把test分支合并到了本身的featureA分支上。测试
这意味着,许多开发中的功能被合并到了featureA上。为了解决这个问题,这位同窗经过对比,手动删除了多余的代码,保持了featureA分支只有本身开发的那部分代码,也通过测试经过了。spa
因而分支变成了这个样子:code
在上线代码合并到master的时候,我检查merge request进行例行的code-review,发现确实featureA 功能的提交,因而将featureA 合并到了master准备上线,上线后也没有任何问题。后续的功能也一个一个都提交上去了。cdn
几天后,一个同窗像我反映,在一个新功能的开发中,基于master切出了featureD分支,开发完成后合并到test分支进行测试的时候,出现了不少不是本身开发的代码,我当时就很纳闷,这种模式下test分支永远是领先于master分支的,基于master的分支开发完成后提交到test应该只会有包含本身开发功能的那部分代码才对呀,最可能是产生一些冲突,不会有太多的文件变动。blog
最初怀疑是否是拉错了分支,一看commit记录,发现了问题的根本缘由:开发
在上次featureA 合并到master的时候,虽然没有多余的文件变动,可是featureA合并过test代码,即featureA包含了添加featureB/C, 删除featureB/C的两次commit记录工作流
因此在后续基于Master拉出来的feature分支都会带上这个错误的commit记录,致使:
git checkout featureA
git revert commit_id
复制代码
提示失败了
—m
参数就能够了,1和2表明你要revert哪个父提交,大多数状况是1,即撤销“刚才merge进来的那一个提交”
git revert commit_id -m 1
复制代码
可是这里有个须要注意的地方,若是revert掉某次修改后,若是须要再次merge该分支, 须要再作一次反向revert。 即Revert 掉以前的Revert,不然该分支以前的修改没法被提交,由于已是“落后”于主干分支了。
reset和revert不一样的是:
这里要注意的是,若是在出错的commit版本后还有若干次正确的提交,reset后也会一并消失,须要从新加回来,否则后续正确的代码也会丢失,按照以下操做进行cherry-pick:
git reset --hard commit_id #退回到出错前的一个commit
git cherry-pick commit_id_right #将出错后的commit提交从新加回当前的时间轴
git push -f #强制更新
复制代码
rebase即变基 使用git rebase -i
命令能够压缩合并屡次提交
格式:git rebase -i [startpoint] [endpoint]
其中-i
的意思是interactive,即弹出交互式的界面让用户编辑完成合并操做,[startpoint] [endpoint]则指定了一个编辑区间,若是不指定[endpoint],则该区间的终点默认是当前分支HEAD所指向的commit(注:该区间指定的是一个前开后闭的区间)。
操做方式为:
首先根据git log,找到出错前的一个commit
执行git rebase -i commit_id
合并以前的提交记录
会弹出一个vi编辑器以下:
pick
改成drop
,即丢弃。 Esc :wq
保存
若是出现冲突
git add xxx
git rebase --continue
复制代码
revert
来进行错误回退,并注意后续分支再次合并是否有问题。reset
和rebase
尽可能在私人分支或者未提交到远程的时候使用,若是过去的分支已经提交到远程,会对其余人的本地分支形成影响。