问题
我司的项目都是模块化的,一个大项目下面有很多小项目。某一个开发阶段,开发人员可能要同时修改5-6个项目。
所以,每天早上到办公室的第一件事,我会打开SourceTree
(一个管理Git代码的软件,提供图形化界面),把每个正在开发的项目更新一下(点一下Pull
那个按钮)。
如果有还没来得及 commit 的代码,还要先做备份(这就比较复杂了,需要使用 stash 功能)。
这个过程,一般要花5-10分钟,甚至更久,如果 Git 或者 SourceTree 很慢的话。这一件十分琐碎的工作,需要优化。
解决思路
思路很简单,Git更新项目用到的核心命令是git fetch
/ git pull
。所以,可以结合Shell脚本将这个过程自动化。
最终实现一键更新所有项目。
项目设置
开发使用的是Windows系统,项目路径如下:
C:/codebase/Project_A
C:/codebase/Project_B
C:/codebase/Project_C
存放脚本路径如下:
C:/scripts/git_update.sh
代码
第一部分:读取参数
接受的参数为:项目名 和 branch名
#
# PART 1 - Prep
#
helpFunction()
{
echo ""
echo "Usage: $0 -p param_project -b param_branch"
echo -e " -p, param_project"
echo -e " -b, param_branch"
exit 1 # Exit script after printing help
}
while getopts "p:b:" opt
do
case "$opt" in
p ) param_project="$OPTARG" ;;
b ) param_branch="$OPTARG" ;;
? ) echo "parameter not right"; helpFunction ;; # Print helpFunction in case parameter is non-existent
esac
done
## Print helpFunction in case parameters are empty
if [ -z "$param_project" ] || [ -z "$param_branch" ]
then
echo "Some or all of the parameters are empty";
helpFunction
fi
# Begin script in case all parameters are correct
echo "[INPUT] param_project: $param_project"
echo "[INPUT] param_branch: $param_branch"
第二部分:处理
处理逻辑是这样的:先将任何change备份到一个文件,然后discard;然后pull;最后再将change重新apply回去。
#
# PART 2 - Process
#
# Parse input
DIR_PATH=/c/codebase/
branch=$param_branch
timestamp=`date "+%Y_%m_%d_%H_%M_%S"`
# git backup changes
gitBackupFunction()
{
cd $DIR_PATH/$project
echo "[INFO] current dir is: $PWD";
echo "[GIT] checkout $branch"
git checkout $branch
echo "[GIT] save changes to diff_${branch}_${timestamp}"
git diff > diff_${branch}_${timestamp}
echo "[GIT] reset branch"
git reset --hard
}
# git pull
gitUpdateFunciton()
{
echo "[GIT] fetch $branch"
git -c diff.mnemonicprefix=false -c core.quotepath=false fetch origin
echo "[GIT] pull $branch"
git -c diff.mnemonicprefix=false -c core.quotepath=false pull --rebase origin $branch
}
# git reapply changes
gitReapplyFunction()
{
echo "[GIT] reapply changes from diff_${branch}_${timestamp}"
git apply diff_${branch}_${timestamp}
echo "[GIT] remove temp changes"
rm diff_${branch}_${timestamp}
}
# Loop each project
for project in $param_project
do
echo -e "
##### START TO PROCESS $project #####"
gitBackupFunction
gitUpdateFunciton
gitReapplyFunction
echo -e "##### FINISH TO PROCESS $project #####
"
done
有一点需要说明的是,代码备份+还原,这里使用了git diff
,而没有使用git stash
。原因有二:
git diff
执行起来更快,git stash
经常会卡住一会。git stash
删除起来比较麻烦,它需要指定 stash 队列中的元素位置,而不是名称。
git stash push -m stash_name_with_timestamp
git stash apply stash^{/stash_name_with_timestamp}
# note: can't delete with stash name, have to go with sequence number using git stash drop...
执行
在Windows任意目录下,打开Git Bash
,输入如下命令:
/c/scripts/git_update.sh -p "Project_A Project_B Project_C" -b dev_branch_20201010
这句话的意思是,更新Project A,B,C这三个项目的dev_branch_20201010分支。
定时执行
在Windows下面可以设置定时执行任务。这里就不赘述了。
实际工作中,因为没有计算机的管理员权限,所以我选择了另一种半自动的方法:将所有需要每天执行的脚本命令都放到一个文件。然后早上到了公司就运行一下这个文件,然后再去接水/泡咖啡啦~~~