-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
Copy pathrebase_all_git_branches.sh
executable file
·207 lines (182 loc) · 5.8 KB
/
rebase_all_git_branches.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# This script assumes that your remote is called "origin"
# and that your local master branch is called "master".
# I am sure it could be made more abstract but these are the defaults.
# Edit this line to point to your default directory,
# or always pass a directory to the script.
DEFAULT_DIR="EDIT_ME"
function print_usage {
cat << __EOF
$0: A script to manage your Apache HBase Git repository.
If run with no arguments, it reads the DEFAULT_DIR variable, which you
can specify by editing the script.
Usage: $0 [-d <dir>]
$0 -h
-h Show this screen.
-d <dir> The absolute or relative directory of your Git repository.
__EOF
}
function get_all_branches {
# Gets all git branches present locally
all_branches=()
for i in `git branch --list | sed -e "s/\*//g"`; do
all_branches+=("$(echo $i | awk '{print($1)}')")
done
}
function get_tracking_branches {
# Gets all branches with a remote tracking branch
tracking_branches=()
for i in `git branch -lvv | grep "\[origin/" | sed -e 's/\*//g' | awk {'print $1'}`; do
tracking_branches+=("$(echo $i | awk '{print($1)}')")
done
}
function check_git_branch_status {
# Checks the current Git branch to see if it's dirty
# Returns 1 if the branch is dirty
git_dirty=$(git diff --shortstat 2> /dev/null | wc -l|awk {'print $1'})
if [ "$git_dirty" -ne 0 ]; then
echo "Git status is dirty. Commit locally first." >&2
exit 1
fi
}
function get_jira_status {
# This function expects as an argument the JIRA ID,
# and returns 99 if resolved and 1 if it couldn't
# get the status.
# The JIRA status looks like this in the HTML:
# span id="resolution-val" class="value resolved" >
# The following is a bit brittle, but filters for lines with
# resolution-val returns 99 if it's resolved
jira_url='https://issues.apache.org/jira/rest/api/2/issue'
jira_id="$1"
curl -s "$jira_url/$jira_id?fields=resolution" |grep -q '{"resolution":null}'
status=$?
if [ $status -ne 0 -a $status -ne 1 ]; then
echo "Could not get JIRA status. Check your network." >&2
exit 1
fi
if [ $status -ne 0 ]; then
return 99
fi
}
# Process the arguments
while getopts ":hd:" opt; do
case $opt in
d)
# A directory was passed in
dir="$OPTARG"
if [ ! -d "$dir/.git/" ]; then
echo "$dir does not exist or is not a Git repository." >&2
exit 1
fi
;;
h)
# Print usage instructions
print_usage
exit 0
;;
*)
echo "Invalid argument: $OPTARG" >&2
print_usage >&2
exit 1
;;
esac
done
if [ -z "$dir" ]; then
# No directory was passed in
dir="$DEFAULT_DIR"
if [ "$dir" = "EDIT_ME" ]; then
echo "You need to edit the DEFAULT_DIR in $0." >&2
$0 -h
exit 1
elif [ ! -d "$DEFAULT_DIR/.git/" ]; then
echo "Default directory $DEFAULT_DIR is not a Git repository." >&2
exit 1
fi
fi
cd "$dir"
# For each tracking branch, check it out and make sure it's fresh
# This function creates tracking_branches array and stores the tracking branches in it
get_tracking_branches
for i in "${tracking_branches[@]}"; do
git checkout -q "$i"
# Exit if git status is dirty
check_git_branch_status
git pull -q --rebase
status=$?
if [ "$status" -ne 0 ]; then
echo "Unable to pull changes in $i: $status Exiting." >&2
exit 1
fi
echo "Refreshed $i from remote."
done
# Run the function to get the list of all branches
# The function creates array all_branches and stores the branches in it
get_all_branches
# Declare array to hold deleted branch info
deleted_branches=()
for i in "${all_branches[@]}"; do
# Check JIRA status to see if we still need this branch
# JIRA expects uppercase
jira_id="$(echo $i | awk '{print toupper($0)'})"
if [[ "$jira_id" == HBASE-* ]]; then
# Returns 1 if the JIRA is closed, 0 otherwise
get_jira_status "$jira_id"
jira_status=$?
if [ $jira_status -eq 99 ]; then
# the JIRA seems to be resolved or is at least not unresolved
deleted_branches+=("$i")
fi
fi
git checkout -q "$i"
# Exit if git status is dirty
check_git_branch_status
# If this branch has a remote, don't rebase it
# If it has a remote, it has a log with at least one entry
git log -n 1 origin/"$i" > /dev/null 2>&1
status=$?
if [ $status -eq 128 ]; then
# Status 128 means there is no remote branch
# Try to rebase against master
echo "Rebasing $i on origin/master"
git rebase -q origin/master > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Failed. Rolling back. Rebase $i manually."
git rebase --abort
fi
elif [ $status -ne 0 ]; then
# If status is 0 it means there is a remote branch, we already took care of it
echo "Unknown error: $?" >&2
exit 1
fi
done
# Offer to clean up all deleted branches
for i in "${deleted_branches[@]}"; do
read -p "$i's JIRA is resolved. Delete? " yn
case $yn in
[Yy])
git branch -D $i
;;
*)
echo "To delete it manually, run git branch -D $deleted_branches"
;;
esac
done
git checkout -q master
exit 0