Shell工具-合并社区PR代码脚本

130 阅读2分钟

使用方法

1、第一次合并社区PR代码

sh git_merge_commit.sh -l https://github.com/apache/xx/xx.git -b master -s c -i 3f5021b5d8c701f4ab357777080ac71fcc8c347c

2、之前有已经合并社区PR代码的前提,继续合并社区PR代码

sh git_merge_commit.sh -b master -s c -i 3f5021b5d8c701f4ab357777080ac71fcc8c347c

3、合并社区PR分支到master分支

sh git_merge_commit.sh -s c -i 3f5021b5d8c701f4ab357777080ac71fcc8c347c

4、查看脚本使用方法

sh git_merge_commit.sh 
sh git_merge_commit.sh -h

参数解释

-l:用于指定项目https的格式链接地址。在第一次使用的时候,会将相关信息添加到 .git/config 配置文件中。所以在之后的使用中,可以不用提供。
-b:期望社区代码合并到哪个分支,默认是 master 分支
-s:当前合并PR的状态。c 表示已经合并,u 表示当前尚未合并
-i:与-s参数搭配使用。如果 -s c,则 -i 需要指定当前pr的commitId,如【3f5021b5d8c701f4ab357777080ac71fcc8c347c】格式。如果 -s u,则 -i 需要指定当前pr的 prId,如【12094】格式。

脚本

#!/bin/bash
help() {
    echo "[Example] sh $0 [-l https://xxx.git] [-b branch] -s [c|u] -i [commitId | prId]"
    echo "-l: project git link [http]. optional"
    echo "-b: base branch, optional. default: master"
    echo "-s: current PR status[c: merged. u: unmerged]. required"
    echo "-i: PR information. If it is a submitted PR, use commitId [example: 3f5021b5d8c701f4ab357777080ac71fcc8c347c].
          If it is an unmerged PR, use prId [example: 12094]. required"
    exit -1
}

check_status() {
    if [ $? -eq 0 ];then
        echo $1 "successfully."
    else
        echo $1 "failed."
        exit -1
    fi
}

check_parameter() {
    if [ $# -ne 2 ];then
        echo "ERROR: $1 need to provide a value"
        help
   fi
}

add_link() {
    git remote add upstream $1
    check_status "add upstream"
}

input_git_link() {
    read -p "please input project git link (http): " link
    add_link $link
}

check_add_link() {
    remote_version=$(git remote -v)
    tmp=$(echo $remote_version | grep upstream)
    if [ -z "$tmp" ];then
        if [ -z "$1" ];then
            input_git_link
        else
            add_link
        fi
    fi
}

add_upstream_fetch() {
    config_file=$1
    line=$2

    fetch_config="    fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*"
    sed -i "" "${line}a\
    ${fetch_config}
    " $config_file

    check_status "add upstream fetch config"
}

edit_upstream_config() {
    config_file=./.git/config
    [ ! -f $config_file.bak ] && cp $config_file $config_file.bak

    num=$(cat $config_file | grep -n "refs/remotes/upstream/" | awk -F ":" '{print $1}')

    tmp=$(cat $config_file | grep "refs/remotes/upstream/pr/*")
    if [ -z "$tmp" ];then
        add_upstream_fetch $config_file $num
    fi
}

update_remote() {
    git remote update
}

branch_exists() {
    branch=$(git branch | grep $1)
    if [ -z "$branch" ];then
        return 1
    else
        return 0
    fi
}

checkout_branch() {
    branch_exists $1
    if [ $? -eq 1 ];then
        git checkout -b $1
    else
        git checkout $1
    fi

    check_status "checkout branch : $1"
}

cherry_pick_commited_pr() {
    git cherry-pick $1
    if [ $? -eq 1 ];then
        return -1
    fi
}

cherry_pick_uncommited_pr() {
    pr_id=$1
    git checkout -b pr-$pr_id upstream/pr/$pr_id
    git checkout pr-$pr_id

    git rebase upstream/master

    git diff upstream/master > pr-$pr_id.patch

    git apply --reject pr-$pr_id.patch

    if [ $? -eq 0 ];then
       git commit -a
       rm pr-$pr_id.patch
       git branch -D pr-$pr_id
    else
        echo "************************************************************************************************************"
        echo "* Merge PR failed, please complete the following steps:"
        echo "* 1) The patch that has not been applied is stored in the *. rej file and needs to be manually processed."
        echo "* 2) submit it by 'git commit -a'"
        echo "* 3) rm generated pr-${pr_id}.patch"
        echo "* 4) rm *.rej"
        echo "* 5) git branch -D pr-${pr_id}"
        echo "************************************************************************************************************"
        return -1
    fi
}

cherry_pr() {
    if [ $# -ne 2 ];then
        echo "ERROR: [-s|-i] is null"
        help
    fi

    status=$1
    info=$2
    if [ "$status" == "c" ];then
        cherry_pick_commited_pr $info
    elif [ "$status" == "u" ];then
        cherry_pick_uncommited_pr $info
    else
        echo "ERROR: -s $status not supported"
        help
    fi

    check_status "cherry pick pr"
}


main() {
    [ $# -eq 0 ] && help

    declare link=""
    declare branch="master"
    declare status=""
    declare info=""

    while getopts 'l:b:s:i:h' OPT;do
       case $OPT in
          l) link="$OPTARG";;
          b) branch="$OPTARG";;
          s) status="$OPTARG";;
          i) info="$OPTARG";;
          h) help;;
          ?) help;;
       esac
    done

    check_parameter $status "-s"
    check_parameter $info "-i"

    check_add_link $link
    edit_upstream_config

    update_remote
    checkout_branch $branch

    cherry_pr $status $info
}

main $@

运行环境

Mac