Sprawdź czy pull jest potrzebny w Git
Jak sprawdzić, czy zdalne repozytorium się zmieniło i muszę je pobrać?
Teraz używam tego prostego skryptu:
git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
Ale jest raczej ciężki.
Czy jest lepszy sposób? Idealnym rozwiązaniem byłoby sprawdzenie wszystkich zdalnych gałęzi i zwrócenie nazw zmienionych gałęzi oraz liczby nowych commitów w każdej z nich. 22 answers
Pierwsze użycie git remote update
, aby Twoje zdalne refy były aktualne. Następnie możesz zrobić jedną z kilku rzeczy, takich jak:
git status -uno
powie Ci, czy gałąź, którą śledzisz, jest z przodu, z tyłu lub się rozeszła. Jeśli nic nie mówi, lokalne i zdalne są takie same.git show-branch *master
wyświetli commity we wszystkich gałęziach, których nazwy kończą się na 'master' (np. master I origin / master ).
Jeśli używasz -v
z git remote update
(git remote -v update
) możesz zobaczyć, które gałęzie zostały zaktualizowane, więc tak naprawdę nie potrzebujesz żadnych dalszych poleceń.
Jednak wygląda na to, że chcesz to zrobić w skrypcie lub programie i skończysz z wartością true / false. Jeśli tak, istnieją sposoby, aby sprawdzić związek pomiędzy Twoim obecnym HEAD commit a szefem gałęzi, którą śledzisz, chociaż ponieważ są cztery możliwe wyniki, nie możesz zredukować tego do odpowiedzi tak/nie. Jeśli jednak jesteś gotowy na pull --rebase
, to może traktować "local is behind" I "local has diverged "jako" need to pull", a pozostałe dwa jako " don 't need to pull".
Możesz uzyskać identyfikator commitu dowolnego ref używając git rev-parse <ref>
, więc możesz to zrobić dla master I origin/master i porównać je. Jeśli są równe, gałęzie są takie same. Jeśli są nierówne, chcesz wiedzieć, który jest przed drugim. Użycie git merge-base master origin/master
powie Ci wspólnego przodka obu gałęzi, a jeśli się nie rozeszły, będzie to takie samo jak jedno albo drugie. Jeśli dostaniesz trzy różne identyfikatory, gałęzie się rozeszły.
Aby zrobić to poprawnie, np. w skrypcie, musisz być w stanie odwołać się do bieżącej gałęzi, oraz do gałęzi zdalnej, którą śledzi. Funkcja Bash prompt-setting w /etc/bash_completion.d
ma kilka przydatnych kodów do pobierania nazw gałęzi. Jednak prawdopodobnie nie musisz zdobywać nazwisk. Git posiada kilka zgrabnych skrótów odnoszących się do gałęzi i commitów (jak zostało to udokumentowane w git rev-parse --help
). W szczególności możesz użyć @
dla bieżąca gałąź (zakładając, że nie jesteś w stanie odłączonej głowicy) i @{u}
dla jej gałęzi nadrzędnej (np origin/master
). Tak więc git merge-base @ @{u}
zwróci (hash) commita, w którym bieżąca gałąź i jej źródło się różnią, a git rev-parse @
i git rev-parse @{u}
podadzą ci skróty dwóch podpowiedzi. Można to podsumować w następującym skrypcie:
#!/bin/sh
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")
if [ $LOCAL = $REMOTE ]; then
echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
echo "Need to push"
else
echo "Diverged"
fi
Uwaga: starsze wersje Gita nie zezwalały na @
samodzielnie, więc być może będziesz musiał użyć @{0}
.
Linia UPSTREAM=${1:-'@{u}'}
pozwala na opcjonalnie jawnie przekazać gałąź upstream, na wypadek, gdybyś chciał sprawdzić inną zdalną gałąź niż ta skonfigurowana dla bieżącej gałęzi. Zazwyczaj ma to postać remotename/branchname. Jeśli nie podano żadnego parametru, wartość domyślna to @{u}
.
Skrypt zakłada, że najpierw wykonałeś git fetch
lub git remote update
, aby uaktualnić gałęzie śledzące. Nie wbudowałem tego w skrypt, ponieważ jest bardziej elastyczny, aby móc wykonywać pobieranie i porównywanie jako oddzielne operacje, na przykład, jeśli chcesz porównać bez pobierania, ponieważ pobrano już niedawno.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-17 20:32:08
Jeśli masz gałąź upstream
git fetch <remote>
git status
Jeśli nie masz gałęzi upstream
Porównaj dwie gałęzie:
git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline
Na przykład:
git fetch origin
# See if there are any incoming changes
git log HEAD..origin/master --oneline
(zakładam, że origin/master
to twoja zdalna gałąź śledzenia)
Jeśli któraś z rewizji znajduje się na liście powyżej, to masz nadchodzące zmiany -- musisz scalić. Jeśli nie ma commitów na liście git log
, to nie ma nic do scalenia.
Zauważ, że to zadziała nawet jeśli jesteś na gałęzi feature-that nie posiada pilota do śledzenia, ponieważ if jawnie odwołuje się do origin/master
zamiast do niejawnego używania gałęzi upstream zapamiętanej przez Git.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-29 15:22:57
Jeśli jest to skrypt, możesz użyć:
git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})
(Uwaga: zaletą tej I poprzednich odpowiedzi jest to, że nie potrzebujesz osobnego polecenia, aby uzyskać bieżącą nazwę gałęzi. "HEAD" i "@{u} " (bieżąca gałąź jest pod prąd) dbają o to. Zobacz "git rev-parse --help" po więcej szczegółów.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-16 18:34:53
Komenda
git ls-remote origin -h refs/heads/master
Wyświetli bieżącą głowicę na zdalnym -- możesz porównać ją z poprzednią wartością lub sprawdzić, czy masz SHA w lokalnym repo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-15 17:37:21
Oto Jednolinijkowy Bash, który porównuje hash aktualnej gałęzi HEAD commit z odległą gałęzią upstream, bez konieczności wykonywania ciężkich operacji git fetch
lub git pull --dry-run
:
[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date
Oto jak ta nieco gęsta linia jest podzielona:
- polecenia są grupowane i zagnieżdżane przy użyciu składni
$(x)
Bash command-substitution . -
git rev-parse --abbrev-ref @{u}
zwraca skrócony ref (np.origin/master
), który jest następnie konwertowany na pola oddzielone spacjami za pomocą polecenia pipedsed
, np.origin master
. - ten łańcuch jest wprowadzany do
git ls-remote
, który zwraca commit head zdalnej gałęzi. To polecenie będzie komunikować się ze zdalnym repozytorium. Polecenie pipedcut
wydobywa tylko pierwsze pole (Skrót zatwierdzania), usuwając oddzielony tabulatorami łańcuch odniesienia. -
git rev-parse HEAD
zwraca lokalny hash zatwierdzania.
Składnia Bash
[ a = b ] && x || y
uzupełnia one-liner: this is a Bash string-comparison =
w konstrukcji testowej [ test ]
, po której następuje and-list and or-list constructs && true || false
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-03 21:07:57
Proponuję zapoznać się ze skryptem https://github.com/badele/gitcheck . zakodowałem ten skrypt, aby sprawdzić w jednym przejściu wszystkie repozytoria Git, i pokazuje, kto nie popełnił, a kto nie pchnął / pociągnął.
Oto przykładowy wynik:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 23:04:44
Oparłem To rozwiązanie na komentarzach @jberger.
if git checkout master &&
git fetch origin master &&
[ `git rev-list HEAD...origin/master --count` != 0 ] &&
git merge origin/master
then
echo 'Updated!'
else
echo 'Not updated.'
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-19 13:10:23
Myślę, że najlepszym sposobem na to będzie:
git diff remotes/origin/HEAD
Zakładając, że masz zarejestrowany ten refspec. Powinieneś, jeśli sklonowałeś repozytorium, w przeciwnym razie (np. jeśli repo zostało utworzone de novo lokalnie i przesunięte do zdalnego), musisz wyraźnie dodać refspec.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-16 01:18:01
Istnieje już wiele bardzo bogatych i pomysłowych odpowiedzi. Aby zapewnić kontrast, mógłbym zrobić bardzo prostą linię.
# Check return value to see if there are incoming updates.
if ! git diff --quiet remotes/origin/HEAD; then
# pull or whatever you want to do
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-03 08:59:50
Zrobiłbym to, co zasugerował brool. Poniższy skrypt jednowierszowy pobiera SHA1 ostatniej zatwierdzonej wersji i porównuje ją do zdalnej wersji origin i pobiera zmiany tylko wtedy, gdy różnią się one.
I to jeszcze bardziej lekkie rozwiązania oparte na git pull
lub git fetch
.
[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-10 17:42:20
Poniższy skrypt działa doskonale.
changed=0
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
if [ $changed = 1 ]; then
git pull
echo "Updated successfully";
else
echo "Up-to-date"
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 23:33:44
Jeśli uruchomisz ten skrypt, sprawdzi, czy bieżąca gałąź potrzebuje git pull
:
#!/bin/bash
git fetch -v --dry-run 2>&1 |
grep -qE "\[up\s+to\s+date\]\s+$(
git branch 2>/dev/null |
sed -n '/^\*/s/^\* //p' |
sed -r 's:(\+|\*|\$):\\\1:g'
)\s+" || {
echo >&2 "Current branch need a 'git pull' before commit"
exit 1
}
Jest bardzo wygodne, aby umieścić go jako Git hook pre-commit, aby uniknąć
Merge branch 'foobar' of url:/path/to/git/foobar into foobar
Kiedy ty commit
przed pulling
.
Aby użyć tego kodu jako Hooka, po prostu skopiuj / wklej skrypt w
.git/hooks/pre-commit
I
chmod +x .git/hooks/pre-commit
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 16:10:12
Uruchom git fetch (remote)
aby zaktualizować swoje zdalne refy, pokaże ci, co nowego. Następnie, gdy kasujesz lokalny oddział, pokaże Ci, czy jest on za prądem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-23 20:10:56
Chcę po prostu opublikować to jako rzeczywisty post, ponieważ łatwo jest to przegapić w komentarzach.
Prawidłową i najlepszą odpowiedź na to pytanie dał @Jake Berger, dziękuję bardzo stary, każdy tego potrzebuje i każdy tęskni za tym w komentarzach. Więc dla wszystkich, którzy zmagają się z tym tutaj jest poprawna odpowiedź, po prostu użyj wyjścia tego polecenia, aby wiedzieć, czy musisz zrobić git pull. jeśli na wyjściu jest 0, to oczywiście nie ma co aktualizować.
@stackoverflow, daj ten facet to dzwonek. Dzięki @ Jake Berger
git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two. – Jake Berger Feb 5 '13 at 19:23
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 08:56:07
git ls-remote | cut -f1 | git cat-file --batch-check >&-
Wyświetli wszystkie odniesienia w każdym zdalnym, który nie jest w repo. Aby złapać zdalne zmiany ref do rzeczy, które już posiadałeś (np. reset do poprzednich commitów), potrzeba trochę więcej:
git pack-refs --all
mine=`mktemp`
sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
for r in `git remote`; do
echo Checking $r ...
git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-11 00:40:14
Oto moja wersja skryptu Bash, który sprawdza wszystkie repozytoria w predefiniowanym folderze:
Https://gist.github.com/henryiii/5841984
Może rozróżniać typowe sytuacje, takie jak pociągnięcie potrzebne i pchnięcie potrzebne, i jest wielowątkowy, więc pobieranie dzieje się wszystko na raz. Posiada kilka poleceń, takich jak pull i status.
Umieść dowiązanie symboliczne (lub skrypt) w folderze w ścieżce, a następnie działa jako git all status
(, itd.). Obsługuje tylko origin / master, ale może być edytowane lub łączone z inną metodą.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 23:07:28
Using simple regexp:
str=$(git status)
if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
else
echo "Code is up to date"
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 14:50:28
Może to, jeśli chcesz dodać zadanie jako crontab:
#!/bin/bash
dir="/path/to/root"
lock=/tmp/update.lock
msglog="/var/log/update.log"
log()
{
echo "$(date) ${1:-missing}" >> $msglog
}
if [ -f $lock ]; then
log "Already run, exiting..."
else
> $lock
git -C ~/$dir remote update &> /dev/null
checkgit=`git -C ~/$dir status`
if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
log "-------------- Update ---------------"
git -C ~/$dir pull &>> $msglog
log "-------------------------------------"
fi
rm $lock
fi
exit 0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 11:49:31
Używam wersji skryptu opartej na odpowiedzi Stephena Habermana:
if [ -n "$1" ]; then
gitbin="git -C $1"
else
gitbin="git"
fi
# Fetches from all the remotes, although --all can be replaced with origin
$gitbin fetch --all
if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
$gitbin rebase @{u} --preserve-merges
fi
Zakładając, że skrypt zostanie wywołany git-fetch-and-rebase
, może być wywołany opcjonalnym argumentem directory name
lokalnego repozytorium Git do wykonania operacji. Jeśli skrypt jest wywoływany bez argumentów, zakłada, że bieżący katalog jest częścią repozytorium Git.
Przykłady:
# Operates on /abc/def/my-git-repo-dir
git-fetch-and-rebase /abc/def/my-git-repo-dir
# Operates on the Git repository which the current working directory is part of
git-fetch-and-rebase
Jest on dostępny tutaj również.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 23:09:21
Po przeczytaniu wielu odpowiedzi i wielu postów, i spędzeniu pół dnia na próbowaniu różnych permutacji, to jest to, co wymyśliłem.
Jeśli korzystasz z systemu Windows, możesz uruchomić ten skrypt w systemie Windows używając Git Bash dostarczonego przez Git for Windows (installation lub portable).
Ten skrypt wymaga argumentów
- local path e.g. /d/source/project1 - Git URL e.g. https://[email protected]/username/project1.git - password if a password should not be entered on the command line in plain text, then modify the script to check if GITPASS is empty; do not replace and let Git prompt for a password
Skrypt będzie
- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.
Jeśli nastąpiła zmiana wydrukowana przez skrypt, możesz przystąpić do pobierania lub pobierania. Skrypt może nie jest wydajny, ale to robi to za mnie.
Update-2015-10-30: stderr do dev null, aby zapobiec wydrukowaniu adresu URL z hasłem do konsoli.
#!/bin/bash
# Shell script to check if a Git pull is required.
LOCALPATH=$1
GITURL=$2
GITPASS=$3
cd $LOCALPATH
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
echo
echo git url = $GITURL
echo branch = $BRANCH
# Bash replace - replace @ with :password@ in the GIT URL
GITURL2="${GITURL/@/:$GITPASS@}"
FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
if [ "$?" != "0" ]; then
echo cannot get remote status
exit 2
fi
FOO_ARRAY=($FOO)
BAR=${FOO_ARRAY[0]}
echo [$BAR]
LOCALBAR="$(git rev-parse HEAD)"
echo [$LOCALBAR]
echo
if [ "$BAR" == "$LOCALBAR" ]; then
#read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
echo No changes
exit 0
else
#read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
#echo pressed $key
echo There are changes between local and remote repositories.
exit 1
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 23:33:11
Dla użytkowników windows, którzy kończą na tym pytaniu szukając tego, zmodyfikowałem część odpowiedzi na skrypt powershell. Dostosuj w razie potrzeby, Zapisz do pliku .ps1
i uruchom na żądanie lub zaplanuj, jeśli chcesz.
cd C:\<path to repo>
git remote update #update remote
$msg = git remote show origin #capture status
$update = $msg -like '*local out of date*'
if($update.length -gt 0){ #if local needs update
Write-Host ('needs update')
git pull
git reset --hard origin/master
Write-Host ('local updated')
} else {
Write-Host ('no update needed')
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-24 12:49:58
Możesz również znaleźć skrypt Phing Kto to teraz robi.
Potrzebowałem rozwiązania do automatycznej aktualizacji środowiska produkcyjnego i jesteśmy bardzo zadowoleni dzięki temu skryptowi, który udostępniam.
Skrypt jest napisany w XML i wymaga Phing .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-03 13:37:25