-
-
Notifications
You must be signed in to change notification settings - Fork 111
/
git-spinoff
executable file
·65 lines (56 loc) · 1.65 KB
/
git-spinoff
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
#!/bin/sh
set -eu
#
# Inspired by Magit's super useful `magit-branch-spinoff` command.
# See also https://magit.vc/manual/magit/Branch-Commands.html
#
usage () {
echo "usage: git spinoff [-h] <new-name> [<base>]" >&2
echo >&2
echo "Creates and checks out a new branch starting at and tracking the" >&2
echo "current branch. That branch in turn is reset to the last commit it" >&2
echo "shares with its upstream. If the current branch has no upstream or no" >&2
echo "unpushed commits, then the new branch is created anyway and the" >&2
echo "previously current branch is not touched." >&2
echo >&2
echo "This is useful to create a feature branch after work has already" >&2
echo "began on the old branch (likely but not necessarily \"main\")." >&2
echo >&2
echo "Options:" >&2
echo "-h Show this help" >&2
}
while getopts h flag; do
case "$flag" in
h) usage; exit 2;;
esac
done
shift $(($OPTIND - 1))
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
usage
exit 2
fi
new_name="$1"
rawbase="${2:-}"
if [ -z "$rawbase" ]; then
base="$(git current-branch)"
else
base="$rawbase"
fi
base_sha="$(git sha -s "$base")"
#
# NOTE:
# The flag -B is the transactional equivalent of
# $ git branch -f <branch> [<start point>]
# $ git checkout <branch>
#
git checkout -q --track -B "$new_name" "$base"
rtb="$(git remote-tracking-branch "$base")"
if [ -n "$rtb" ]; then
merge_base="$(git merge-base "$base" "$rtb")"
git branch -vf "$base" "$merge_base"
fi
if [ "$(git sha -s "$base")" != "$base_sha" ]; then
echo "$base reset to $(git sha -s "$base") (was $base_sha)"
else
echo "$base not touched"
fi