Skip to content

Instantly share code, notes, and snippets.

@wingyiu
Created November 24, 2017 01:39
Show Gist options
  • Save wingyiu/42f275b1be86615fe78996fc9adcbd0e to your computer and use it in GitHub Desktop.
Save wingyiu/42f275b1be86615fe78996fc9adcbd0e to your computer and use it in GitHub Desktop.
#!/bin/bash
SCRIPT_DIR=`readlink -f $(dirname $0)`
CONFNAME=git.conf
CFG_FILE=${SCRIPT_DIR}/${CONFNAME}
# 默认配置
DIR=/tmp/boss/publish
# 加载自定义配置
if [[ -f ${CFG_FILE} ]];then
source ${CFG_FILE}
fi
SOURCE_REPO=$2
PROJECT=`echo ${SOURCE_REPO}|awk -F'/' 'gsub(/.git/,"",$2){print $2}'`
PRO_DIR=${DIR}/${PROJECT}
TIMESTAMP=`date +"%Y%m%d%H%M%S"`
#func
Usage() {
echo "Usage:"
echo " $0 <function> <git_repo> [parameter1] [parameter2] ..."
echo " [function] Specify the function you need"
echo " [git_repo] Specify the git address"
echo " [parameter] Specify the other parameters you need"
echo "Example:"
echo " $0 branch_head git@repo.we.com:java/ps-hello.git master"
echo " $0 branch_tail git@repo.we.com:java/ps-hello.git master"
echo " $0 online_head git@repo.we.com:java/ps-hello.git"
echo " $0 branches git@repo.we.com:java/ps-hello.git"
echo " $0 branch_commits git@repo.we.com:java/ps-hello.git dev 0 15"
echo " $0 diffs git@repo.we.com:java/ps-hello.git 797666c d3bd4bd"
echo " $0 diff_files git@repo.we.com:java/ps-hello.git 797666c d3bd4bd"
echo " $0 diff_file_content git@repo.we.com:java/ps-hello.git 797666c d3bd4bd pom.xml"
echo " $0 release git@repo.we.com:wingyiu.li/ps-asdfsf.git e932c47 /data/boss/cmdb/log/publish_1073.log"
echo " $0 recover_release git@repo.we.com:wingyiu.li/ps-asdfsf.git /data/boss/cmdb/log/publish_1073.log"
echo " $0 rollback_release git@repo.we.com:wingyiu.li/ps-asdfsf.git /data/boss/cmdb/log/publish_1073.log"
echo " $0 archive git@repo.we.com:wingyiu.li/ps-asdfsf.git /data/boss/cmdb/log/publish_1073.log"
echo " $0 rollback_online git@repo.we.com:wingyiu.li/ps-asdfsf.git e298328 /data/boss/cmdb/log/publish_1073.log"
echo " $0 commit_file git@repo.we.com:wingyiu.li/ps-asdfsf.git e298328 pom.xml"
echo " $0 commit_tree git@repo.we.com:wingyiu.li/ps-asdfsf.git e298328"
}
function log() {
echo "`date +"%F %T"` $@"
# echo "`date +"%F %T"` $@" >> ${SCRIPT_DIR}/git.log
}
function ensure_repo() {
if [[ ! -d ${DIR} ]];then
mkdir -p ${DIR}
fi
cd ${DIR}
if [[ ! -d ${PRO_DIR} ]];then
git clone ${SOURCE_REPO}
if [[ $? -ne 0 ]];then
log "[ERROR] <${SOURCE_REPO}> clone fail"
exit 1
fi
fi
cd ${PRO_DIR}
git fetch origin
}
function ensure_branch() {
local branch=$1
local remote_br="remotes/origin/${branch}"
ensure_repo
cd ${PRO_DIR}
ck_result=`git branch -a | grep ${remote_br}`
if [[ -n ${ck_result} ]];then
# git checkout ${branch}
git update-ref refs/heads/${branch} origin/${branch}
else
git checkout -b ${branch}
fi
}
#function: release
#description: 发布,返回合并后的SHA
function release() {
local commit=$1
local logfile=$2
echo '--------------拉release,合并到release------------------' &>> ${logfile}
ensure_branch master &>> ${logfile}
cd ${PRO_DIR}
# TODO 如果已经有release,表示有正在进行的发布,不应该允许再来一个
git checkout -b release &>> ${logfile}
# TODO 判断master和online是否在一起?
# TODO 如果release 和 commit在同一个commit
merge_log=`git merge --no-ff --commit ${commit}`
if [[ $? -ne 0 ]];then
log "[ERROR] merge ${commit} fail: ${merge_log}"
log ${merge_log}
exit 1
fi
echo $merge_log &>> ${logfile}
git push origin release &>> ${logfile}
merged=`git log --pretty=format:"%H" --max-count=1 release`
echo "合并后COMMIT:${merged}" &>> ${logfile}
echo ${merged}
echo '----------------------------------------------' &>> ${logfile}
}
#function: recover_release
#description: merge失败后恢复
function recover_release() {
local logfile=$1
echo '--------------恢复------------------' &>> ${logfile}
ensure_branch master &>> ${logfile}
cd ${PRO_DIR}
git checkout master &>> ${logfile}
git reset --hard HEAD
git branch -D release
echo '----------------恢复完毕------------------------' &>> ${logfile}
}
#function: archive
#description: master和online回归
function archive() {
local logfile=$1
echo '--------------master和online归档------------------' &>> ${logfile}
ensure_repo &>> ${logfile}
cd ${PRO_DIR}
git checkout master &>> ${logfile}
git pull origin master &>> ${logfile}
git merge --ff origin/release &>> ${logfile}
if [[ $? -ne 0 ]];then
log "[ERROR] merge origin/release fail"
exit 1
fi
TAG="tag-${TIMESTAMP}"
git tag $TAG &>> ${logfile}
git push --tags origin master &>> ${logfile}
git push origin --delete release &>> ${logfile}
git branch -D release &>> ${logfile}
local check_online=`git branch -a | grep 'online'`
if [[ -z ${check_online} ]];then
git checkout -b online &>> ${logfile}
git merge --ff origin/master &>> ${logfile}
git push --tags origin online &>> ${logfile}
else
git checkout online &>> ${logfile}
git merge --ff origin/master &>> ${logfile}
git push --tags origin online &>> ${logfile}
fi
echo "打标签为:$TAG" &>> ${logfile}
echo $TAG
echo '----------------------------------------------' &>> ${logfile}
}
#function: rollback_release
#description: 回滚发布分支
function rollback_release() {
local logfile=$1
echo '--------------回滚release------------------' &>> ${logfile}
cd ${PRO_DIR}
local check_release=`git branch -a | grep 'release'`
if [[ -n ${check_release} ]];then
git checkout master &>> ${logfile}
git push origin --delete release &>> ${logfile}
git branch -D release &>> ${logfile}
else
log "[ERROR] release branch not existed"
exit 1
fi
echo '----------------------------------------------' &>> ${logfile}
}
#function: rollback_online
#description: 回滚线上分支,需指定回滚到那个commit
function rollback_online() {
local last_commit=$1
local logfile=$1
echo '--------------回滚online------------------' &>> ${logfile}
ensure_repo &>> ${logfile}
cd ${PRO_DIR}
git checkout online &>> ${logfile}
git reset --hard ${last_commit} &>> ${logfile}
git push --force origin online &>> ${logfile}
echo '----------------------------------------------' &>> ${logfile}
}
#function: diff_files
#description: 两个commit间的差异文件
function diff_files() {
local sha_start=$1
local sha_end=$2
ensure_repo &> /dev/null
cd ${PRO_DIR}
git diff --name-status ${sha_start} ${sha_end}
}
#function: diff_file_content
#description: 两个commit间的某文件的内容差异
function diff_file_content() {
local sha_start=$1
local sha_end=$2
local file=$3
ensure_repo &> /dev/null
cd ${PRO_DIR}
git diff ${sha_start} ${sha_end} -- ${file}
}
#function: diffs
#description: 两个commit间的差异
function diffs() {
local sha_start=$1
local sha_end=$2
local file=$3
ensure_repo &> /dev/null
cd ${PRO_DIR}
git diff ${sha_start} ${sha_end}
}
#function: branches
#description: 所有分支(远端)
function branches() {
ensure_repo &> /dev/null
cd ${PRO_DIR}
git branch -r | grep -v HEAD | sed s/\ //g
}
#function: branch_commits
#description: 某个分支的commit log,树形,分页
function branch_commits() {
local branch=$1
local offset=$2
local limit=$3
ensure_repo &> /dev/null
cd ${PRO_DIR}
git log --graph --date-order --pretty=format:"<%H | %cn | %ci | %s>" --skip=${offset} --max-count=${limit} origin/${branch} --
}
#function: branch_head
#description: 当前某个分支的最新commit
function branch_head() {
local branch=$1
ensure_branch ${branch} &> /dev/null
cd ${PRO_DIR}
git log --pretty=format:"%H" --max-count=1 origin/${branch} --
}
#function: branch_tail
#description: 当前某个分支的最旧commit
function branch_tail() {
local branch=$1
ensure_branch ${branch} &> /dev/null
cd ${PRO_DIR}
git log --pretty=format:"%H" origin/${branch} | tail -n 1
}
#function: commit_file
#description: commit中某个文件的内容
function commit_file() {
local commit=$1
local path=$2
ensure_repo &> /dev/null
cd ${PRO_DIR}
git show ${commit}:${path}
}
#function: commit_tree
#description: commit中所有文件
function commit_tree() {
local commit=$1
ensure_repo &> /dev/null
cd ${PRO_DIR}
git ls-tree -r --name-only ${commit}
}
#function: current_publog
#description: 某个app最新的发布过程日志文件名
function current_publog() {
local appid=$1
local dir=$2
cd ${dir}
local ticket=`find . -type f -name "${appid}_*.log" | awk -F'[/_.]' '{ print $4}' | sort -r | head -n 1`
echo ${appid}_${ticket}.log
}
#function: log_content
#description: 分行获取某个日志文件名的内容,有多少拿多少
function log_content() {
local file=$1
local offset=$2
tail -c +${offset} ${file}
}
#function: release_vue
#description: 发布VUE,返回x后的SHA
function release_vue() {
local branch=$1
local previous_master=$2
local commit=$3
local logfile=$4
echo '-----------------合并到master------------------' &>> ${logfile}
ensure_branch master &>> ${logfile}
ensure_branch ${branch} &>> ${logfile}
cd ${PRO_DIR}
git checkout ${branch} &>> ${logfile}
diff_files=`git diff --name-status ${previous_master} ${commit}`
local fss=(`git diff --name-status ${previous_master} ${commit} | awk '{print $1}'`)
local fns=(`git diff --name-status ${previous_master} ${commit} | awk '{print $2}'`)
for i in ${!fss[@]}
do
if [[ ${fss[$i]} == "D" ]]; then
git rm ${fns[$i]} &>> ${logfile}
else
git checkout ${commit} -- ${fns[$i]} &>> ${logfile}
fi
done
git commit -am "+${commit}" &>> ${logfile}
git push origin ${branch} &>> ${logfile}
merged=`git log --pretty=format:"%H" --max-count=1 ${branch} -- `
echo "新COMMIT:${merged}" &>> ${logfile}
echo ${merged}
echo '----------------------------------------------' &>> ${logfile}
}
#function: rollback_vue
#description: 回滚VUE,返回x后的SHA
function rollback_vue() {
local branch=$1
local previous_master=$2
local commit=$3
local logfile=$4
echo '-----------------合并到master------------------' &>> ${logfile}
ensure_branch master &>> ${logfile}
ensure_branch ${branch} &>> ${logfile}
cd ${PRO_DIR}
git checkout ${branch} &>> ${logfile}
diff_files=`git diff --name-status ${commit} ${previous_master}`
local fss=(`git diff --name-status ${commit} ${previous_master} | awk '{print $1}'`)
local fns=(`git diff --name-status ${commit} ${previous_master} | awk '{print $2}'`)
for i in ${!fss[@]}
do
if [[ ${fss[$i]} == 'D' ]]; then
git rm ${fns[$i]} &>> ${logfile}
else
git checkout ${previous_master} -- ${fns[$i]} &>> ${logfile}
fi
done
git commit -am "-${commit}" &>> ${logfile}
git push origin ${branch} &>> ${logfile}
merged=`git log --pretty=format:"%H" --max-count=1 ${branch}`
echo "新COMMIT:${merged}" &>> ${logfile}
echo ${merged}
echo '----------------------------------------------' &>> ${logfile}
}
#function: archive_vue
#description: 发布VUE,返回x后的SHA
function archive_vue() {
local branch=$1
local previous_master=$2
local commit=$3
local logfile=$4
echo '-----------------合并到master------------------' &>> ${logfile}
ensure_branch master &>> ${logfile}
ensure_branch ${branch} &>> ${logfile}
cd ${PRO_DIR}
git checkout master &>> ${logfile}
merge_log=`git merge --no-ff --commit ${commit}`
if [[ $? -ne 0 ]];then
log "[ERROR] merge ${commit} fail: ${merge_log}"
log ${merge_log}
exit 1
fi
echo $merge_log &>> ${logfile}
git push origin master &>> ${logfile}
merged=`git log --pretty=format:"%H" --max-count=1 ${branch} -- `
echo "新COMMIT:${merged}" &>> ${logfile}
echo ${merged}
echo '----------------------------------------------' &>> ${logfile}
}
#function: commit_info
#description: commit基本信息
function commit_info() {
local commit=$1
ensure_repo &> /dev/null
cd ${PRO_DIR}
git log ${commit} -1 --abbrev=40
}
function listfunc() {
echo -e "\nAvailable functions example:\n"
local func_list=(`grep '^#function:' $0 | awk '{print $2}'`)
local func_desc=(`grep '^#description:' $0 | awk '{print $2}'`)
for i in ${!func_list[@]}
do
printf "%-20s %s %s\n" ${func_list[$i]} \#${func_desc[$i]}
done
}
case $1 in
release)
release $3 $4
;;
release_vue)
release_vue $3 $4 $5 $6
;;
recover_release)
recover_release $3
;;
archive)
archive $3
;;
rollback_release)
rollback_release $3
;;
rollback_online)
rollback_online $3 $4
;;
rollback_vue)
rollback_vue $3 $4 $5 $6
;;
branches)
branches
;;
diffs)
diffs $3 $4
;;
diff_files)
diff_files $3 $4
;;
diff_file_content)
diff_file_content $3 $4 $5
;;
branch_commits)
branch_commits $3 $4 $5
;;
branch_head)
branch_head $3
;;
branch_tail)
branch_tail $3
;;
commit_file)
commit_file $3 $4
;;
commit_info)
commit_info $3
;;
commit_tree)
commit_tree $3
;;
current_publog)
current_publog $2 $3
;;
log_content)
log_content $2 $3 $4
;;
-h)
Usage
listfunc
exit 0
;;
*)
log "[ERROR] error options"
Usage
listfunc
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment