-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit-update
executable file
·168 lines (142 loc) · 4.43 KB
/
git-update
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
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env bash
# git-update --- combine fetch/pull/submodules/lfs/rebase of workspace
# Author: Noah Friedman <[email protected]>
# Created: 2015-10-31
# Public domain
git() { command ${GITPROG-git} "$@"; }
git_revno()
{
git rev-list -n1 HEAD
}
bare_repo_p()
{
case `git config --bool --local --get core.bare` in
true ) return 0 ;;
* ) return 1 ;;
esac
}
has_remotes()
{
# exit code 1 if no matches
git config --local --get-regexp '^remote\..*\.url$' > /dev/null
}
num_remotes()
{
declare -i i=0
git config --local --get-regexp '^remote\..*\.url$' |
while read line; do
i=$((i + 1))
done
echo $i
}
num_jobs()
{
declare -i n=1
case ${OSTYPE-`uname -s`} in
*[Ll]inux* ) n=`nproc` ;;
esac
if [ $n -gt 4 ]; then n=$((n / 2)); fi
echo $n
}
# If you want submodules to be at higher revisions than the superproject
# expects at any given time, you should disable submodule recursion
# by running:
#
# git config --local --replace-all update.recurse-submodules no
#
# and use
#
# git submodule foreach git update
#
# to update the submodules independently of the superproject.
recurse_flag()
{
local flag=`git config --local --get update.recurse-submodules`
echo --recurse-submodules=${flag:-yes}
}
# Fast forward, without checkout, any non up-to-date local branches that
# have no local commits which would need merging with the upstream.
fastforward_refs()
{
ref_cur=`git symbolic-ref HEAD`
git for-each-ref --format='%(refname) %(upstream)' refs/heads |
while read ref_loc ref_rem; do
# check if no upstream or ref is current checkout
case $ref_rem:$ref_loc in :* | *:$ref_cur ) continue ;; esac
rev_loc=`git rev-parse $ref_loc`
rev_rem=`git rev-parse $ref_rem`
case $rev_loc in $rev_rem ) continue ;; esac
case `git merge-base $ref_loc $ref_rem` in
$rev_loc ) git update-ref $ref_loc $ref_rem ;;
esac
done
}
main()
{
declare -a gitargs
while :; do
case $1 in
-r | --rebase ) shift; gitargs+=( --rebase=merges ) ;;
-p | --prune ) shift; gitargs+=( --prune ) ;;
* ) break ;;
esac
done
case $# in 0 ) set . ;; esac
for dir in "$@"; do
if [ $# -gt 1 ]; then
case $dir in
. ) gdir=`pwd` ;;
.. ) gdir=`cd .. && pwd` ;;
* ) gdir=$dir ;;
esac
echo "* $gdir"
fi
(
cd "$dir" || exit $?
if ! has_remotes; then
if [ -f .gitmodules ]; then
git submodule foreach -q 'echo $path' |
while read path; do
echo "$path"
git -C "$path" update
echo
done
fi
#echo "repository has no upstream remotes"
return 0
fi
if bare_repo_p; then
# git-2.35 "--all" overrides "--no-write-fetch-head",
# so do each remote separately.
for remote in `git remote`; do
git fetch --no-write-fetch-head --tags $remote
done
test -d lfs/objects && git lfs fetch --all
# No reason to clutter the filesystem with these for mirrored repos
git pack-refs --all
else
declare -a xopts=( --no-stat `recurse_flag` )
j=`num_jobs`
if [ $j -gt 1 ]; then
xopts+=( --jobs=$j )
fi
# git 2.21 (and maybe others) will fetch submodules twice
# if you use both --all and --recursive-submodules, so
# don't use it unless there are really more than 1 remote.
# Also, the first fetch won't honor --jobs so it's
# especially slow.
if [ `num_remotes` -gt 1 ]; then xopts+=( --all ); fi
revno_old=`git_revno`
git pull "${gitargs[@]}" "${xopts[@]}"
revno_new=`git_revno`
case $revno_new in $revno_old ) return 0 ;; esac
git restore-commit-mtime $revno_old..$revno_new
fastforward_refs
fi
)
test $# -gt 1 && echo
:
done
}
main "$@"
# eof