实现gitlab下主干开发模式的CR流程
背景
GitLab下不具备gerrit那样的commit级别的CR的机制,多人在开发同一个功能的时候,往往是都大家拉出各自的分支,然后往开发分支上进行合并,如果开发过程中依赖对方实现的逻辑,那么这个合并过程就非常繁琐。要么就是开发过程中不做CR,大家都在一个分支上开发,最后在集中进行CR,那么这个时候功能开发得差不多了,CR的粒度就非常大,可能就会涉及到大量的代码逻辑调整。基于这种现状,这里尝试探索一种新的CR方式:边开发边CR,简化CR协同流程
实现思路
这里以master分支为例,来说下具体的流程:
1.master分支设置为保护模式:不允许任何人提交,需要通过MR的方式合入代码.
2.大家都在本地都在master分支上写代码,不需要拉出feature分支.
3.写完代码后,直接git push推送是不成功的,这个时候需要使用git cr命令来替代git push.
4.git cr命令执行后会先同步远端master代码带本地,若有冲突在本地解决,无冲突则将本地代码推送到远端临时分支,同时发起一个MR合并请求.
5.在MR里做CR,CR通过后即可合入master.
借助GitLab下的Push Options思路,来实现这种机制,Push Options详细介绍:https://docs.gitlab.com/ee/user/project/push_options.html
实现代码
package main import ( "fmt" "os/exec" "strings" "github.com/pkg/errors" ) func gitBranch() (branch string, err error) { cmd := exec.Command("/bin/bash", "-c", "git rev-parse --abbrev-ref HEAD") out, err := cmd.CombinedOutput() if err != nil { err = errors.Wrap(err, "请在git仓库目录下运行!!!") return } branch = strings.TrimSpace(string(out)) return } func gitUser() (username string, err error) { cmd := exec.Command("/bin/bash", "-c", "git config user.name") out, err := cmd.CombinedOutput() if err != nil { err = errors.Wrap(err, "请在git仓库目录下运行!!!") return } username = strings.TrimSpace(string(out)) return } func gitPull(branch string) error { fmt.Printf("开始同步分支 %s 远端代码到本地...\n", branch) shell := ` #!/bin/bash set -e export TARGET_BRANCH="%s" RES=$(git ls-remote --heads origin refs/heads/${TARGET_BRANCH}) if [[ "RES" == "" ]]; then echo "远端仓库里不存在分支:${TARGET_BRANCH},请先创建好该分支" exit 1 fi git pull origin ${TARGET_BRANCH} ` args := []string{"-c", fmt.Sprintf(shell, branch)} cmd := exec.Command("/bin/sh", args...) out, err := cmd.CombinedOutput() if err != nil { err = errors.Wrapf(err, "执行失败,错误信息如下:\n%s", string(out)) return err } fmt.Println("同步远端代码到本地成功.") return nil } func gitPush(username, branch string) error { fmt.Println("推送代码到远端仓库并发起评审任务...") shell := ` #!/bin/bash set -e export USER_NAME="%s" export TARGET_BRANCH="%s" export SOURCE_BRANCH="cr/${USER_NAME}/${TARGET_BRANCH}" git push origin HEAD:${SOURCE_BRANCH} \ -o merge_request.create \ -o merge_request.title="%s" \ -o merge_request.target=${TARGET_BRANCH} \ -o merge_request.source=${SOURCE_BRANCH} \ -o merge_request.remove_source_branch=true ` args := []string{"-c", fmt.Sprintf(shell, username, branch, fmt.Sprintf("%s merge code into %s", username, branch))} cmd := exec.Command("/bin/sh", args...) out, err := cmd.CombinedOutput() if err != nil { err = errors.Wrapf(err, "执行失败,错误信息如下:\n%s", string(out)) return err } fmt.Println("推送代码并创建评审任务成功,详情如下:") fmt.Println(string(out)) return nil } func main() { branch, err := gitBranch() if err != nil { fmt.Println(err) return } username, err := gitUser() if err != nil { fmt.Println(err) return } if err = gitPull(branch); err != nil { fmt.Println(err) return } if err = gitPush(username, branch); err != nil { fmt.Println(err) return } }
代码已提交到github,链接地址为:https://github.com/5bug/git-cr