यदि मेरे स्थानीय गिट रिपॉजिटरी में परिवर्तन हो तो मैं बैश स्क्रिप्ट में कैसे जांच कर सकता हूं?


176

कुछ स्क्रिप्ट हैं जो परिवर्तनों के लिए जाँच करने पर सही ढंग से काम नहीं करती हैं।

मैंने इसे इस तरह आज़माया:

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

क्या किसी प्रकार की बूलियन जांच है अगर पिछले प्रतिबद्ध के बाद से परिवर्तन हुए हैं, या अगर मैं अपने स्थानीय भंडार में नए परिवर्तन कर रहा हूं तो मैं वास्तव में कैसे परीक्षण कर सकता हूं?

मैं यह सब एक संस्करण निर्माण स्क्रिप्ट के लिए कर रहा हूं (जो मुझे यहां कहीं मिला)।


3
इसमें गलत क्या है git status?
कर्लफिलिप

4
@karlphillip: यह बहुत अधिक प्रसंस्करण करता है जिसकी आपको वास्तव में आवश्यकता नहीं है।
कैसाब्ले

1
@Klphillip यह एक "चीनी मिट्टी के बरतन" कमांड है, जिसका अर्थ है: स्क्रिप्ट में उपयोग के लिए उपयुक्त नहीं है क्योंकि उत्पादन को मनुष्यों द्वारा पढ़ा जा सकता है और परिवर्तन हो सकता है (संस्करणों के बीच या स्थानीयकरण के कारण)
एंड्रयू स्पेन्सर

जवाबों:


201

आप जो कर रहे हैं वह लगभग काम करेगा: आपको $CHANGEDखाली होने की स्थिति में उद्धरण देना चाहिए , और -zखाली के लिए परीक्षण करना चाहिए , जिसका अर्थ है कि कोई बदलाव नहीं। आपका मतलब क्या था:

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

Git's का एक उद्धरण GIT-VERSION-GEN:

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

ऐसा लगता है कि आप उस की नकल कर रहे थे, लेकिन आप उद्धृत करने के उस विवरण को भूल गए।

बेशक, आप भी ऐसा कर सकते हैं:

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

या यदि आप केवल "कुछ बदल गया है" मामले की परवाह करते हैं:

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

उपयोग करने --quietसे यह लाभ होता है कि जैसे ही यह एक एकल अंतर का सामना करता है, वैसे ही Git प्रसंस्करण बंद कर सकता है, इसलिए इसे आपके संपूर्ण कार्य वृक्ष की जाँच नहीं करनी पड़ सकती है।


2
नमस्ते, यह एक सवाल पर सबसे अच्छे जवाबों में से एक था, आपने बस मुझे वह सारी जानकारी दी जो मुझे चाहिए थी और जो मेरी ज़रूरत थी, :)। मुझे बस पिछले एक की आवश्यकता होगी, "कुछ बदल गया है" :) और आप सही थे, मैंने इसे कॉपी किया।
किमी 34

9
गंदे राज्य को निर्धारित करने के लिए अद्भुत बैश पूरा करने वाली स्क्रिप्ट का उपयोग git diff --no-ext-diff --quiet --exit-codeकरने लगता है ।
mjs

3
@ mjs: यह वास्तव में इस तरह की चीजों को देखने के लिए एक शानदार जगह है! --no-ext-diffविकल्प हालांकि, (मामले में किसी को एक बाहरी diff ड्राइवर को कॉन्फ़िगर किया है) सुरक्षा के लिए अच्छा है --exit-code, आवश्यक नहीं होना चाहिए, क्योंकि यह से गर्भित है --quiet
कैस्केबेल

4
यह मेरे लिए काम नहीं करता है क्योंकि यह बिना पढ़ी हुई फाइलों की सूचना नहीं देता है
कुकी

1
git diff-indexरिपोर्ट बदलती है भले ही केवल फ़ाइल संशोधन समय बदल गया हो (और उनकी सामग्री नहीं)। यदि आप touchएक फाइल करते हैं, तो यह संशोधन की रिपोर्ट करेगा जो चल रहा है git statusरीसेट करेगा। git statusनीचे के रूप में उपयोग करना बेहतर है।
सम्पो

303

का उपयोग कर git status:

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

15
सबसे अच्छा जवाब, 'शेल और गिट आर्किटेक्ट्स' के जवाब शर्मनाक हैं।
jwg

4
यह बहुत अच्छा है क्योंकि यह बिना फाइलों के खाते में जाता है और चीनी मिट्टी के बरतन का भी उपयोग करता है, यह अलग-अलग गिट संस्करणों के साथ अधिक संगत होना चाहिए।
'12

25
अनियोजित फ़ाइलों को अनदेखा करने के लिए: यदि [[ git status --porcelain --untracked-files=no]]; उसके बाद
तूफ़ान_एम २१३

4
स्थानीय परिवर्तनों की जाँच के लिए -> if [[ $(git status --porcelain | wc -l) -gt 0 ]]; then echo CHANGED else echo NOT CHANGED locally fi
कार्लोस साल्टोस

3
यह कोड क्या करता है:git status --porcelain यदि उत्पादन खाली नहीं है तो निष्पादित करें । यदि ऐसा है तो इसका मतलब है कि परिवर्तन मौजूद हैं।
भाथिया-परेरा

18

हालांकि जेफ्रोमी का जवाब अच्छा है, मैं इसे सिर्फ संदर्भ के लिए पोस्ट कर रहा हूं।

Git source कोड से एक shस्क्रिप्ट आती है जिसमें निम्नलिखित शामिल हैं।

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
}

संदर्भ के लिए, और यदि मैं यह सही पढ़ता हूं, $1तो एक स्ट्रिंग एक नामकरण कार्य है जिसे आप चलाना चाहते हैं और $2एक स्ट्रिंग है जिसमें वैकल्पिक रूप से विफलता पर कस्टम त्रुटि संदेश है। उदाहरण के लिए, इसे कॉल करेंrequire_clean_work_tree deploy "Skipping deploy, clean up your work tree or run dev-push"
छाता

6

मुझे एक समान समस्या थी, लेकिन मुझे अतिरिक्त फ़ाइलों के लिए भी जांच करनी थी। इसलिए मैंने निम्नलिखित कार्य किया:

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 आपका दोस्त है

git statusकाम करने के लिए गिट निर्देशिका में बदलें :

cd c:/path/to/.git

वर्क ट्री को सेट करने के लिए एक वैरिएबल सेट करें ताकि आपको यह न मिले 'यह ऑपरेशन वर्क ट्री में चलाया जाना चाहिए:'

WORKTREE=c:/path/to/worktree

git statusआउटपुट को बैश वैरिएबल में कैप्चर करें

का प्रयोग करें --porcelainजो एक मानक प्रारूप और parsable में होने की गारंटी देता है:

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

इफ-एन (शून्य नहीं), हमारे पास परिवर्तन हैं।

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

else
  echo 'not changed';
fi

1
इससे अनकैप्ड फ़ाइलों का भी पता लगाने का लाभ है।
लुइज़ सी।

2

यह भी काम करता है:

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

1

यह अच्छी तरह से काम करता है। यह प्रभावित फाइलों की सूची भी देगा:

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
यदि आप यह नहीं देखना चाहते हैं कि git diff --no-ext-diff --quiet --exit-codeयह कार्य भी करता है।
एलेक्स

1

यहाँ बैश स्क्रिप्ट फ़ंक्शंस का एक अच्छा सेट है जो जाँचता है कि क्या कोई अंतर है, यह उपयोगकर्ता को प्रिंट करता है और उपयोगकर्ता को संकेत देता है कि क्या वे तैनाती से पहले परिवर्तन करना चाहते हैं। यह एक हरोकू और पायथन एप्लिकेशन के लिए बनाया गया है, लेकिन इसे किसी अन्य एप्लिकेशन के लिए बहुत कम बदलाव की जरूरत है।

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 से कॉपी कर सकते हैं: https://gist.github.com/sshadmand/f33afe7c9071bb780105


1

ओपी का सवाल अब 9 साल से ज्यादा पुराना है। मुझे नहीं पता man git-statusकि तब क्या कहा गया था, लेकिन यहाँ यह अब क्या कहता है:

--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.  

इससे पता चलता है कि --porcelainपरिवर्तन के लिए रेपो की स्थिति का परीक्षण करने के लिए तर्क अच्छी तरह से अनुकूल है।

ओपी के सवाल को गलत बताया, "क्या किसी प्रकार की बूलियन जांच है अगर पिछले प्रतिबद्ध के बाद से परिवर्तन हुए हैं, या मैं वास्तव में परीक्षण कैसे कर सकता हूं अगर मेरे स्थानीय भंडार में नए बदलाव हैं?"

मुझे नहीं लगता कि प्रतिbash बूलियन डेटा प्रकार हैं , लेकिन यह काफी करीब हो सकता है:

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

यह if-then-elseएक स्क्रिप्ट के लिए एक फॉर्म के रूप में फिर से कास्ट किया जा सकता है , या जैसा कि निष्पादित किया जा सकता है- gm रेपो फोल्डर में रहते हुए CLI है । अन्यथा, -Cब्याज के रेपो के लिए एक पथ कल्पना के साथ विकल्प का उपयोग करें :

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

परिशिष्ट:

  1. कुछ लोग सलाह देते हैं कि जिन -u, --untracked-fileफाइलों को अनदेखा करना चाहते हैं उन पर रिपोर्टिंग स्थिति से बचने के लिए विकल्प का उपयोग करें । ध्यान दें कि यह एक दुर्भाग्यपूर्ण साइड-इफ़ेक्ट के साथ आता है : नई जोड़ी गई फाइलें या तो स्टेटस नहीं होती हैं। विकल्प कुछ स्थितियों में उपयोगी है , लेकिन उपयोग करने से पहले सावधानी से विचार करें।

0

यहाँ है कि मैं यह कैसे करते हैं ...

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

3
मुझे गिट स्थिति का उपयोग करना पसंद है, लेकिन लिपियों में चीनी मिट्टी के बरतन का उपयोग करना बेहतर है और परिणाम में बिना किसी बदलाव के एक खाली स्ट्रिंग की तुलना करें, क्योंकि यह गारंटी है कि संस्करणों में असंगत तरीके से नहीं बदलना चाहिए।
पॉल चेरोच

0
nano checker_git.sh

इसे पेस्ट करें

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

Daud sh checker_git.sh gitpath


0

@ Storm_m2138 के आधार पर @ RyanMoon के उत्तर ( लिंक ) पर टिप्पणी मैं निम्नलिखित का उपयोग कर रहा हूं 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" }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.