Git çalışma dizininin bir komut dosyasından temiz olup olmadığını belirleyin.


82

Ben çalışan bir komut dosyası var rsynchedef olarak Git çalışma dizinine sahip. Komut dosyasının çalışma dizininin temiz olup olmamasına bağlı olarak (davranışta değişiklik yapılmaması) veya farklı olmasına bağlı olarak farklı davranışlarda bulunmasını istiyorum. Örneğin, çıktısı git statusaşağıdaki gibi ise, komut dosyasının çıkmasını istiyorum:

git status
Already up-to-date.
# On branch master
nothing to commit (working directory clean)
Everything up-to-date

Eğer dizin temiz değilse, daha fazla komut çalıştırmasını istiyorum.

Bir kabuk betiğinde yukarıdaki gibi çıktıları nasıl kontrol edebilirim?


Son komuttan bir durumu kontrol etmek burada yardımcı olur mu? ($?)
UVV

Daha fazla ayrıntı verebilir misiniz lütfen? Senaryonuzun ana fikri nedir?
tachomi

@tachomi Ben düzenleme bağlamında ekledim
brentwpeterson

temiz olmadığını varsayabilir ve bir şey yapacağınızı git reset --hard origin/branch
söylersiniz ... bir

1
@SnakeDoc Yapabilirsiniz, ancak ters durumun daha yaygın olacağını varsayalım, yani yerel değişiklikleri yönetmemek için çalışma dizini kirliyse çıkın. Her iki durumu da düşünmek, gelecek okuyucular için soruyu daha faydalı hale getirecektir.
Thomas Nyman

Yanıtlar:


133

Çıktısının ayrıştırılması git statuskötü bir fikir çünkü çıktının makine tarafından okunabilir değil, insan tarafından okunabilir olması amaçlanmıştır. Çıktının Git'in gelecekteki sürümlerinde veya farklı şekilde yapılandırılmış ortamlarda aynı kalacağı garantisi yoktur.

UVV'lerin yorumu doğru yolda, ancak ne yazık ki kabul git statusedilmeyen değişiklikler olduğunda dönüş kodu değişmiyor. Bununla birlikte, --porcelainçıktının git status --porcelainkomut dosyaları için ayrıştırılması kolay bir biçimde biçimlendirilmesine neden olan ve Git sürümlerinde ve kullanıcı yapılandırmasından bağımsız olarak sabit kalmasını sağlayan bir seçenek sunar .

git status --porcelainYapılması gereken hiçbir değişiklik olmadığının göstergesi olarak boş çıktıları kullanabiliriz :

if [ -z "$(git status --porcelain)" ]; then 
  # Working directory clean
else 
  # Uncommitted changes
fi

Çalışma dizinindeki izlenmemiş dosyaları umursamıyorsak, bunları --untracked-files=nogöz ardı etmek için bu seçeneği kullanabiliriz :

if [ -z "$(git status --untracked-files=no --porcelain)" ]; then 
  # Working directory clean excluding untracked files
else 
  # Uncommitted changes in tracked files
fi

Koşullardan karşı bu daha sağlam hale getirmek için aslında neden git statusçıktı olmadan başarısız stdout, çek için daraltabilirsiniz:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else 
  # Uncommitted changes
fi

Ayrıca git status, çalışma dizini kirli olduğunda anlamlı bir çıkış kodu vermese de , bu farkın ne zaman ve ne zaman bulunmadığına göre , durumun diff yardımcı programına benzer davranmasını sağlayan bir seçenek git diffsağladığını --exit-codebelirtmek önemlidir .10

Bunu kullanarak, etiketlenmemiş değişiklikleri aşağıdakilerle kontrol edebiliriz:

git diff --exit-code

ve aşamalı, ancak şunlarla değişiklik yapmadı:

git diff --cached --exit-code

Her ne kadar git diffalt modüllerdeki takip edilmeyen dosyalar için uygun argümanlar üzerinden rapor verebilse de --ignore-submodules, maalesef asıl çalışma dizinindeki takip edilmeyen dosyalar hakkında rapor vermesinin mümkün olmadığı görülmektedir. Çalışma dizinindeki izlenmeyen dosyalar alakalıysa, git status --porcelainmuhtemelen en iyi bahis budur.


4
ughhh git status --porcelain, işleme ve takip edilmeyen dosyalar için aşamalı olmayan değişiklikler olsa bile 0 koduyla çıkacaktır.
Alexander Mills,

Bir git stashşey yapıp yapmayacağını önceden belirlemekle ilgilenmiştim (yararlı bir dönüş kodu vermez). --ignore-submodulesAksi halde git status, git stashgörmezden gelen alt modül değişikliklerini göstereceği gibi eklemek zorunda kaldım .
Devin Lane

1
@AlexanderMills: Ben de aynısını gözlemledim. Ama sonra ne if [ -zyaptığını kontrol ettim . -zAraçlarının şu dize boşsa, eğer değerlendirir için true. Başka bir deyişle, bu git status --porcelainhiçbir dizge ile sonuçlanmazsa, repo temizdir. Değilse, değiştirilmiş / eklenen / kaldırılmış dosyaları listeler ve artık boş bir dize değildir. ifDaha sonra değerlendirilir false.
Adeynack

19

kullanın:

git diff-index --quiet HEAD

Dönüş kodu çalışma dizininin durumunu yansıtır (0 = temiz, 1 = kirli). İzlenmeyen dosyalar göz ardı edilir.


6
Geçerli dizinde izlenmemiş dosya olduğunda 0 değerini döndürür.
Adam Parkin

2
Dosya / dokundu üzerine ama aksi endekse aynıdır olsaydı, ilk çalıştırmadan gerek git update-index --refreshönce git diff-index HEAD. Daha fazla bilgi: stackoverflow.com/q/34807971/1407170
sffc

@AdamParkin Yayınlamadan önce sadece tüm dosyaları ekliyorum git add .. Genellikle bir komut dosyasında kullanmak için bir yoldur
ceztko

Bu harika. Sıfır olmayan bir dönüş / çıkış kodunun da bir 'hata' olarak yorumlandığını unutmayın; eğer set -e ile bir komut dosyasındaysanız , komut dosyası 'kirli' durumundan çıkar. Bu set +e, aramadan önce yaparak gitve set -edeğerlendirdikten sonra tekrar ekleyerek önlenebilir $?.
orion elenzil

1

André'nin mükemmel cevabına küçük uzatma .

Bu, sonuçları değerlendirmenin ve daha önce sete verilen bir senaryoda iseniz bir tuzaktan kaçınmanın bir yoludur .

İzlenmeyen dosyalar göz ardı edilir.

set +e
git diff-index --quiet HEAD

if [ $? == 1 ] ; then
  set -e
  GIT_MODS="dirty"
else
  set -e
  GIT_MODS="clean"
fi
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.