-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathrebasebranch
executable file
·146 lines (108 loc) · 3.2 KB
/
rebasebranch
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
#!/bin/bash
rebasebranch() {
if [ "" == "${NEW_BASELINE}" ]; then
return 0
fi
local STASH=$(git status -s | grep -v '??')
if [ "" != "$STASH" ]; then
git stash
fi
if rollbackbranch; then
if [ "" != "$STASH" ]; then
git stash pop
fi
return 0
fi
echo "Rebasing against $SHORT_NAME ($NEW_BASELINE)"
git rebase $NEW_BASELINE
EXIT_STATUS=$?
if [ "" != "$STASH" ]; then
if [[ 0 -ne $EXIT_STATUS ]]; then
echo "Failed to rebase against $NEW_BASELINE, restoring git stash"
git rebase --abort
git stash pop
else
git stash pop
EXIT_STATUS=$?
fi
fi
return $EXIT_STATUS
}
resetbasebranch() {
CURRENT_HASH=$(git log -1 --pretty='%H')
if [ "" == "${NEW_BASELINE}" ]; then
return 0
fi
if git merge-base --is-ancestor $CURRENT_HASH $NEW_BASELINE; then
git merge --ff-only $NEW_BASELINE
return $?
fi
CLOSEST_ANCESTOR=
CLOSEST_COUNT=$(git rev-list --count HEAD)
for remote in $(git remote); do
local ANCESTOR=$(git for-each-ref --format='%(refname)' refs/remotes/ | grep "/${remote}/${BASE_BRANCH}$" | cut -d'/' -f 3,4)
if [ "" == "$ANCESTOR" ]; then
continue
fi
local COUNT=$(git log --pretty='%H' ${ANCESTOR}..${CURRENT_HASH} | wc -l)
echo "$(git rev-parse --abbrev-ref HEAD) differs from ${ANCESTOR} by ${COUNT} commits"
if [[ $COUNT -lt $CLOSEST_COUNT ]]; then
CLOSEST_ANCESTOR=$ANCESTOR
CLOSEST_COUNT=$COUNT
fi
done
if [[ 0 -eq ${CLOSEST_COUNT} ]]; then
echo "Resetting $(git rev-parse --abbrev-ref HEAD) to ${BASE_BRANCH} baseline because there are no unique commits"
git reset --hard $NEW_BASELINE
return $?
fi
if ! git merge-base --is-ancestor $NEW_BASELINE $CURRENT_HASH; then
git rebase $NEW_BASELINE
return $?
fi
}
rollbackbranch() {
CURRENT_HASH=$(git log -1 --pretty='%H')
if [ "${CURRENT_HASH}" == "${NEW_BASELINE}" ]; then
return 0
fi
git merge-base --is-ancestor $NEW_BASELINE $CURRENT_HASH
if [[ 0 -ne $? ]]; then
return 1
fi
resetbasebranch
if [ "$SHORT_NAME" == "$CLOSEST_ANCESTOR" ]; then
echo "$CURRENT_BRANCH is already rebased against $SHORT_NAME ($NEW_BASELINE)"
return 0
fi
if [ "" == "${CLOSEST_ANCESTOR}" ]; then
echo "Unable to determine closest ancestor"
return 1
fi
echo "Detected a deviation from the build reference commit ${NEW_BASELINE} due to rebase against ${CLOSEST_ANCESTOR}"
echo "Saving existing $CURRENT_BRANCH to ${CURRENT_BRANCH}-old in case of failure"
git branch -m ${CURRENT_BRANCH} ${CURRENT_BRANCH}-old
echo "Attempting to rollback to reference commit ${NEW_BASELINE}"
git checkout -b ${CURRENT_BRANCH}
git format-patch --relative ${CLOSEST_ANCESTOR}
git reset --hard ${NEW_BASELINE}
set -o pipefail
EXIT_STATUS=0
if [ "" != "$(ls -1 | grep '\.patch$')" ]; then
ls -1 *.patch | sort | xargs git am
EXIT_STATUS=$?
rm -f *.patch
fi
set +o pipefail
if [[ 0 -eq $EXIT_STATUS ]]; then
echo "Rollback to reference commit succeeded, deleting ${CURRENT_BRANCH}-old"
git branch -D ${CURRENT_BRANCH}-old
return 0
fi
echo "Rollback to reference commit failed. Build may end up being as slow as a regular ant all!"
git am --abort
git checkout -f ${CURRENT_BRANCH}-old
git branch -D ${CURRENT_BRANCH}
git branch -m ${CURRENT_BRANCH}-old ${CURRENT_BRANCH}
}
rebasebranch