-
Notifications
You must be signed in to change notification settings - Fork 239
/
git-remote-in-sync.sh
executable file
·134 lines (126 loc) · 3.88 KB
/
git-remote-in-sync.sh
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
#!/usr/bin/env bash
# checks if the specified remote(s) are in sync with what we have
# in other words: do we have anything which is not at the remote?
# Any commit, tag, branch, dirty WC/index or stashed state?
# This is especially useful if you're wondering:
# "is it safe to delete this clone? is any work here that needs to be
# distributed/shared/pushed first?"
# Note that there are some special cases, like a branch here may
# have a different name on the remote. This script is not aware of
# stuff like that. Also, `git status` will not detect if the local
# repo is ahead of an svn repo (using git svn)
# written by Dieter Plaetinck
list="$*"
[ -z "$list" ] && list=$(git remote)
ret=0
if [ -z "$(git branch)" ]
then
if [ "$(cd "$(git root)" && ls -Al | grep -Ev "^(.git|total)" | wc -l)" -gt 0 ]
then
echo "WARN: This repo doesn't contain any branch, but contains a bunch of files!" >&2
ls -Alh "$(git root)"
ret=1
else
echo "INFO: This repo doesn't contain any branch, and is empty"
# note that stashing doesn't work without a branch, so the above check is sufficient
exit 0
fi
else
echo -n "INFO: Valid git repo with branches: "
git branch | tr '\n' ' '
echo
fi
if [ -z "$list" ]
then
echo "WARN: At least one branch, but no remotes found! The content here might be unique!" >&2
ret=1
else
if [ -n "$*" ]
then
echo "INFO: working with remote(s): $*"
echo "INFO: fyi, all remotes: $(git remote)"
else
echo "INFO: working with all remotes: $list"
fi
fi
for remote in $list;
do
echo "INFO: Checking remote $remote.."
# Check commits and branches
# An approach where you `git push --all -n $remote 2>&1` and check whether the result is
# 'Everything up-to-date' can (and often will) yield
# "To prevent you from losing history, non-fast-forward updates were rejected"
# Since such an approach does traffic with the remote anyway, I choose to fetch the origin
# and inspect it's branches. This is a bit inefficient network-wise, but couldn't see a better solution
if ! git fetch $remote
then
echo " WARN: could not git fetch $remote" >&2
ret=1
fi
IFS_BACKUP=$IFS
IFS=$'\n'
for branch in $(git branch)
do
branch=${branch/\*/};
branch_local=${branch// /}; # git branch prefixes branches with spaces. and spaces in branchnames are illegal.
if ! git branch -r --contains $branch_local 2>/dev/null | grep -q "^ $remote/"
then
echo " WARN: Branch $branch_local is not contained within remote $remote!" >&2
ret=1
else
echo " INFO: Branch $branch_local is contained within remote $remote"
fi
if ! git branch -r | grep -q "^ $remote/$branch_local"
then
echo " WARN: Branch $branch_local exists, but not $remote/$branch_local" >&2
ret=1
else
echo " INFO: Branch $branch_local exists also as $remote/$branch_local"
fi
done
IFS=$IFS_BACKUP
# Check tags
out=$(git push --tags -n "$remote" 2>&1)
if [ "$out" != 'Everything up-to-date' ];
then
echo -e " WARN: Some tags are not in $remote!\n$out" >&2
ret=1
else
echo " INFO: All tags ($(git tag)) exist at $remote as well"
fi
done
# Check WC/index
cur_branch=$(git branch | grep '^\* ' | cut -d ' ' -f2)
cur_branch=${cur_branch// /}
exp="# On branch $cur_branch
nothing to commit (working directory clean)"
out=$(git status)
wc_ok=1
if [ "$out" != "$exp" ]
then
# usually i'd use bash regex, but this case is multiple-lines so bash regex is no go
out=$(echo "$out" | grep -E -v "^(# On branch $cur_branch|# Your branch is behind .* commits, and can be fast-forwarded.|#|nothing to commit \(working directory clean\))$")
if [ -n "$out" ]
then
wc_ok=0
echo "WARN: Dirty WC or index" >&2
git status
ret=1
fi
fi
if [ $wc_ok -eq 1 ]
then
echo "INFO: Working copy/index are clean"
git status
fi
# Check stash
if [ "$(git stash list | wc -l)" -gt 0 ];
then
echo "WARN: Dirty stash:" >&2
GIT_PAGER= git stash list >&2
ret=1
else
echo "INFO: Stash clean"
GIT_PAGER= git stash list
fi
exit $ret