forked from satanson/cpp_etudes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcherry-pick.sh
executable file
·153 lines (131 loc) · 3.42 KB
/
cherry-pick.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/bin/bash
# Copyright (c) 2020 Ran Panfeng. All rights reserved.
# Author: satanson
# Email: [email protected]
# Github repository: https://github.com/satanson/cpp_etudes.git
#
#basedir=$(cd $(dirname ${BASH_SOURCE:-$0});pwd);
#cd ${basedir}
branch_exists(){
local br=${1:?"branch"};shift
local res=$(git branch -v |perl -lne "print qq/ok/ if /^\\s*(\\*\\s*)?$br\\s+/"|head -1)
if [ -n "$res" ];then
return 0;
else
return 1;
fi
}
ensure_branch_exists(){
if !(branch_exists $1);then
echo "ERROR: branch $1 not exists " >&2;
exit 1
fi
}
ensure_branch_not_exists(){
if (branch_exists $1);then
echo "ERROR: branch $1 exists " >&2
exit 1
fi
}
branch_current(){
git branch -v |perl -lne "print \$1 if /^\\s*\\*\\s*(\\S+)\\s+/"|head -1
}
current_branch_is(){
local br=${1:?"branch"};shift
local cbr=$(branch_current)
if [ "x${br}x" != "x${cbr}x" ];then
return 1
else
return 0
fi
}
ensure_current_branch(){
local br=${1:?"branch"};shift
if !(current_branch_is $br);then
echo "ERROR: not on branch '${br}', current branch is '$(branch_current)'" >&2
exit 1
fi
}
branch_switch(){
local br=${1:?"branch"};shift
if (current_branch_is $br);then
echo "INFO: already on current branch '$br'";
elif (branch_exists $br);then
git checkout $br
else
git checkout -b $br;
fi
ensure_current_branch $br;
}
branch_rename(){
local br0=${1:?"branch0"};shift
local br1=${1:?"branch1"};shift
ensure_branch_exists $br0
ensure_branch_not_exists $br1
git branch -m $br0 $br1
}
now_ts(){
date +"%Y%m%d_%H%M%S"
}
branch_backup(){
local br=${1:?"branch"};shift
local br_backup="${br}.backup.$(now_ts)"
branch_rename ${br} ${br_backup}
echo ${br_backup}
}
branch_topmost_commits(){
local br=${1:?"branch"};shift
local n=${1:?"num"};shift
ensure_branch_exists ${br}
git log -${n} --pretty=oneline ${br} |perl -lne 'print $1 if /^(\S+)\s/' |tac
}
branch_cherry_pick_one(){
local cmt=${1:?"commit"};shift
git cherry-pick ${cmt}
}
branch_fetch(){
local br=${1:?"branch"};shift
git fetch origin ${br}:${br}
}
cherry_pick() {
local br0=${1:?"base branch"};shift
local br1=${1:?"target branch"};shift
local n=${1:?"num"};shift
local fetch_latest=${1:?"fetch_latest"};shift
# force fetch latest branch
if [ "x${fetch_latest}x" = "xfetchx" ];then
if (branch_exists ${br0}); then
branch_backup ${br0}
fi
ensure_branch_not_exists ${br0}
branch_fetch ${br0}
fi
# fetch if not exists br0
if ! (branch_exists ${br0});then
branch_fetch ${br0}
fi
ensure_branch_exists ${br0}
ensure_branch_exists ${br1}
local br1_tmp=${br1}.tmp.$(now_ts)
branch_switch ${br0}
ensure_current_branch ${br0}
ensure_branch_not_exists ${br1_tmp}
branch_switch ${br1_tmp}
ensure_current_branch ${br1_tmp}
for cmt in $(branch_topmost_commits ${br1} ${n});do
branch_cherry_pick_one ${cmt}
done
branch_switch ${br0}
ensure_current_branch ${br0}
branch_backup ${br1}
branch_rename ${br1_tmp} ${br1}
ensure_branch_exists $br1
branch_switch $br1
}
set -e -o pipefail
baseBranch=${1:?"missing <baseBranch>"};shift
targetBranch=${1:?"missing <targetBranch>"};shift
commitNum=${1:?"missing <commitNum>"};shift
fetchLatest=${1:?"missing <fetchLatest>"};shift
echo "cherry-pick ${commitNum} commits from ${targetBranch} to ${baseBranch} fetchLatest=${fetchLatest}"
cherry_pick ${baseBranch} ${targetBranch} ${commitNum} ${fetchLatest}