背景情况:
我们项目如两周一个更新版本,每个人可能同时在开发版本v1,同时也在开发后续需求v2,v3版本。
有两个基础条件:
-
一是,我们所有业务分支v1,v2,v3都是从master拉取
-
二是,我们业务分支可能会去合并公共分支common,比如一些基础设施的调整,或者是公共组件等分支,没期版本都有相应common分支
当,v1版本发布后,master分支已经更新,因为v2,v3分支是上期拉出来的,这次需要根据master分支rebase出修改的代码,所以就需要重建v2,v3分支
另外,我们v2,v3分支可能合并了相应的公共分支,比如common-v2,common-v3
那么比如v2上面的代码是master + common-v2 + 新加的业务代码这三部分组成;common-v2上面的代码是master + 公共v2的代码。现在master分支的已经更新到v1版本,那么此时就要重建这两个分支,那common-v2的代码也需要重建分支,然后再重建v2分支
现在我们重建common-v2分支的步骤:
1、确保master分支已经拉取最新,分支切换到common-v2,在命令行输入 git merge master --no-commit --no-off
,获得common-v2和master的差异代码
2、存储上述差异代码
3、删除common-v2分支的本地分支和远程分支
4、从master拉分支命名为common-v2,此时common-v2和master分支一模一样
5、将第2步差异代码应用到common-v2
6、提交common-v2并push到服务器,重建common-v2完成
现在我们common-v2已经重建完成,接着重建v2分支:
1、确保master分支和common-v2分支已经拉取最新,将分支切换到v2分支,在命令行输入 git merge common-v2 --no-commit --no-off
,获得v2和common-v2的差异代码
2、存储上述差异代码
3、删除v2分支的本地分支和远程分支
4、从master拉分支命名为v2,此时v2和master分支一模一样
5、合并common-v2分支到v2分支
6、将第2步差异代码应用到v2
7、提交v2并push到服务器,重建v2完成
可以看到,不论是重建common-v2还是重建v2过程基本相同,中间涉及很多git命令操作,可以通过shell脚本完成。
执行方式
git checkout v2 // 切换到v2分支
sh rebuild-branch.sh -c common-v2 // 执行重建脚本
重建分支脚本 rebuild-branch.sh
# !/bin/bash
help() {
echo "Usage:"
echo "rebuild-branch.sh [-c COMPARE_BRANCH -b BASE_BRANCH]"
echo "e.g. rebuild-branch.sh -c feature/xxx -b main"
echo "Description:"
echo "COMPARE_BRANCH,比对分支(代码提纯的比对分支),默认是master"
echo "BASE_BRANCH,基准分支(重建所需的基准分支),默认是master"
echo "本脚本作用为将当前执行命令时的分支(需被重建的分支)与COMPARE_BRANCH进行比对,找出差异,并将差异应用到一条从BASE_BRANCH为基准创建的新分支(新分支名仍为需被重建的分支名,原来的需被重建的分支会被重命名并存在本地,用于安全自检。)"
exit -1
}
# Defaults:
# 重建所需的基准分支
BASE_BRANCH=master
# 代码提纯的对比分支
COMPARE_BRANCH=master
# get opts
while getopts ":c:b:h" opt_name
do
case $opt_name in
c) COMPARE_BRANCH=$OPTARG
;;
b)
BASE_BRANCH=$OPTARG
;;
h)
help
;;
?) # 其它未指定名称参数
echo "Unknown argument(s)."
help
exit 2
;;
esac
done
# 确保在根目录
repo_dir=$(git rev-parse --show-toplevel)
# 捕获在项目根目录外执行脚本
if [ $? -ne 0 ];then
exit
fi
cd $repo_dir
branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$branch" == "$COMPARE_BRANCH" ]]; then
echo "当前分支是$COMPARE_BRANCH(代码对比取差异的分支),请切换到你的工作分支"
exit
elif [[ "$branch" == "$BASE_BRANCH" ]]; then
echo "当前分支是$BASE_BRANCH(重建所基准的分支),请切换到你的工作分支"
exit
else
echo "需要被重建的分支:$branch"
echo "代码比对提纯分支:$COMPARE_BRANCH"
echo "重建所需基准分支:$BASE_BRANCH"
echo "【请确认上述信息,输入y/n/h】?y 继续 n 放弃 h 查看帮助文档"
read makesure
if [[ "$makesure" == "y" ]];then
echo "重建分支开始 !"
elif [[ "$makesure" == "h" ]];then
help
else
exit
fi
fi
# 检出比对分支
git checkout $COMPARE_BRANCH
# 捕获上一步错误
if [ $? -ne 0 ];then
echo "git checkout ${COMPARE_BRANCH} error"
exit
fi
# 拉取最新代码
git pull
# 将当前分支往比对分支上合并提取差异
result="$(git merge $branch --no-commit --no-ff)"
if [[ $result == *conflict* ]];then
echo "失败!存在冲突,请自行打开vscode解决,解决完后,输入y继续执行,输入n放弃并退出!"
git merge --continue
echo "【请输入y/n】?y 我已解决完 n 放弃合并"
read constep
if [[ "$constep" == "y" ]];then
echo "您选择了我已解决完继续执行"
# 暂存差异
git add .
# 将差异储藏
git stash
# result=`git merge --continue`
else
echo "您选择了放弃合并,自动退出"
git merge --abort
git checkout $branch
exit
fi
else
# 将差异储藏
git stash
fi
# git merge --abort
# 切换到需要被重建的分支
git checkout $branch
# 捕获上一步错误
if [ $? -ne 0 ];then
echo "git checkout ${branch} error"
exit
fi
echo "【请输入y/n】合并正常,是否继续?"
read ispopstash
if [[ "$ispopstash" == "y" ]];then
newbranch="$branch-$(date "+%d-%H-%M-%S")"
echo $newbranch
# 备份旧分支
git branch -m $branch $newbranch
# 检出备份分支并去掉备份分支远程跟踪关系
git checkout $newbranch
git branch --unset-upstream
# 检出基准分支
git checkout $BASE_BRANCH
git pull
# 从基准分支新建一条原分支名的分支
git checkout -b $branch
echo "【请输入y/n】分支已备份,从$BASE_BRANCH新建的纯净分支(这次未应用存储),是否推送到服务器?"
read puremaster
if [[ "$puremaster" == "y" ]];then
echo "推送纯净分支"
git push -f --set-upstream origin $branch
else
echo "未推送纯净分支,后续可一起推"
fi
echo "【请输入y/n】是否合并比较分支并推送?"
read comparebranch
if [[ "$comparebranch" == "y" ]];then
echo "合并比较分支并推送"
# 合并比较分支
git merge --commit --no-edit $COMPARE_BRANCH
git push -f --set-upstream origin $branch
else
echo "未推送比较分支,后续可一起推"
fi
# 应用最近一次的代码储藏,即之前提纯的代码
result="$(git stash pop)"
if [[ $result == *conflict* ]];then
echo "应用提纯的代码失败!存在冲突,请自行打开vscode解决"
echo "【请输入y/n】?y 我已解决完 n 放弃合并"
read constep
if [[ "$constep" == "y" ]];then
echo "您选择了我已解决完继续执行"
git add .
else
echo "您选择了放弃合并,自动退出"
git merge --abort
git checkout $branch
exit
fi
else
# 无冲突
git add .
fi
echo "【请输入y/n】已应用存储,是否提交并推送到服务器?"
read ispush
if [[ "$ispush" == "y" ]];then
git commit -m "feature: 新建分支$branch"
if [[ "$puremaster" == "y" ]];then
git push -f
else
git push -f --set-upstream origin $branch
fi
echo "重建完成,本地原分支备份为$newbranch可移除"
else
echo "您选择了放弃推送,请手动推送后续操作"
exit
fi
else
echo "您选择了放弃合并,自动退出"
exit
fi