开发中git分支管理
研发流程
- 从develop分支切出一个新分支,根据是功能还是bug,命名为id-xxx 或 id-fixbug-*。
- 开发者完成开发,提交分支到远程仓库。
- 开发者发起merge请求,将新分支请求merge到develop分支,并提醒code reviewer进行review(也可以在当前开发分支review)
- code reviewer对代码review之后,若无问题,则接受merge请求,新分支merge到develop分支,同时可删除新建分支;若有问题,则不能- - 进行merge,可close该请求,同时通知开发者在新分支上进行相应调整。调整完后提交代码重复review流程。
- 转测时,直接从当前develop分支merge到pre-release分支,重新构建测试环境完成转测。
- 测试完成后,从pre-release分支merge到master分支,基于master分支构建生产环境完成上线。并对master分支打tag
git命令
问题
- develop merge到 pre-release,发现有bug,此时,我们需要踢出此处merge,在develop分支bugfix,接着在commit,merge
- 此处涉及到一个代码的回退,也就是revert操作,最近在上线过程中,因假期封网,导致必须将已经merge的代码回退,因此有此篇总结
命令解析
- revert 可以取消指定的某次提交内容。
- revert我们在讨论时候,需要分两种情况
- 一种是常规的 commit,也就是使用 git commit 提交的 commit;
- 另一种是 merge commit,在使用 git merge 合并两个分支之后,你将会得到一个新的 merge commit。
- merge commit 和普通 commit 的不同之处在于 merge commit 包含两个 parent commit,代表该 merge commit 是从哪两个 commit 合并过来的。我们可以从git的可视化图形中看出,如下:
-
如上有一个merge commit, 我们将分支 105700s-liaojiamin 合并到master,可以利用git show XXX来查看对应的commit,如下
-
如上对提交 id: fccc479 的查询,得到了 Merge: 5705f77 e4b8f63 这个结构,其中前后两个都是对应的commit id
-
对5705f77 的查询,得到的是具体的修改信息,这样是能明显看出区别的
-
此处我们主要多merge commit进行分析,在前后两个 commit Id中,这代表该 merge commit 是从 5705f77和 e4b8f63两个 commit 合并过来的。
-
如上图中, 5705f77 是原来master的最后一个提交, e4b8f63 是开发分支中的最后一个提交
revert 常规 commit
- 使用 git revert 即可,git 会生成一个新的 commit,将指定的 commit 内容从当前分支上撤除。
revert merge commit
- 我们可以先按常规的方式执行,如下图:
- 提示信息说明:改commit 是一个merge commit,但是执行命令必须添加 -m操作,本次revert 失败
- revert merge commit 有一些不同,按提示我们需要添加 -m 选项以代表这次 revert 的是一个 merge commit
- 但如果直接使用 git revert ,git 也不知道到底要撤除哪一条分支上的内容,这时需要指定一个 parent number 标识出"主线",主线的内容将会保留,而另一条分支的内容将被 revert。
- 如上面的例子中,从 git show 命令的结果中可以看到,merge commit 的 parent 分别为 5705f77 和 e4b8f63,其中 5705f77 代表 master 分支(从图中可以看出),e4b8f63代表 105700s-liaojiamin 分支。需要注意的是 -m 选项接收的参数是一个数字,数字取值为 1 和 2,也就是 Merge 行里面列出来的第一个还是第二个。
-
- 我们要 revert 105700s-liaojiamin 分支上的内容,即 保留主分支,应该设置主分支为主线,操作如下:
git revert -m 1 fccc479
revert 后重新上线
- 当前我们在分支 105700s-liaojiamin 上开发了一个功能,并合并到了 master 上,之后 master 上又提交了一个修改 h,这时提交历史如下:
a -> b -> c -> f -- g -> h (master)\ /d -> e (105700s-liaojiamin)
- 当前我们突然发现开发分支(105700s-liaojiamin)存在严重的 bug,需要 revert 掉,于是大家把 g 这个 merge commit revert 掉了,记为 G,如下:
a -> b -> c -> f -- g -> h -> G (master)\ /d -> e (105700s-liaojiamin)
- 然后在回到原开发分支进行 bugfix,修好之后想重新合并到 master,直觉上只需要再 merge 到 master 即可(或者使用 cherry-pick),像这样:
a -> b -> c -> f -- g -> h -> G -> i (master)\ / /d -> e -> j -> k ---- (105700s-liaojiamin)
- i 是新的 merge commit。但需要注意的是,这 不能 得到我们期望的结果。因为 d 和 e 两个提交曾经被丢弃过,如此合并到 master 的代码,并不会重新包含 d 和 e 两个提交的内容,相当于只有 105700s-liaojiamin 上的新 commit 被合并了进来,而 105700s-liaojiamin 分支之前的内容,依然是被 revert 掉了。
- 所以,如果想恢复整个 105700s-liaojiamin 所做的修改,应该先把 G revert 掉:
a -> b -> c -> f -- g -> h -> G -> G' -> i (master)\ / /d -> e -> j -> k ---------- (105700s-liaojiamin)
- 其中 G’ 是对 G 的 revert 操作生成的 commit,把之前撤销合并时丢弃的代码恢复了回来,然后再 merge 狗蛋的分支,把解决 bug 写的新代码合并到 master 分支。
- 我来执行如下命令
//查找对应commit id
git log --oneline --graph
//回退revert
git revert e56a2ec
- 效果图如下:
- 如上我们找回来了之前revert的代码,并且在master上提交的代码还在,并且存在冲突,我们解决冲突,在master上在commit即可完成