installed_progs.t: Python checks stdout too, 150 ok
[sunny256-utils.git] / git-wip
blob8361c8019c154f6fc5a42137a051bebe107c4ea5
1 #!/bin/sh
3 #==============================================================================
4 # git-wip
5 # File ID: fe636b92-445c-11e4-940c-c80aa9e67bbd
7 # Create subbranches using '.' as level delimiter.
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #==============================================================================
13 progname=git-wip
14 VERSION=0.4.1
16 opt_delete=0
17 opt_help=0
18 opt_merge=0
19 opt_parent=0
20 opt_quiet=0
21 opt_squash=0
22 opt_verbose=0
23 while test -n "$1"; do
24 case "$1" in
25 -D|--delete) opt_delete=1; shift ;;
26 -h|--help) opt_help=1; shift ;;
27 -m|--merge) opt_merge=1; shift ;;
28 -p|--parent) opt_parent=1; shift ;;
29 -q|--quiet) opt_quiet=$(($opt_quiet + 1)); shift ;;
30 -s|--squash) opt_squash=1; shift ;;
31 -v|--verbose) opt_verbose=$(($opt_verbose + 1)); shift ;;
32 --version) echo $progname $VERSION; exit 0 ;;
33 --) shift; break ;;
35 if printf '%s\n' "$1" | grep -q ^-; then
36 echo "$progname: $1: Unknown option" >&2
37 exit 1
38 else
39 break
41 break ;;
42 esac
43 done
44 opt_verbose=$(($opt_verbose - $opt_quiet))
46 if test "$opt_help" = "1"; then
47 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
48 cat <<END
50 Create subbranches using '.' as level delimiter.
52 Usage: $progname OPTION
53 $progname BRANCHNAME
55 Options:
57 -D, --delete
58 Delete current branch after merging it to parent. Used when there's
59 no need to document the existence of the branch, and a fast-forward
60 merge will do just fine.
61 -h, --help
62 Show this help.
63 -m, --merge
64 Merge the current branch to the parent branch using --no-ff in
65 git(1). This creates a merge commit even if a fast-forward is
66 possible. Useful to group related changes together.
67 -p, --parent
68 Change the active branch (git checkout) to the parent branch, i.e.,
69 the part of the branch name before the final full stop. If no parent
70 branch exists, you will be prompted to create one on 'master'.
71 -q, --quiet
72 Be more quiet. Can be repeated to increase silence.
73 -s, --squash
74 Squash the branch into the parent branch, all commits will be
75 collapsed into one.
76 -v, --verbose
77 Increase level of verbosity. Can be repeated.
78 --version
79 Print version information.
81 When the -D, -m, -p or -s option is used and there are no parent
82 branches (there are no full stops ('.') in the current branch name), the
83 branch will be merged or squashed to 'master'.
85 If no options are specified, a new "subbranch" will be created from the
86 current branch by postfixing it with ".BRANCHNAME" where BRANCHNAME is
87 specified on the command line. An exception is made when the current
88 branch is 'master', in that case the old branch name is not used as
89 prefix.
91 The GITWIP_GIT environment variable can be set to a specific git(1)
92 executable to use. Example:
94 export GITWIP_GIT=/usr/bin/git
95 git wip -m
97 END
98 exit 0
101 test -n "$GITWIP_GIT" && CMD_GIT="$GITWIP_GIT" || CMD_GIT=git
102 curr="$($CMD_GIT rev-parse --abbrev-ref HEAD)"
103 use_new_branch=0
104 test "$curr" = "master" -o "$curr" = "HEAD" && use_new_branch=1
106 ext="wip"
107 test -n "$1" && { ext="$1"; shift; }
109 loop_until_y() {
110 # Loop until the user says 'y'.
111 unset resp
112 until test "$resp" = "y"; do
113 echo -n $progname: Type \'y\' + Enter to $*... >&2
114 read resp
115 done
118 chkopt="$opt_delete$opt_merge$opt_parent$opt_squash"
119 if test -n "$(echo $chkopt | grep 1)"; then
120 if test -n "$(echo "$curr" | grep '\.')"; then
121 # Current branch contains a full stop, so it has a parent
122 parent="$(echo "$curr" | rev | cut -d . -f 2- | rev)"
123 else
124 # Current branch has no parents, prepare for merge or squash to
125 # master.
126 test "$opt_squash" = "1" && ms_str=squash || ms_str=merge
127 if test "$curr" = "master"; then
128 echo Is already on master, \
129 nowhere to $ms_str branch >&2
130 exit 1
132 if test "$opt_parent" = "1"; then
133 loop_until_y set active branch to \'master\' \
134 \($CMD_GIT checkout\)
135 else
136 loop_until_y $ms_str $curr to master
138 parent=master
141 $CMD_GIT branch | cut -c 3- | grep "^$parent\$" || {
142 echo $progname: $parent: Parent branch does not exist >&2
143 loop_until_y create the \'$parent\' branch on \'master\'
144 $CMD_GIT branch "$parent" master
146 $CMD_GIT checkout $parent &&
147 if test "$opt_delete" = "1"; then
148 # Delete current branch after merge to parent, use fast-forward
149 # if possible.
150 $CMD_GIT merge $curr
151 $CMD_GIT branch -d $curr
152 elif test "$opt_squash" = "1"; then
153 # Squash the current branch to parent, combine all commits into
154 # one.
155 $CMD_GIT merge --squash $curr
156 elif test "$opt_merge" = "1"; then
157 # Merge current branch into parent, always create merge commit
158 # even if a fast-forward merge is possible.
159 $CMD_GIT merge --no-ff $curr
160 $CMD_GIT branch -d $curr
162 exit
165 if test "$use_new_branch" = "1"; then
166 # Create new branch without prefix
167 $CMD_GIT branch "$ext" || exit 1
168 $CMD_GIT checkout "$ext"
169 else
170 # Create new branch, use current branch name as prefix
171 $CMD_GIT branch "$curr.$ext" || exit 1
172 $CMD_GIT checkout "$curr.$ext"
175 # vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 :