Git'te çekme gerekip gerekmediğini kontrol edin


622

Uzak deponun değişip değişmediğini ve çekmem gerektiğini nasıl kontrol ederim?

Şimdi bu basit komut dosyasını kullanıyorum:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

Ama oldukça ağır.

Daha iyi bir yol var mı? İdeal çözüm, tüm uzak dalları kontrol eder ve değiştirilen dalların adlarını ve her birindeki yeni taahhütlerin sayısını döndürür.


14
Lütfen dikkat: "git pull --dry-run" beklendiği gibi çalışmıyor. Görünüşe göre git pull, bilinmeyen seçenekleri doğrudan git getirmeye geçirir. Sonuç, normal bir git çekme sonucudur.

27
"Çekme" bir kerede "getirme" ve "birleştirme" işlemlerinin kısa bir yoludur, eğer uzaktan repo durumunu kontrol etmeniz gerekiyorsa gerçekten bir "getirme" simülasyonu yaparsınız. Yani git fetch -v --dry-runne ihtiyaç vardır.
Claudio Floreani

Yanıtlar:


858

İlk kullanım git remote update, uzaktan referanslarınızı güncel hale getirmek için. Ardından, aşağıdakilerden biri gibi birkaç şeyden birini yapabilirsiniz:

  1. git status -unoizlediğiniz dalın önde mi, arkasında mı yoksa ayrışmış mı olduğunu size bildirir. Hiçbir şey söylemiyorsa, yerel ve uzak aynıdır.

  2. git show-branch *masterisimleri 'master' ile biten tüm şubelerde (örn. master ve orijin / master ) taahhütleri gösterecektir .

Eğer kullanırsanız -vile git remote update( git remote -v updateeğer gerçekten başka komutları gerekmez) Eğer dalları güncellenmiş var olduğunu görebilirsiniz.

Ancak, bunu bir komut dosyasında veya programda yapmak ve doğru / yanlış değeriyle sonuçlanmak istediğiniz gibi görünüyor. Öyleyse, mevcut HEAD taahhüdünüz ile izlediğiniz şubenin başı arasındaki ilişkiyi kontrol etmenin yolları vardır , ancak dört olası sonuç olduğundan, evet / hayır cevabına indirgeyemezsiniz. Ancak, bir yapmaya hazırsanız pull --rebase, "yerel arkasında" ve "yerel" çekmek zorunda "olarak, diğer iki" çekmek gerek yok "olarak tedavi edebilirsiniz.

Bunu kullanarak herhangi bir ref'nin taahhüt kimliğini alabilirsiniz git rev-parse <ref>, böylece bunu master ve origin / master için yapabilir ve karşılaştırabilirsiniz. Eşitlerse, dallar aynıdır. Eşit değilse, hangisinin diğerinin önünde olduğunu bilmek istersiniz. Kullanmak git merge-base master origin/mastersize her iki dalın ortak atalarını söyleyecektir ve eğer ayrılmamışlarsa, bu biri veya diğeri ile aynı olacaktır. Üç farklı kimlik alırsanız, dallar birbirinden ayrılmıştır.

Bunu düzgün bir şekilde yapmak için, örneğin bir komut dosyasında, geçerli dalı ve izlediği uzak dalı ifade edebilmeniz gerekir. İçindeki bash istemi ayarlama işlevi, /etc/bash_completion.dşube adlarını almak için bazı yararlı kodlara sahiptir. Ancak, muhtemelen isimleri almanıza gerek yoktur. Git'in şube ve taahhütlere atıfta bulunmak için bazı düzgün kısayolları vardır (belgelendiği gibi git rev-parse --help). Özellikle, @mevcut dal için (bağımsız bir durumda olmadığınız varsayılarak) ve @{u}yukarı akış dalında (örneğin origin/master) kullanabilirsiniz. Yani git merge-base @ @{u}(karmasını) geri geldiğini şimdiki şube ve upstream ıraksar ve taahhüt edecek git rev-parse @ve git rev-parse @{u}siz iki ipuçları karmaları verecektir. Bu, aşağıdaki komut dosyasında özetlenebilir:

#!/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

Not: git'in eski sürümleri @kendi başına izin vermediğinden , bunun @{0}yerine kullanmanız gerekebilir .

UPSTREAM=${1:-'@{u}'}Geçerli dal için yapılandırılmış olandan farklı bir uzak dal ile karşılaşmak istemeniz durumunda, çizgi isteğe bağlı olarak yukarı akış dalını açıkça geçirmenize izin verir. Bu genellikle remotename / branchname biçimindedir . Herhangi bir parametre verilmezse, değer varsayılan olarak kullanılır @{u}.

Komut dosyası , izleme dallarını güncelleştirmek için bir git fetchveya git remote updateilk yaptığınızı varsayar . Bunu betiğin içine inşa etmedim, çünkü getirme ve karşılaştırmayı ayrı işlemler olarak yapabilmek daha esnek, örneğin zaten yakın zamanda getirdiğiniz için getirme olmadan karşılaştırmak istiyorsanız.


4
@takeshin Sanırım git ls-remote origin -h refs / heads / master'ı @brool tarafından önerildiği gibi git rev-list --max-count = 1 origin / master ile birleştirebilirsiniz. Aynı karma değerini döndürürlerse, uzak referanslarınızı (çekme, getirme, uzaktan güncelleme vb. İle) en son güncellediğinizden bu yana uzak şube değişmez. Bunun avantajı, tüm taahhütler hemen, ama daha rahat bir süre için bunu bırakabilir. Ancak, uzaktan güncelleme tahribatsız olduğundan, yine de yapabilirsiniz.
Neil Mayhew

2
Ayrıca git status -s -u no, daha kısa bir çıktı veren deneyebilirsiniz git status -u no.
Phillip Cloud

2
@mhulse git remote -v update,. git remote --helpDaha kapsamlı bir açıklama için çıktısına bakın .
Neil Mayhew

1
@ChrisMaes İyi bir nokta. Daha açık sözdizimi git'in eski sürümlerinde gereklidir. Sahip olduğum çeşitli sistemleri @{u}denedim ve git 1.8.3.2 ile işe yaradığını gördüm ama işe @yaramadı. Ancak ile @çalışır 1.8.5.4. Hikayenin ahlakı: git gelişmeye devam ediyor ve yapabileceğiniz en son sürüme sahip olmaya değer.
Neil Mayhew

1
@ İçin bir tanımlayıcı gerekiyor. @ Yerine @ {0} kullanabilirsiniz.
Ben Davis

132

Memba şubeniz varsa

git fetch <remote>
git status

Memba şubeniz yoksa

İki dalı karşılaştırın:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

Örneğin:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

( origin/masterUzaktan izleme şubeniz olduğunu varsayıyorum )

Yukarıdaki çıktıda herhangi bir taahhüt listelenmişse, gelen değişiklikleriniz vardır - birleştirmeniz gerekir. Hiçbir taahhüt listelenmemişse git logbirleştirilecek bir şey yoktur.

Bunun, bir izleme uzaktan kumandası olmayan bir özellik dalında olsanız bile çalışacağını unutmayın, çünkü Git tarafından hatırlanan yukarı akış dalınıorigin/master örtülü olarak kullanmak yerine açıkça belirtilir .


2
git fetch; git log HEAD.. --onelineYerel için varsayılan bir uzak dal varsa daha kısa bir gösterim bile kullanılabilir.
phil pirozhkov

@philpirozhkov Eğer varsayılan bir uzak dalınız varsa, basit bir "git durumu" sanırım. Cevabım, biri diğerini takip ediyor olsun veya olmasın, herhangi iki dal için genel bir cevaptı.
PlagueHammer

55
git rev-list HEAD...origin/master --countikisi arasında toplam "farklı" taahhüt sayısını verecektir.
Jake Berger

1
kısa ve basit. Yeni taahhütleri (iki kez
beğeniyorum

Bunu bir (Ubuntu) toplu iş dosyasında nasıl kullanabilirim, böylece bu komut bir çekme işleminin gerekli olduğunu göstermesi durumunda diğer komutları çalıştırabilir miyim?
Ulysses Alves

69

Bu bir komut dosyası içinse şunları kullanabilirsiniz:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(Not: önceki yanıtlara kıyasla bunun avantajı, geçerli şube adını almak için ayrı bir komuta gerek duymamanızdır. "HEAD" ve "@ {u}" (geçerli dalın yukarı akış) buna dikkat edin. "git rev-parse --help" daha fazla bilgi için.)


@ {U} 'u bağımsız olarak keşfettim ve sizinkini görmeden önce cevabımı güncelledim.
Neil Mayhew

1
Will git rev-parse @{u}aslında son bir olmadan taahhüt göstermek git fetch?
Kyle Strand

3
Bilet buydu! Bununla birlikte, mantığınız =="yukarı akışta değişiklik yoksa" anlamına gelir. Uygulamam !=için "yukarı akıştan değişiklik varsa" kontrol ederdim. git fetchÖnce unutmayın !
26'de ChrisPrime

1
Git getirmesini ekledim, çünkü orijinal soruyu cevaplamak gerçekten gerekli. btw @kısaltmasıdır HEAD.
user1338062

Windows kullanıcıları 5@{u}git rev-parse '@{u}'
7'de

36

Komuta

git ls-remote origin -h refs/heads/master

uzaktan kumandadaki geçerli başlığı listeleyecektir - bunu önceki bir değerle karşılaştırabilir veya yerel deponuzda SHA olup olmadığını görebilirsiniz.


1
Bu değerleri karşılaştırmak için herhangi bir örnek komut dosyası var mı?
takeshin

18
git rev-list HEAD...origin/master --countikisi arasında toplam "farklı" taahhüt sayısını verecektir.
Jake Berger

3
@jberger açıklığa kavuşturmak için, bu sadece geride olduğunuz taahhütlerin sayısını gösterir (ileri ve geri değil) ve sadece siz git fetchveya git remote updateilk önce çalışır . git statusayrıca bir sayı gösterir, btw.
Dennis

1
@Dennis diye düşündüm .."menşe / master taahhütleri, HEAD çıkarılması" (yani arkadaki taahhütlerin sayısı). Oysa, ...bir simetrik fark (yani önde ve arkada)
Jake Berger

3
Mükemmel. Anlayabildiğim kadarıyla, bu aslında kökeni güncellemeler için kontrol eden ancak örtük olarak bir yapmayan tek çözümdür fetch.
Kyle Strand

35

Aşağıda, mevcut şubenin HEAD taahhüt karmasını uzak yukarı akış şubesiyle karşılaştıran, ağır git fetchveya git pull --dry-runoperasyon gerektirmeyen bir Bash tekli astar var :

[ $(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

Bu biraz yoğun çizginin parçalanması:

  • Komutlar, $(x)Bash komut değiştirme söz dizimi kullanılarak gruplandırılır ve iç içe yerleştirilir .
  • git rev-parse --abbrev-ref @{u}kısaltılmış bir yukarı akış ref (ör. origin/master) döndürür ; bu daha sonra piped sedkomutu ile boşlukla ayrılmış alanlara dönüştürülür , örn.origin master .
  • Bu dize, git ls-remoteuzak dalın baş komutunu döndüren beslenir . Bu komut uzak havuzla iletişim kuracaktır. Piped cutkomutu, sekmeyle ayrılmış referans dizgisini kaldırarak yalnızca ilk alanı (satır karması) ayıklar.
  • git rev-parse HEAD yerel işlem karmasını döndürür.
  • Bash sözdizimi [ a = b ] && x || ytek astarı tamamlar: bu, bir test yapısı içindeki bir Bash dize karşılaştırmasıdır , bunu and-list ve veya-list yapılar izler .=[ test ]&& true || false

2
Ben ediyorum değil şube adlarında eğik çizgi kullanırsanız sed üzerinde / g kullanın. Bu sadece "sed 's / \ // /".
Martyn Davis

@wjordan Uzak depoya erişilemediğinde (veya bakım altında değilken) çözümünüz başarısız olur ve "güncel" tetiklenir
çerçeve

20

Https://github.com/badele/gitcheck betiğini görmenizi öneririm . Tüm Git depolarınızı bir geçişte kontrol etmek için bu komut dosyasını kodladım ve kimin işlemediğini ve kimin itmediğini / çekmediğini gösterir.

İşte bir örnek sonuç:

Resim açıklamasını buraya girin


6
temiz, saf kabukta yeniden yazma hakkında düşünme
Olivier Refalo

1
Şimdi, hile kontrolünü doğrudan bir docker konteynerinden de kullanabilirsiniz (dosyalarınız ana makinenizde) Daha fazla bilgi için gitcheck github projesine bakın
Bruno Adelé

Benzer bir araç bash git-multi-repo-tooling . git mrepo -cbu bekleyen tüm taahhütleri gösterecektir.
Greg

11

Bu çözümü @jberger'in yorumlarına dayandırdım.

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

önceki yorumunuzla ilgili olarak , bu noktada size kesin bir cevap veremem. Bu yorumları yaptığım sırada git'in derinliklerine, özellikle de uzaktan kumandalara ve difflere daldım. O zamandan bu yana birkaç ay geçti ve bu bilgilerin çoğu beynimin içine gömüldü. ;) İkisi arasında 'farklı' taahhütlerin sayısını arıyorsanız ..., çözümünüzün geçerli bir parçası gibi görünüyor.
Jake Berger

1
Teşekkürler. Bu temizdi.
Shobhit Puri

10

Zaten çok sayıda zengin özellikli ve ustaca cevap var. Biraz kontrast sağlamak için çok basit bir çizgiyle yapabilirim.

# 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

2
Orijinal cevap '!' eğer. Herhangi bir değişiklik olmadığında git farkının dönüş değeri sıfırdır.
thuovila

Orada "uzaktan kumandalar / kökeni / KAFA" yerine "kökeni / usta" veya başka bir değişiklik yerine İMO en iyi çözüm
Matthias Michael Engh

9

Bunu yapmanın en iyi yolu:

git diff remotes/origin/HEAD

Bu refspec'in kayıtlı olduğunu varsayarsak. Depoyu klonladıysanız, aksi takdirde (yani, repo yerel olarak de novo oluşturulduysa ve uzaktan kumandaya itildiyse), refspec'i açıkça eklemeniz gerekir.


9

Aşağıdaki komut dosyası mükemmel çalışıyor.

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

6

Brool tarafından önerilen yolu yapardım. Aşağıdaki tek satırlık komut dosyası, son taahhüt edilen sürümünüzün SHA1'ini alır ve uzaktaki kaynaklardan biriyle karşılaştırır ve değişiklikleri yalnızca farklı olmaları durumunda alır. Ve git pullveya tabanlı çözümler daha da hafiftir git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull

Git deposu "--depth 1" ile klonlanmışsa (indirme boyutunu sınırlamak için) bu komut başarısız olur. Bunu düzeltmenin bir yolu varsa biliyor musun?
Adam Ryczkowski

Git günlüğü birçok satır döndürüyor ve hata veriyor "bash: [: çok fazla argüman" geçeceğimgit rev-parse --verify HEAD
Drew Pierce

1
Bu bash tarafından yapılan basit bir dize karşılaştırmasıdır. Bir şey başarısız olursa, sözdizimini kontrol etmenizi öneririm (yani yanlış yazıyorsunuz). İlk olarak git log --pretty=%H ...refs/heads/master^ son taahhüt edilen sürümünüzün SHA1'ini git ls-remote origin -h refs/heads/master |cut -f1 almak için çalıştırın ve sonra uzaktaki kaynağın SHA1'ini almak için çalıştırın . Bu ikisi git komutlarıdır ve bash ile ilgisi yoktur. Kare parantez içinde bash'ın yaptığı şey, ilk komuttan çıktıyı ikincisi ile karşılaştırmaktır ve eğer eşitlerse, true değerini döndürür ve çalışır git pull.
Claudio Floreani

msgstr "ve eğer eşit ise, doğru döner ve çalışır git pull". Ben nitpicky davrandığımı biliyorum, ama sadece o olmalı birileri karışıklığı kaydetmek için "onlar eğer değil eşit". Ayrıca, hangi nedenle olursa olsun, ilk git komutu benim için çalışmaz. (Ben git'indeyim 2.4.1.) Bu yüzden sadece kullanıyorum git log --pretty=%H master | head -n1. Ama bunun tamamen aynı olup olmadığından emin değilim.
xd1le

6

Bu komut dosyasını çalıştırırsanız, geçerli dalın aşağıdakilere ihtiyacı olup olmadığını sınar 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
}

Bunu önlemek için Git kanca ön taahhüdü olarak koymak çok uygun

Merge branch 'foobar' of url:/path/to/git/foobar into foobar

daha commitönce ne zamanpulling .

Bu kodu bir kanca olarak kullanmak için komut dosyasını kopyalayıp yapıştırın.

.git/hooks/pre-commit

ve

chmod +x .git/hooks/pre-commit

6

Bunu yorumlarda kaçırmak kolay olduğu için bunu gerçek bir gönderi olarak göndermek istiyorum.

Bu soru için doğru ve en iyi cevap @Jake Berger tarafından verildi, Çok teşekkür ederim ahbap, herkesin buna ihtiyacı var ve herkes yorumlarda bunu özlüyor. Burada bununla mücadele eden herkes için doğru cevap, sadece bir git çekme yapmanız gerekip gerekmediğini bilmek için bu komutun çıktısını kullanın. çıktı 0 ise, açıkçası güncellenecek bir şey yoktur.

@stackoverflow, bu adama bir çan verin. Teşekkürler 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

4

git fetch (remote)Uzaktan referanslarınızı güncellemek için çalıştırın , size yenilikleri gösterecektir. Ardından, yerel şubenizi kontrol ettiğinizde, yukarı akışın arkasında olup olmadığını gösterecektir.


Sanırım zaten yerel şubeyi kontrol ettirdi, bu yüzden geride olup olmadığını göstermek için başka bir şeye ihtiyacı var. Bunu git durumu ile yapabilir.
Neil Mayhew

Doğru, uzaktan kumanda getirdikten sonra da bunu git statusgösterecektir.
che

1
Bu ruh hali içinde bir şey git pull --dry-runyapar, ama her dakika bir cron betiği çalıştırmak için ağır olduğunu düşünüyorum.
takeshin

@takeshin: Ağa gitmeden uzak depoları kontrol edemezsiniz. Eğer yeni bir şey yoksa, fetchdurumu kontrol etmekten daha fazlasını yapmayacaktır. Uzaktan güncellemelerde çok hızlı ve hafif bir reaksiyona ihtiyacınız varsa, uzak depoya bir tür bildirimleri takmak isteyebilirsiniz.
che

@takeshin: Uzaktaki repoyu her dakika kontrol etmek istiyorsanız DVCS'nin noktasını kaçırdığınızı düşünüyorum. Bütün fikir, bir süre bağımsız olarak gelişebilmeyi ve sonra daha sonra sorunsuz bir şekilde bir araya getirebilmektir. Her zaman depodaki en son şeylerin üstünde çalışmak zorunda olduğunuz cvs, svn, p4 vb. Başka birinin üzerinde çalıştığı bir şeye gerçekten ihtiyacınız varsa, çekmeye hazır olduğunu size bildirmek için e-posta gibi farklı bir iletişim mekanizması kullanmalısınız.
Neil Mayhew

4

Çözelti çok kısa ve kolayken tüm bu karmaşık öneriler:

#!/bin/bash

BRANCH="<your branch name>"
LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`

git remote update
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
        echo "Updating your branch $BRANCH"
        git pull --no-edit
else
        echo "No updates available"
fi

Değişiklikler olsa bile LAST_COMMIT ve LAST_UPDATE her zaman eşittir
canbax

Bu çözüm iyi ve basittir, git remote updateen son orijin taahhüt bilgilerini almak için kodunuzdan önce yürütülmüş olması gerekir
ak93

Should git remote updateönce eklenemez git showkomutları?
SETOP

2

İşte önceden tanımlanmış bir klasördeki tüm depoları kontrol eden bir Bash komut dosyasının sürümü:

https://gist.github.com/henryiii/5841984

İhtiyaç duyulan çekme ve itme ihtiyacı gibi yaygın durumlar arasında ayrım yapabilir ve çok iş parçacıklıdır, bu nedenle getirme bir kerede gerçekleşir. Çekme ve durum gibi çeşitli komutları vardır.

Yolunuzdaki bir klasöre bir sembolik bağlantı (veya komut dosyası) koyun, ardından git all status(, vb.) Olarak çalışır . Yalnızca orijin / master'ı destekler, ancak başka bir yöntemle düzenlenebilir veya birleştirilebilir.


1
git ls-remote | cut -f1 | git cat-file --batch-check >&-

deponuzda olmayan herhangi bir uzaktan kumandada başvurulan her şeyi listeler. Zaten sahip olduğunuz şeylerde uzaktan ref değişikliklerini yakalamak (örneğin, önceki taahhütlere sıfırlar) biraz daha zaman alır:

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

1

Belki bu, crontab olarak görev eklemek istiyorsanız:

#!/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

1

Basit regexp kullanma:

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

Bu işe yaramayacak. git durumu yalnızca yerel bir kontroldür ve bu nedenle yalnızca uzaktaki defs'lerinizi güncellediyseniz şubenizin arkasında olup olmadığını söyler.
minhaz1

0

Stephen Haberman'ın cevabına dayanan bir script versiyonu kullanıyorum:

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

Bu komut dosyasının çağrıldığı varsayılarak git-fetch-and-rebase, isteğe bağlı bir bağımsız değişkenle çağrılabilirdirectory name işlemi gerçekleştirmek yerel Git deposunun . Komut dosyası hiçbir bağımsız değişken olmadan çağrılırsa, geçerli dizinin Git deposunun bir parçası olduğunu varsayar.

Örnekler:

# 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

Bu kullanılabilir burada da.


0

Birçok cevap ve birden fazla gönderi okuduktan ve yarım gününü çeşitli permütasyonları denedikten sonra, bu benim ortaya çıktığım şeydi.

Windows kullanıyorsanız, Windows için Git tarafından sağlanan Git Bash'i (kurulum veya taşınabilir) kullanarak bu komut dosyasını Windows'ta çalıştırabilirsiniz.

Bu komut dosyası bağımsız değişkenler gerektiriyor

- yerel yol örn. / d / kaynak / proje1
- Git URL'si örn. Https: //username@bitbucket.org/username/project1.git
- parola

komut satırına düz metin olarak bir şifre girilmemesi gerekiyorsa,
sonra GITPASS'ın boş olup olmadığını kontrol etmek için komut dosyasını değiştirin; yapma
değiştirin ve Git'in şifre girmesine izin verin

Senaryo

- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.

Komut dosyası tarafından yazdırıldığı gibi bir değişiklik varsa, getirmeye veya çekmeye devam edebilirsiniz. Senaryo etkili olmayabilir, ama işi benim için halleder.

Güncelleme - 2015-10-30: URL'yi konsola şifre ile yazdırmayı önlemek için dev.

#!/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

0

Bunu arayan bu soru ile sonuçlanan windows kullanıcıları için, bazı cevapları powershell betiği olarak değiştirdim. Gerektiğinde değiştirin, bir .ps1dosyaya kaydedin ve isteğe bağlı olarak çalıştırın veya isterseniz planlayın.

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')
}

0

Neils yanıtı bana çok yardımcı oldu çünkü burada bağımlılığı olmayan bir Python çevirisi:

import os
import logging
import subprocess

def check_for_updates(directory:str) -> None:
    """Check git repo state in respect to remote"""
    git_cmd = lambda cmd: subprocess.run(
        ["git"] + cmd,
        cwd=directory,
        stdout=subprocess.PIPE,
        check=True,
        universal_newlines=True).stdout.rstrip("\n")

    origin = git_cmd(["config", "--get", "remote.origin.url"])
    logging.debug("Git repo origin: %r", origin)
    for line in git_cmd(["fetch"]):
        logging.debug(line)
    local_sha = git_cmd(["rev-parse", "@"])
    remote_sha = git_cmd(["rev-parse", "@{u}"])
    base_sha = git_cmd(["merge-base", "@", "@{u}"])
    if local_sha == remote_sha:
        logging.info("Repo is up to date")
    elif local_sha == base_sha:
        logging.info("You need to pull")
    elif remote_sha == base_sha:
        logging.info("You need to push")
    else:
        logging.info("Diverged")

check_for_updates(os.path.dirname(__file__))

hth


-5

Bunu şimdi yapan bir Phing betiği de bulabilirsiniz .

Üretim ortamlarımı otomatik olarak güncellemek için bir çözüme ihtiyacım vardı ve paylaştığım bu komut dosyası sayesinde çok mutluyuz.

Betik XML olarak yazılmıştır ve Phing'e ihtiyaç duyar .


Belki de senaryoyu buraya yapıştırmak iyi bir fikir değil, hala güncelliyoruz ...
Pol Dellaiera
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.