-
Notifications
You must be signed in to change notification settings - Fork 3
/
git-bs
executable file
·158 lines (141 loc) · 4.16 KB
/
git-bs
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
#!/bin/bash
#
# git Branch Sync
# Report branch status for all your tracking branches and optionally sync them
fetch='' # -f|--fetch specified
pull='' # -p|--pull specified
noise='' # -q|--quiet, -v|--verbose specified
stat='' # --stat or -n|--no-stat specified (only for pull)
stash='' # -s|--stash specified
local=show # -r|--remote-only specified
# Is -q useful enough on fetch/pull? It seems to have
# little effect on fetch and no effect on pull?
bold="\033[1m"
norm="\033[0m"
function print_status() {
branch="$1"
remote=$(git config "branch.$branch.remote")
remote_branch=$(git config "branch.$branch.merge")
track="$remote/${remote_branch##*/}"
if [[ "/" = $track ]]; then
if [[ show = $local ]]; then
echo -e "# . $branch is only ${bold}local${norm}"
fi
elif git rev-parse "$track" 2>&1 | grep -q 'unknown revision'; then
echo -e "# ! $branch is tracking ${bold}non-existent${norm} remote branch $track"
else
set -- $(git rev-list "$branch..$track" | wc -l)
behind="$1"
set -- $(git rev-list "$track..$branch" | wc -l)
ahead="$1"
if [[ 0 != $behind && 0 != $ahead ]]; then
echo -e "# X $branch and $track have ${bold}diverged${norm} by $ahead and $behind commits"
elif [[ 0 != $behind ]]; then
echo -e "# < $branch is ${bold}behind${norm} $track by $behind commits"
if [[ pull = $pull ]]; then
echo ""
echo "] git checkout $branch"
if git checkout "$branch"; then
echo "] git merge$stat $track"
git merge $stat "$track"
else
pull='error'
fi
echo ""
fi
elif [[ 0 != $ahead ]]; then
echo -e "# > $branch is ${bold}ahead${norm} of $track by $ahead commits"
else
echo -e "# = $branch is ${bold}current${norm} with $track"
fi
fi
}
function usage() {
echo "Usage: git bs [-fnpqrsv] [--stat]" >&2
echo "Short for: --fetch --no-stat --pull --quiet --remote-only --stash --verbose" >&2
}
GETOPT=$(getopt -o hfnpqrsv --long fetch,no-stat,pull,quiet,remote-only,stash,verbose,stat -- "$@")
if [[ $? != 0 ]]; then
usage
exit 1
fi
set -- $GETOPT
while [[ 0 != $# ]]; do
case "$1" in
-f|--fetch)
fetch=fetch
;;
-p|--pull)
# pull implies fetch (and we're not doing a literal pull)
fetch=fetch
pull=pull
;;
-q|--quiet|-v|--verbose)
noise="$1"
;;
-r|--remote-only)
local=hide
;;
--stat|-n|--no-stat)
stat=" $1"
;;
--stash|-s)
stash="stash"
;;
-h)
usage
exit 0
;;
--)
shift
if [[ 0 != $# ]]; then
echo "Too many arguments ($*)" >&2
usage
exit 1
fi
;;
*)
echo "Unrecognized option ($1)??" >&2
usage
exit 1
;;
esac
shift
done
if [[ fetch = $fetch ]]; then
for remote in $(git remote); do
echo "] git fetch$noise $remote"
git fetch $noise "$remote"
echo ''
done
fi
if [[ stash = $stash && pull = $pull ]]; then
echo ""
echo "] git stash save git-bs auto-stash"
output=$(git stash save git-bs auto-stash)
echo $output
if echo $output | grep "No local changes" >/dev/null 2>&1; then
stash=""
fi
fi;
# Current branch
current_branch=$(git branch | grep '*' | sed 's/ *\* *//')
if [[ -n $current_branch && $current_branch != "(no branch)" ]]; then
echo "# On branch $current_branch"
print_status "$current_branch"
# A blank line to separate other branches
echo "#"
fi
# The rest
branches=$(git branch | grep -v '*')
for branch in $branches; do
print_status "$branch"
done
if [[ -n $pull ]]; then
git checkout "$current_branch"
fi
if [[ stash = "$stash" && pull = "$pull" ]]; then
echo ""
echo "] git stash pop"
git stash pop
fi