-
Notifications
You must be signed in to change notification settings - Fork 2
/
git-ffwd
executable file
·101 lines (81 loc) · 2.87 KB
/
git-ffwd
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
#!/bin/bash
SUBDIRECTORY_OK=1 source "$(git --exec-path)/git-sh-setup" ||
die "Not a git repository."
has_matching_push() {
# push.default is setup for 'simple', 'current', or 'matching'.
case "$(git config --get push.default || echo "matching")" in
current | simple | matching)
return 0
esac
return 1
}
if has_matching_push; then
MATCHING_PUSH=t
else
MATCHING_PUSH=
fi
determine_upstream_branch() {
local ref="${1#refs/heads/}"
local upstream="$(git for-each-ref --format='%(upstream:short)' "refs/heads/$ref")"
local publish_branch
if [[ -n "$upstream" ]]; then
echo "$upstream"
return 0
fi
if [[ -z "$MATCHING_PUSH" ]]; then
return 1
fi
# Use the push location as the upstream.
local remote=$(git config --get branch.${ref}.pushremote ||
git config --get remote.pushdefault ||
git config --get branch.${ref}.remote)
if [ -z "$remote" -a -n "$(git config --get remote.origin.url 2> /dev/null)" ]; then
remote="origin"
fi
if [[ -n "$remote" ]]; then
git rev-parse "$remote/$ref" > /dev/null 2>&1 &&
publish_branch="$remote/$ref"
fi
if [[ -n "$publish_branch" ]]; then
echo "$publish_branch"
return 0
fi
return 1
}
# Taken from http://stackoverflow.com/questions/620650/can-i-easily-update-all-local-git-branches-from-remote-branches-simultaneously/answer-9076361
# with a small tweak by me to make the fast-forward merge use --ff-only, and to
# help prune remote branches. It has also been updated to treat the push branch
# as the default upstream, if no upstream is configured.
main() {
local upstream
local ALR
local LR
local CLB=$(git branch -l|awk '/^\*/{print $2}')
local REMOTES="$@"
if [ -z "$REMOTES" ]; then
REMOTES="$(git remote)"
fi
REMOTES="$(echo "$REMOTES" | xargs -n1 echo)"
git remote update -p $REMOTE
git show-ref --heads | cut -d ' ' -f 2 | while read ALB; do
LB="${ALB#refs/heads/}"
RB="$(determine_upstream_branch "${LB}")"
if [ -z "${RB}" ]; then
continue
fi
NBEHIND=$(( $(git rev-list --count $LB..$RB 2>/dev/null) +0))
NAHEAD=$(( $(git rev-list --count $RB..$LB 2>/dev/null) +0))
if [ "$NBEHIND" -gt 0 ]; then
if [ "$NAHEAD" -gt 0 ]; then
echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $RB. could not be fast-forwarded"
elif [ "$LB" = "$CLB" ]; then
echo " branch $LB was $NBEHIND commit(s) behind $RB. fast-forward merge";
git merge --ff --ff-only -q $RB
else
echo " branch $LB was $NBEHIND commit(s) behind $RB. resetting local branch to remote"
git branch -l -f $LB -t $RB >/dev/null
fi
fi
done
}
main $@