]> Tony Duckles's Git Repositories (git.nynim.org) - dotfiles.git/blob - bin/git-cut-branch
.vim: vim-plug @b6050d6
[dotfiles.git] / bin / git-cut-branch
1 #!/bin/sh
2 #/ Usage: git-cut-branch <name>
3 #/ Create a new branch named <name> pointed at HEAD and reset the current branch
4 #/ to the head of its tracking branch. This is useful when working on master and
5 #/ you realize you should be on a topic branch.
6 set -e
7
8 # bail out with message to stderr and exit status 1
9 die() {
10 echo "$(basename $0):" "$@" 1>&2
11 exit 1
12 }
13
14 # write a short sha for the given sha
15 shortsha() {
16 echo "$1" |cut -c1-7
17 }
18
19 # show usage
20 [ -z "$1" -o "$1" = "--help" ] && {
21 grep '^#/' "$0" |cut -c4-
22 exit 2
23 }
24
25 # first argument is the new branch name
26 branch="$1"
27
28 # get the current branch for HEAD in refs/heads/<branch> form
29 ref=$(git symbolic-ref -q HEAD)
30 sha=$(git rev-parse HEAD)
31 [ -n "$ref" ] ||
32 die "you're not on a branch"
33
34 # just the branch name please
35 current=$(echo "$ref" |sed 's@^refs/heads/@@')
36 [ -n "$current" ] ||
37 die "you're in a weird place; get on a local branch"
38
39 # figure out what branch we're currently tracking
40 remote=$(git config --get "branch.$current.remote" || true)
41 merge=$(git config --get "branch.$current.merge" | sed 's@refs/heads/@@')
42
43 # build up a sane <remote>/<branch> name
44 if [ -n "$remote" -a -n "$merge" ]
45 then tracking="$remote/$merge"
46 elif [ -n "$merge" ]
47 then tracking="$merge"
48 else die "$current is not tracking anything"
49 fi
50
51 # make sure there's no changes before we reset hard
52 if ! git diff-index --quiet --cached HEAD || ! git diff-files --quiet
53 then die "cannot cut branch with changes to index or working directory"
54 fi
55
56 # reset the current branch to its tracking branch, create the new branch also
57 # tracking the original branch, and switch to it.
58 git branch "$branch"
59 git reset -q --hard "$tracking"
60 git checkout -q "$branch"
61 git branch --set-upstream "$branch" "$tracking"
62 git reset -q --hard "$sha"
63 echo "[$(shortsha "$sha")...$(shortsha $(git rev-parse $tracking))] $current"
64 echo "[0000000...$(shortsha $(git rev-parse HEAD))] $branch"