Yerel Git veri havuzumda değişiklik olup olmadığı nasıl bir Bash betiğini kontrol edebilirim?


176

Değişiklikleri kontrol ederlerse düzgün çalışmayan bazı komut dosyaları vardır.

Ben böyle denedim:

VN=$(git describe --abbrev=7 HEAD 2>/dev/null)

git update-index -q --refresh
CHANGED=$(git diff-index --name-only HEAD --)
if [ ! -z $CHANGED ];
    then VN="$VN-mod"
fi

Son işlemden bu yana bir değişiklik olup olmadığı konusunda bir tür boolean kontrolü var mı veya yerel veri havuzumda yeni değişiklikler olup olmadığını nasıl test edebilirim?

Tüm bunları bir sürüm oluşturma komut dosyası için yapıyorum (burada bir yerde buldum).


3
Sorun nedir git status?
karlphillip

4
@karlphillip: Gerçekten ihtiyacınız olmayan çok fazla işlem yapıyor.
Cascabel

1
@karlphillip bu bir "porselen" komutudur, yani: çıktılar insanlar tarafından okunmak üzere tasarlandığından ve (sürümler arasında veya yerelleştirme nedeniyle) değişebileceğinden komut dosyasında kullanım için uygun değildir
Andrew Spencer

Yanıtlar:


201

Yaptığınız şey neredeyse işe yarayacak: $CHANGEDboş olması durumunda teklif vermelisiniz ve -zboş testler yapmalısınız , yani değişiklik yok. Demek istediğin şuydu:

if [ -n "$CHANGED" ]; then
    VN="$VN-mod"
fi

Git'ten bir alıntı GIT-VERSION-GEN:

git update-index -q --refresh
test -z "$(git diff-index --name-only HEAD --)" ||
VN="$VN-dirty"

Görünüşe göre bunu kopyalıyordunuz, ama sadece alıntı detayını unuttun.

Tabii ki, bunu da yapabilirsiniz:

if git diff-index --quiet HEAD --; then
    # No changes
else
    # Changes
fi

Veya yalnızca "bir şeyler değişti" durumunu önemsiyorsanız:

if ! git diff-index --quiet HEAD --; then
    VN="$VN-mod"
fi

Kullanmanın --quietGit'in tek bir farkla karşılaşır işlemeyi durdurabilme avantajı vardır, bu nedenle tüm çalışma ağacınızı kontrol etmeniz gerekmeyebilir.


2
Merhaba, bu bir sorunun en iyi cevaplarından biriydi, bana ihtiyacım olan tüm bilgileri verdin ve diğerlerinin de ihtiyacım olduğunu söyledin :). Sonuncusuna ihtiyacım olacak, "bir şeyler değişti" :) ve haklısın, kopyaladım.
kmindi

9
Şaşırtıcı bash tamamlama betiğigit diff --no-ext-diff --quiet --exit-code kirli durumu belirlemek için kullanılıyor gibi görünüyor .
mjs

3
@mjs: Bu gerçekten böyle şeyler aramak için harika bir yer! Bu --no-ext-diffseçenek güvenlik için iyidir (birisinin harici bir dif sürücüsünü yapılandırması durumunda), ancak --exit-codezorunlu olmadığı için gerekli olmamalıdır --quiet.
Cascabel

4
İzlenmemiş dosyaları rapor etmediği için bu benim için çalışmaz
Cookie

1
git diff-indexraporlar yalnızca dosya değiştirme süreleri değişse bile (içeriklerini değil) değişir. Bir touchdosyaysanız, çalışmanın git statussıfırlanacağını bildirecektir. git statusAşağıdaki gibi kullanmak daha iyidir.
Sampo

303

Kullanma git status:

cd /git/directory
if [[ `git status --porcelain` ]]; then
  # Changes
else
  # No changes
fi

15
En iyi cevap, utanç 'kabuk ve git mimarlardan' cevaplar daha yüksek oy alıyor.
jwg

4
Bu, sürümsüz dosyaları hesaba kattığı ve porselen kullandığından harika, farklı git sürümleriyle daha uyumlu olmalıdır.
Jayd

25
İzlenmeyen dosyaları yoksaymak için: if [[ git status --porcelain --untracked-files=no]]; sonra
storm_m2138

4
Yerel değişiklikleri kontrol etmek için -> if [[ $(git status --porcelain | wc -l) -gt 0 ]]; then echo CHANGED else echo NOT CHANGED locally fi
Carlos Saltos

3
Bu kod işe yarar: Yürütme git status --porcelainçıkış boş değilse, bkz. Eğer öyleyse bu mevcut değişiklikler olduğu anlamına gelir.
bhathiya-perera

18

Jefromi'nin cevabı iyi olmasına rağmen, bunu sadece referans için gönderiyorum.

Git kaynak kodunda shaşağıdakileri içeren bir komut dosyası 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
}

Başvuru için ve bu hakkı $1okursam, çalıştırmak istediğiniz görevi adlandıran $2bir dize ve isteğe bağlı olarak hata durumunda özel bir hata iletisi içeren bir dize. Örneğin, şöyle deyinrequire_clean_work_tree deploy "Skipping deploy, clean up your work tree or run dev-push"
Şemsiye

6

Benzer bir sorunum vardı, ancak ek dosyaları da kontrol etmek zorunda kaldım. Bu yüzden aşağıdakileri yaptım:

cd /local/repo
RUN=0
git diff --no-ext-diff --quiet --exit-code || RUN=1
if [ $RUN = 0 ]; then
    RUN=`git ls-files --exclude-standard --others| wc -l`
fi

if [ $RUN = 0 ]; then
    exit 0
fi

5

git status senin arkadaşın

git statusÇalışmak için Git dizinine geçin:

cd c:/path/to/.git

Çalışma ağacını 'Bu işlem bir çalışma ağacında çalıştırılmalıdır' hatası almayacak şekilde ayarlamak için bir değişken ayarlayın:

WORKTREE=c:/path/to/worktree

git statusÇıktıyı bir Bash değişkeninde yakalama

--porcelainStandart bir formatta ve ayrıştırılabilecek garantileri kullanın :

CHANGED=$(git --work-tree=${WORKTREE} status --porcelain)

-N (null değil) ise değişiklikler olur.

if [ -n "${CHANGED}" ]; then
  echo 'changed';

else
  echo 'not changed';
fi

1
Bu, izlenmeyen dosyaları da algılama avantajına sahiptir.
Luiz

2

Bu da işe yarıyor:

if [ $(git status --porcelain | wc -l) -eq "0" ]; then
  echo "  🟢 Git repo is clean."
else
  echo "  🔴 Git repo dirty. Quit."
  exit 1
fi

1

Bu iyi çalışıyor. Ayrıca etkilenen dosyaları da listeler:

if git diff-index --name-status --exit-code HEAD;
then
    echo Git working copy is clean...;
else
    echo ;
    echo ERROR: Git working copy is dirty!;
    echo Commit your changes and try again.;
fi;

1
Eğer fark görmek istemiyorsanız git diff --no-ext-diff --quiet --exit-codeda iş yapar.
Alex

1

Burada bir fark olup olmadığını kontrol eden, kullanıcıya basan ve dağıtımdan önce değişiklik yapmak isteyip istemediklerini soran güzel bir Bash komut dosyası işlevleri kümesi. Bir Heroku ve Python uygulaması için üretilmiştir, ancak diğer uygulamalar için çok az değişikliğe ihtiyaç duyar.

commit(){
    echo "Please enter a commit message..."
    read msg
    git add . --all
    git commit -am $msg
}

check_commit(){
    echo ========== CHECKING FOR CHANGES ========
    changes=$(git diff)
    if [ -n "$changes" ]; then
        echo ""
        echo "*** CHANGES FOUND ***"
        echo "$changes"
        echo ""
        echo "You have uncomitted changes."
        echo "Would you like to commit them (y/n)?"
        read n
        case $n in
            "y") commit;;
            "n") echo "Changes will not be included...";;
            *) echo "invalid option";;
        esac
    else
        echo "... No changes found"
    fi
}

deploy(){
    check_commit
    echo ========== DEPLOYING TO HEROKU ========
    git push heroku master
    heroku run python manage.py syncdb
}

Gists'ten şu adresten kopyalayabilirsiniz: https://gist.github.com/sshadmand/f33afe7c9071bb725105


1

OP'nin sorusu şu anda 9 yıldan daha eski. man git-statusO zaman ne dedi bilmiyorum , ama şimdi şöyle diyor:

--porcelain[=<version>]  
Give the output in an easy-to-parse format for scripts. This is similar to the 
short output, but will remain stable across Git versions and regardless of user 
configuration. See below for details.  

The version parameter is used to specify the format version. This is optional and 
defaults to the original version v1 format.  

Bu, --porcelainargümanın bir repo durumunu değişiklikler için test etmeye uygun olduğunu göstermektedir.

OP sorusuna göre, "Son işlemden bu yana değişiklik olup olmadığını bir tür boolean kontrolü var mı, yoksa yerel depomda yeni değişiklikler olup olmadığını nasıl test edebilirim?"

Ben kendi başınabash boole veri türleri olduğunu sanmıyorum , ama bu yeterince yakın olabilir:

[ -z "`git status --porcelain`" ] && echo "NULL-NO DIFFS" || echo "DIFFS EXIST"

Bu, if-then-elsebir komut dosyası formu olarak yeniden kullanılabilir veya git repo klasöründeyken CLI'da olduğu gibi yürütülebilir . Aksi takdirde, -Cseçeneği ilgili repoya özgü bir yolla kullanın:

git -C ~/path/to/MyGitRepo status --porcelain 

Zeyilname:

  1. Bazıları -u, --untracked-fileyoksaymak istediği dosyalarda durum bildirmekten kaçınma seçeneğini kullanmanızı önerir . Bunun bir talihsiz ile geldiğini unutmayın yan etkisi olduğunu unutmayın : yeni eklenen dosyalar da bildirilmez. Seçenek bazı durumlarda yararlıdır , ancak kullanmadan önce dikkatlice düşünün.

0

İşte böyle yapıyorum ...

CHANGES=`git status | grep "working directory clean"`
if [ ! CHANGES -eq "" ] then
    # do stuff here
else
    echo "You have uncommitted changes..."
fi

3
Git durumunu kullanmayı seviyorum, ancak komut dosyalarında --porselen kullanmak ve sonucu hiçbir değişiklik için boş bir dize ile karşılaştırmak daha iyidir, çünkü sürümler arasında uyumsuz bir şekilde değişmemesi garanti edilir.
Paul Chernoch

0
nano checker_git.sh

bunu yapıştır

#!/bin/bash

echo "First arg: $1"

cd $1

bob="Already up-to-date."
echo $bob

echo $(git pull) > s.txt
cat s.txt
if [ "$(cat s.txt)" == "$bob" ]
then
echo "up"
else
echo "not up"

fi
rm -rf st.txt

Çalıştırmak sh checker_git.sh gitpath


0

@ Storm_m2138 @ @ RyanMoon 'un cevabına ( link ) dayanarak aşağıdakileri kullanıyorum Powershell.

function hasChanges($dir="."){ $null -ne (iex "git -C $dir status --porcelain --untracked-files=no") }

gci -Directory | ?{ hasChanges $_ } | %{ Write-Host "$_ has changes" }
gci -Directory | ?{ hasChanges $_ } | %{ iex "git -C $_ add -u"; iex "git -C $_ commit -m"Somemthing" }
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.