Mevcut branşta işlenecek bir şey olup olmadığını nasıl kontrol edebilirim?


172

Amaç bir kabuk komutunda değerlendirilebilecek kesin bir durum elde etmektir.

Denedim git statusama taahhüt edilecek öğeler olsa bile her zaman 0 döndürür.

git status
echo $?  #this is always 0

Bir fikrim var ama bence bu oldukça kötü bir fikir.

if [ git status | grep -i -c "[a-z]"> 2 ];
then
 code for change...
else
  code for nothing change...
fi

başka yolu var mı?


aşağıdaki çözmeyle güncelleyin, Mark Longair'in gönderisine bakın

Bunu denedim ama bir soruna neden oluyor.

if [ -z $(git status --porcelain) ];
then
    echo "IT IS CLEAN"
else
    echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
    echo git status
fi

Aşağıdaki hatayı alıyorum [: ??: binary operator expected

Şimdi adama bakıyorum ve git farkını deniyorum.

=================== umudum için kod ve umut daha iyi cevap ======================

#if [ `git status | grep -i -c "$"` -lt 3 ];
# change to below code,although the above code is simple, but I think it is not strict logical
if [ `git diff --cached --exit-code HEAD^ > /dev/null && (git ls-files --other --exclude-standard --directory | grep -c -v '/$')` ];
then
        echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
    exit 1

else
    exit 0
fi

4
Güncellenmiş bölümünde, gerçekte neyi yapmadığı anlaşılıyor Eckes de anlaşılacağı onun cevabını diyor, sen etrafında çift tırnak koymak gerekir - $(git status --porcelain). Ayrıca, iletinize ünlem işaretleri koymak istiyorsanız, çift tırnak yerine tek tırnak kullanmanız gerekir - yani echo 'PLEASE COMMIT YOUR CHANGE FIRST!!!'yerine
Mark Longair

4
Mark'ın dediği gibi: Sana söylediğim gibi, etrafına çift tırnak koymanız gerekiyor$(git status --porcelain) !
eckes

1
Cevapların bir kısmını içermiyorsa, bu sorular çok daha yararlı olacaktır.
oberlies

@ 9nix00 size söylenenleri yapın ve yukarıdaki kabuk komut dosyanızdaki hatayı düzenleyip düzeltin: HATA: if [-z $ (bazı komut)] DÜZELTME: eğer [-z "$ (bazı komut)"]
MarcH

Yanıtlar:


232

Çıktının git status --porcelainboş olup olmadığını test etmenin bir alternatifi, önem verdiğiniz her durumu ayrı ayrı test etmektir. Örneğin, çıktısında izlenmemiş dosyalar varsa, her zaman ilgilenmeyebilir git status.

Örneğin, yerel etiketlenmemiş değişiklik olup olmadığını görmek için aşağıdakilerin dönüş koduna bakabilirsiniz:

git diff --exit-code

Aşamalı ancak işlenmemiş herhangi bir değişiklik olup olmadığını kontrol etmek için aşağıdakilerin dönüş kodunu kullanabilirsiniz:

git diff --cached --exit-code

Son olarak, çalışma ağacınızda göz ardı edilmeyen izlenmemiş dosyalar olup olmadığını öğrenmek istiyorsanız, aşağıdaki komutun çıktısının boş olup olmadığını test edebilirsiniz:

git ls-files --other --exclude-standard --directory

Güncelleme: Aşağıda, çıktıdaki dizinleri hariç tutmak için bu komutu değiştirip değiştiremeyeceğinizi sorarsınız. Boş dizinleri ekleyerek --no-empty-directoryhariç tutabilirsiniz, ancak bu çıktıdaki tüm dizinleri hariç tutmak için, aşağıdaki gibi çıktıyı filtrelemeniz gerektiğini düşünüyorum:

git ls-files --other --exclude-standard --directory | egrep -v '/$'

-vİçin egrepyollara yalnızca çıkış desen uyuşmuyor hatları ve desen herhangi bir satırı bir o biter eşleşir /.


Bu ipuçlarını eğdim ve bir sorunum var. yani, git ls-files --other --exclude-standard --directory dizinleri içeren listeyi alır. Bu dizini hariç tutmak bir yolu var mı?
9nix00

evet, bu istiyorum. ve yazımı yeni kod kodu için güncelliyorum. Ben seninkini daha kod lol rağmen daha katı mantıklı olduğunu düşünüyor ... ve umut daha iyi cevaplar görünür.
9nix00

3
@albfan: git-diff man sayfasında : "diff (1) 'e benzer kodlarla programdan çıkış yapın. Yani fark varsa 1 ile çıkar ve 0 fark yok demektir."
Mark Longair

Sadece belirtmek gerekirse , en azından 2007 13da0fc0'dan beri , kabuk komut dosyaları için gerçekten kullanışlı ve
git'in

10
--quiet(bu da ima eder --exit-code) sadece çıkış kodunu isteyenler için çıktıyı susturur.
phs

113

Dönüş değeri, yapılacak herhangi bir değişiklik olup olmadığını değil git status, çıkış kodunu gösterir git status.

git statusÇıktının bilgisayar tarafından daha okunabilir bir sürümünü istiyorsanız ,

git status --porcelain

git statusBununla ilgili daha fazla bilgi için açıklamasına bakın .

Örnek kullanım (komut dosyası git status --porcelainherhangi bir çıktı verip vermediğini test eder , ayrıştırma gerekmez):

if [ -n "$(git status --porcelain)" ]; then
  echo "there are changes";
else
  echo "no changes";
fi

Test etmek için dizeyi, yani çıktısını alıntılamanız gerektiğini lütfen unutmayın git status --porcelain. Test yapıları hakkında daha fazla ipucu için Gelişmiş Bash Komut Dosyası Kılavuzu'na (Bölüm dizesi karşılaştırması ) bakın.


merhaba, sen iyi bir öneri vermek, ben denedim, ama senaryoda, bu bazı soruna neden olur, ben bunu kullanırsak, eğer bunu kullanırsak [-z $ (git status --porcelain)]; bazı hatalar alacak, [: ??: ikili operatör kılavuzu bulmak ve [-z $ (git status --short)] eğer bunu kullanın bekleniyor; bu işe yarayabilir, teşekkürler!
9nix00

üzgünüm, hala sorun var. taahhüt temiz olduğunda. porselen kullanın ve her ikisi de kısa. ama taahhüt temiz olmadığında. hataya neden olur. [: ??: ikili operatör bekleniyor. Bence belki kodlamak için base64 kullanmayı denemeliyiz. izin ver deneyeyim! base64 komut araçlarını indirme .... lol
9nix00

taahhüt temiz olmadığında soruna neden olur.
9nix00

1
Harika bir çözüm. Daha fazla sağlamlık || echo noiçin, git statustemel olarak başarısız olursa çalışma alanının yanlışlıkla temiz bildirilmemesi için komut ikamesine ekleyebilirsiniz . Ayrıca, kodunuz (övgüye değer) POSIX uyumludur, ancak bir bash kılavuzuna bağlandığınızdan [[ ... ]], POSIX uyumlu yerine bash kullanırsanız [ ... ], komut ikamesini iki kez alıntılamanıza gerek olmadığını ( zarar vermez) [[ -z $(git status --porcelain) ]].
mklement0

@eckes Birkaç gün önce yeni bir repo başlattım, bir taahhüt ekledim, bazı taahhüt öncesi kanca yazmaya ve neyin taahhütte bulunacağını ve söylediklerimin davamda işe yaramadığını kontrol etmeye çalıştım.
alinsoar

33

Benim gibiyseniz, var olup olmadığını bilmek istersiniz:

1) mevcut dosyalarda yapılan değişiklikler 2) yeni eklenen dosyalar 3) silinmiş dosyalar

ve özellikle 4) izlenmeyen dosyaları bilmek istemiyorum.

Bunu yapmalı:

git status --untracked-files=no --porcelain

Repo temizse komut dosyasından çıkmak için bash kodum. İzlenmeyen dosyalar seçeneğinin kısa sürümünü kullanır:

[[ -z $(git status -uno --porcelain) ]] && echo "this branch is clean, no need to push..." && kill -SIGINT $$;

4
İçin +1 —untracked-files=no; Testinizin basitleştirilebileceğini düşünüyorum [[ -z $(git status --untracked-files=no --porcelain) ]]. git statustemel şeyler ters giderse sürece, stderr'e yazmak gerekir - ve sonra yok olduğunu çıkışını görmek istiyorum. (Bu olayda daha sağlam bir davranış istiyorsanız, || echo notemizlik testinin hala başarısız olması için komut ikamesine ekleyin ). Dize karşılaştırmaları / -zoperatör çok satırlı dizelerle ilgilenebilir - buna gerek yoktur tail.
mklement0

2
teşekkürler @ mklement0, hatta biraz daha kısa:[[ -z $(git status -u no --porcelain) ]]
moodboom

1
düzeltme: Kısa sürümüm aslında "no" adlı dosyadaki durumu kontrol ediyor! Bzzt. Olması gereken: [[ -z $(git status -uno --porcelain) ]]
moodboom

2
İzlemeyi takdir ediyorum; bu ince bir hata - ders, isteğe bağlı bağımsız değişkenlere sahip kısa seçeneklerin , aralarında boşluk olmadan, doğrudan bağımsız değişkenin eklenmesi gerektiğidir . Düzeltilmiş kısa versiyonu doğrudan cevabınıza dahil etmeye ne dersiniz?
mklement0

9

Testi gerçekleştirmek için git status --porcelainbir basitle birleştirmek mümkündür grep.

if git status --porcelain | grep .; then
    echo Repo is dirty
else
    echo Repo is clean
fi

Bunu bazen basit bir astar olarak kullanıyorum:

# pull from origin if our repo is clean
git status --porcelain | grep . || git pull origin master

-qsSessiz kılmak için grep komutunuza ekleyin .


2
Zarafet için +1; hafif uyarı: git statusölümcül başarısız olmalıdır (örn. bozuk bir repo), testiniz yanlışlıkla temiz bir çalışma alanını rapor edecektir . Bir seçenek kullanmaktır git status --porcelain 2>&1, ancak grep kullandıysanız bu hata mesajını 'yiyecektir' -q. (Bununla başa çıkmak zarafeti kaybedecek: (git status --porcelain || echo err) | grep -q .)
mklement0

alternatif olarak, bir yazabilirsiniz:test -z "$(git status --porcelain)" || git pull origin master
VasiliNovikov

5

Git kaynak kodundan aşağıdakileri içeren bir sh betiği vardır.

require_clean_work_tree () {
    git rev-parse --verify HEAD >/dev/null || exit 1
    git update-index -q --ignore-submodules --refresh
    err=0

    if ! git diff-files --quiet --ignore-submodules
    then
        echo >&2 "Cannot $1: You have unstaged changes."
        err=1
    fi

    if ! git diff-index --cached --quiet --ignore-submodules HEAD --
    then
        if [ $err = 0 ]
        then
            echo >&2 "Cannot $1: Your index contains uncommitted changes."
        else
            echo >&2 "Additionally, your index contains uncommitted changes."
        fi
        err=1
    fi

    if [ $err = 1 ]
    then
        test -n "$2" && echo >&2 "$2"
        exit 1
    fi
}

Bu sniplet, daha önce bilinen dosyalarda herhangi bir değişiklik olup olmadığını nasıl kullanabileceğinizi git diff-filesve git diff-indexbulabileceğinizi gösterir . Ancak, çalışma ağacına yeni bir bilinmeyen dosyanın eklenip eklenmediğini bulmanıza izin vermez.


bu yeni dosyalar dışında iyi çalışır. bunu ekleyebiliriz. Eğer ! git ls-dosyaları - diğer --exclude-standart --dizin | grep -c -v '/ $' sonra 0 başka echo'dan çıkın "lütfen yeni dosyanızı ekleyin, eklemek istemiyorsanız, lütfen git-ignore dosyasına ekleyin." çıkış 1 fi
9nix00

Sadece if [ -n "$(git ls-files --others --exclude-standard)" ]herhangi bir ek borulama veya grevleme olmadan izlenmemiş dosyaları tespit etmek için yeterli olmalıdır.
Arrowmaster

5

Bu konuda bir test yapardı:

git diff --quiet --cached

veya bunun açık olması:

git diff --quiet --exit-code --cached

nerede:

--exit kod

Diff (1) 'e benzer kodlarla programdan çıkın. Yani, farklılıklar varsa 1 ile çıkar ve 0 fark olmadığı anlamına gelir.

--sessiz

Programın tüm çıktılarını devre dışı bırakın. --Exit-kodunu ima eder


3

Tartışmaya biraz geç kaldım, ancak eğer git status --porcelainhiçbir şey döndürmezse 0 çıkış koduna sahip olmanız gerekiyorsa ve! = 0 ise, bunu deneyin:

exit $( git status --porcelain | wc -l )

Bu, 255'ten fazla satır olduğunda sorun alma riski altında olan satır sayısını çıkış kodu yapar. Yani

exit $( git status --porcelain | head -255 | wc -l )

hesap verecek;)


1
255 satırdan fazla çıktı varsa, bu temelde tanımsız olacaktır.
üçlü

İyi tespit, teşekkürler!
Skeeve

2

Bunu bir komut dosyasında kullanıyorum:

  • 0 her şey temiz olduğunda
  • 1 diff veya izlenmeyen dosyalar olduğunda

    [-z "$ (git durumu - porselen)"]


kullanarak if ! git diff --quiet; thendaha temiz ve daha fazla ölçülebilir (Sanırım) 'dir. Başka bir deyişle, stdout'u değil çıkış kodunu kullanın.
Alexander Mills

1
@AlexanderMills , önbellekteki değişiklikler için git diff --quietfarklı davranır git status --porcelain.
Martin von Wittich

0

Güzel değil, ama çalışıyor:

git status | grep -qF 'working directory clean' || echo "DIRTY"

İletinin yerel ayara bağlı olup olmadığından emin değilsiniz, bu yüzden LANG=Cönüne bir koyunuz .

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.