-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgit-cherry-copy
executable file
·199 lines (178 loc) · 4.75 KB
/
git-cherry-copy
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
#!/usr/bin/env bash
#
# git-cherry-copy
#
# License: MIT
# Copyright (c) 2012 Lennart C. L. Kats
set -e
STASH=
CURRENTBRANCH=`git-get-branch`
MASTER=origin/master
MAKENEWBRANCH=
MAKE_NEW=
NO_FETCH=
MOVE_BRANCH=
PULL_REQUEST=
ORIGINAL_COMMAND="`basename $0` $*"
while echo "$1" | grep -E "-" >/dev/null; do
case "$1" in
-b)
MAKE_NEW=-b ;;
-f)
NO_FETCH=-f ;;
-m)
MOVE_BRANCH=-m ;;
-p)
PULL_REQUEST=-p ;;
*)
break ;;
esac
shift
done
if echo "$1" | grep origin/ >/dev/null; then
MASTER=$1
shift
fi
BRANCH=$1
shift
if [ "`git branch --list $BRANCH 2>/dev/null`" == "" ]; then
if [ ! $MAKE_NEW ]; then
echo Branch $BRANCH does not exist and option -b not specified. Aborting. >&2
exit 1
fi
elif [ $MAKE_NEW ]; then
echo Branch $BRANCH already exists and option -b specified. Aborting. >&2
exit 1
fi
if [ "$1" == "" ]; then
echo "Error: no commits to cherry-pick specified" >&2
if [ "`git status --porcelain | grep -Ev '\?+ '`" != "" ]; then
echo "Tip: did you mean to move your uncommited changes? Try: $ORIGINAL_COMMAND LOCAL" >&2
fi
echo Aborting. >&2
exit 1
fi
if [ "$BRANCH" == "" ] || [ "$BRANCH" == "--help" ]; then
echo "Usage: `basename $0` [OPTIONS...] [<origin/BRANCH>] <BRANCH> <CHERRY.. | LOCAL>"
echo ' -b create a new branch BRANCH, rather than use an existing one'
echo ' -f disable fetch step'
echo ' -p make a pull request for the created branch'
# echo ' -m` move the commit(s), instead of copying it'
echo ' origin/BRANCH name for base branch'
echo ' BRANCH name for new branch'
echo " CHERRY a commit, a branch to pick the head from, or a range of commits [default: $CURRENTBRANCH]"
echo " LOCAL take uncommited changes instead of a range of commits"
exit
fi
if [ "$1" == local ] || [ "$1" == LOCAL ]; then
echo '$ git stash'
RESULT=`git stash save "changes stashed by git-branch-from-cherry"`
if echo "$RESULT" | grep -iE 'No local changes' >/dev/null; then
echo -e "error: no local changes. Aborting.">&2
exit 1
fi
echo
fi
# -m is very conservative and only supports a few cases
if [ "$MOVE_BRANCH" ]; then
if [ "$*" == "local" ] || [ "$*" == LOCAL ]; then
MOVE_BRANCH=
elif echo "$*" | grep -Ei '^ (HEAD\^\^|HEAD~2) (HEAD\^|HEAD~1) HEAD$' >/dev/null; then
MOVE_BRANCH="git reset --hard HEAD^^^"
elif echo "$*" | grep -Ei '^(HEAD\^|HEAD~1) HEAD$' >/dev/null; then
MOVE_BRANCH="git reset --hard HEAD^^"
elif echo "$*" | grep -Ei '^HEAD$' >/dev/null || [ "`git rev-parse $*`" == "`git rev-parse HEAD`" ] ||
[ "$*" == "" ]; then
MOVE_BRANCH="git reset --hard HEAD^"
else
echo "error: cannot use -m with this cherry-pick pattern. Aborting." >&2
exit 1
fi
fi
if [ ! $NO_FETCH ] && [ $MAKE_NEW ]; then
M=`echo $MASTER | perl -pe 's/^origin\/(.*)/$1/'`
echo "$ git fetch origin $M"
git fetch -q origin $M
echo
fi
if [ "$1" == local ] || [ "$1" == LOCAL ]; then
if [ $MAKE_NEW ]; then
echo "$ git checkout $MASTER"
git checkout -q $MASTER
echo
fi
echo "$ git checkout $MAKE_NEW $BRANCH"
git checkout -q $MAKE_NEW $BRANCH
echo
echo "$ git stash pop"
git stash pop -q
echo
echo "$ git status -s"
git status -s
exit
else
CHERRY=`git rev-parse "$@"`
if [ $# == 1 ]; then
echo "$ git log --oneline --first-parent -1 $@"
git --no-pager log --oneline --color=never --first-parent -1 `git rev-parse "$@"`
echo
#else
# echo "(can't show revision log for multiple revisions)"
fi
fi
RESULT=`git stash save "changes stashed by git-branch-from-cherry"`
if ! echo "$RESULT" | grep -iE 'No local changes' >/dev/null; then
echo '$ git stash'
echo
STASH=1
fi
if [ $MAKE_NEW ]; then
echo "$ git checkout $MASTER"
git checkout -q $MASTER
echo
fi
if ! ls `pwd` &>/dev/null; then
PREVPWD=`pwd`
while [ ! -e .git ] && [ "`pwd`" != "/" ]; do
cd ..
done
echo "$ git checkout $CURRENTBRANCH"
git checkout -q $CURRENTBRANCH
echo
if [ $STASH ]; then
echo '$ git stash pop'
git stash pop -q
echo
fi
echo "error: cannot execute this from directory `pwd` that only exists in the curent branch. Aborted."
cd $PREVPWD
exit 1
fi
echo "$ git checkout $BRANCH"
git checkout -q $MAKE_NEW $BRANCH
echo
echo "$ git cherry-pick $CHERRY"
git cherry-pick $CHERRY
echo
echo "$ git checkout $CURRENTBRANCH"
git checkout -q $CURRENTBRANCH
echo
if [ "$MOVE_BRANCH" ]; then
echo "$ $MOVE_BRANCH"
$MOVE_BRANCH
echo
fi
if [ $STASH ]; then
echo '$ git stash pop'
git stash pop -q
echo
fi
echo "Successfully cherry-picked to $BRANCH."
echo
if [ "$PULL_REQUEST" ]; then
if [ $MAKE_NEW ]; then # already fetched
NO_FETCH=-f
fi
echo "$ git-pull-request $BRANCH"
git-pull-request $BRANCH
fi