অনির্ধারিত পরিবর্তন আছে কিনা তা আমি প্রোগ্রামগতভাবে কীভাবে নির্ধারণ করব?


226

একটি মেকফাইলে, আমি যদি কিছু আপত্তিহীন পরিবর্তন (তবে কার্যকরী গাছ বা সূচকগুলিতে) থাকে তবে আমি কিছু ক্রিয়া সম্পাদন করতে চাই। এটি করার সবচেয়ে পরিষ্কার এবং সবচেয়ে কার্যকর উপায় কোনটি? যে কমান্ডটি এক ক্ষেত্রে শূন্য এবং অন্য ক্ষেত্রে শূন্য নয় তার রিটার্ন মান সহ আমার প্রযোজ্য suit

আমি git statusআউটপুটটি চালাতে এবং পাইপ করতে grepপারি, তবে আমার মনে হয় আরও ভাল উপায় থাকতে হবে।


উত্তর:


288

আপডেট : ওপি ড্যানিয়েল Stutzbach তুলে ধরে মন্তব্য করে এই সহজ কমান্ড git diff-indexতার জন্য কাজ করেন:

git update-index --refresh 
git diff-index --quiet HEAD --

( নরঙ্গোন মন্তব্যগুলিতে উল্লেখ করেছে যে, যদি এমন ফাইলগুলি থাকে যা স্পর্শ করা হয়েছে, তবে যাঁর বিষয়বস্তু সূচকের মতো একই, তবে আপনাকে git update-index --refreshআগে চালানো দরকার git diff-index, অন্যথায় diff-indexভুলভাবে গাছটি নোংরা বলে জানাবেন)

তারপরে আপনি " কমান্ডটি সফল হয়েছে কিনা তা কীভাবে পরীক্ষা করবেন? " আপনি যদি এটি কোনও ব্যাশ স্ক্রিপ্টে ব্যবহার করছেন তা দেখতে পাবেন:

git diff-index --quiet HEAD -- || echo "untracked"; // do something about it

দ্রষ্টব্য: অ্যান্টনি সটাইল মন্তব্য করেছেন

git diff-index HEAD ...কোনও শাখায় ব্যর্থ হবে যার কোন কমিট নেই (যেমন একটি নতুন আরম্ভিত সংগ্রহস্থল)।
আমি খুঁজে পেয়েছি একটি কাজgit diff-index $(git write-tree) ...

আর haridsvআউট পয়েন্ট মন্তব্যের যে git diff-filesএকটি উপর নতুন ফাইলটি একটি পরিবর্তন যেমন শনাক্ত করতে পারেনি।
নিরাপদ পদ্ধতির মাধ্যমে মনে হয় git addপ্রথমে ফাইলটি চালাবেন এবং তারপরে git diff-indexচালানোর আগে সূচিতে কিছু যুক্ত হয়েছে কিনা তা ব্যবহার করুন git commit

git add ${file_args} && \
git diff-index --cached --quiet HEAD || git commit -m '${commit_msg}'

এবং মন্তব্যে 6502 রিপোর্ট:

আমি যে সমস্যার মুখোমুখি হয়েছি git diff-indexতা হ'ল যে পার্থক্য রয়েছে যখন ফাইলগুলির টাইমস্ট্যাম্প ব্যতীত আর কিছুই নেই। একবার
চালানো git diffসমস্যার সমাধান করে (আশ্চর্যজনকভাবে যথেষ্ট, git diffআসলে এখানে স্যান্ডবক্সের সামগ্রী পরিবর্তন করে .git/index)

এই টাইমস্ট্যাম্প সমস্যাগুলিও ঘটতে পারে যদি গিটটি ডকারে চলমান থাকে


আসল উত্তর:

"প্রোগ্রাম্যমেটিক্যালি" অর্থ কখনই চীনামাটির বাসন কমান্ডগুলির উপর নির্ভর করবেন না
সর্বদা নদীর গভীরতানির্ণয় আদেশের উপর নির্ভর করুন

বিকল্পগুলির (" পছন্দসইgit status --porcelain ) জন্য" ময়লা সূচক বা গিটের সাথে তালাবিহীন ফাইলগুলি পরীক্ষা করা "দেখুন

আমরা নতুন " require_clean_work_treeফাংশন " থেকে অনুপ্রেরণা নিতে পারি যা আমরা কথা বলেছি ;) (অক্টোবর ২০১০ এর প্রথম দিকে)

require_clean_work_tree () {
    # Update the index
    git update-index -q --ignore-submodules --refresh
    err=0

    # Disallow unstaged changes in the working tree
    if ! git diff-files --quiet --ignore-submodules --
    then
        echo >&2 "cannot $1: you have unstaged changes."
        git diff-files --name-status -r --ignore-submodules -- >&2
        err=1
    fi

    # Disallow uncommitted changes in the index
    if ! git diff-index --cached --quiet HEAD --ignore-submodules --
    then
        echo >&2 "cannot $1: your index contains uncommitted changes."
        git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2
        err=1
    fi

    if [ $err = 1 ]
    then
        echo >&2 "Please commit or stash them."
        exit 1
    fi
}

12
"স্ক্রিপ্টিংয়ের জন্য প্লাম্বিং বনাম চীনামাটির বাসন" নীতিটি এমন একটি পাঠ যা জাকুব নারাবস্কি আমাকে বারবার উল্লেখ করেছিলেন: " গিটে বর্তমান প্রকল্পের সমস্ত লগ কিভাবে তালিকাভুক্ত করবেন? ", " গিট: দিনে দিনে
চেঞ্জলগ

18
লিঙ্ক আপনি সুপারিশ কিছু ক্লিক করার পর, আমি দেখেছি আমি যা খুঁজছেন ছিল: git diff-index --quiet HEAD
ড্যানিয়েল স্টুটজবাচ

11
@ ড্যানিয়েলস্টুটজবাচ: যদি আপনার HEADকার্যকারী ডিরেক্টরিতে কোনও ফাইল কল করা থাকে তবে এটি ব্যর্থ হতে পারে । আরও ভাল ব্যবহার git diff-index --quiet HEAD --
ডেভিড ওঙ্গারো

7
এবং তবুও ম্যানুয়ালটি git status --helpরাজ্যগুলিতে: --porcelain আউটপুটটিকে স্ক্রিপ্টগুলির জন্য সহজে
এড র্যান্ডাল

7
@ ভনসি যে সত্যিই কোন ধারণা দেয় না। এইভাবে আপনি সবকিছুকে তার বিপরীতে মোচড় দিতে পারেন। --পোরস্লেইন আপনাকে শীঘ্রই ভেঙে যাচ্ছে এমন ধারণা দেয়। যদি তা না হয় তবে এটিকে প্লাম্বিং বলা উচিত, চীনামাটির বাসন নয়। --Porcelain ব্যবহারের ফলে আপনার স্ক্রিপ্টটি ভঙ্গ না হওয়ার কারণ, যা এটিকে কোনও চীনামাটির বাসের স্ক্রিপ্ট হিসাবে উপস্থাপন করে না ;-)। আপনি যদি নিজের স্ক্রিপ্টটি নষ্ট করতে চান, আপনি - পোরস্লেইন ব্যবহার করবেন না !! সুতরাং এটি এটি পুরোপুরি বোধগম্য এবং সবাইকে ছুড়ে ফেলে।
Xennex81

104

অন্যান্য সমাধানগুলি খুব পুঙ্খানুপুঙ্খভাবে থাকলেও আপনি যদি সত্যই দ্রুত এবং ময়লা কিছু চান তবে এই জাতীয় কিছু চেষ্টা করুন:

[[ -z $(git status -s) ]]

এটি কেবল স্থিতি সংক্ষিপ্তসারে কোনও আউটপুট আছে কিনা তা পরীক্ষা করে cks


7
আমার জন্য কাজ কর. বিপরীত (আপনার পরিবর্তনগুলি আছে) এর জন্য -n ব্যবহার করুন উদাহরণস্বরূপ `যদি [[-n $ (গিট স্ট্যাটাস -s)]]]; তারপর ... fi`
হারুন

এটি কাজ করে, তবে [[ ... ]]সিনট্যাক্স আসলে কী করছে তা আপনি বলতে পারবেন ? এর আগে আমি এর আগে কখনও দেখিনি।
জিএমএ

2
@ EE git statusএই পরীক্ষায় রিটার্ন কোডটি আসলে উপেক্ষা করা হয়। এটি কেবল আউটপুট দেখায়। পরীক্ষা করে দেখুন এই ব্যাশ সংশ্লিষ্ট পৃষ্ঠা আরো তথ্যের জন্য [, [[এবং কিভাবে ব্যাশ মধ্যে কাজ পরীক্ষা।
নেপথর

2
এটি প্রায় সঠিক উত্তর, তবে স্ক্রিপ্টের জন্য এখানে--porcelain প্রদর্শিত প্যারামিটার ব্যবহার করা ভাল
মারিউস পাভেলস্কি

2
আপনি git status -s -uallতালাবিহীন ফাইল অন্তর্ভুক্ত করতে ব্যবহার করতে চাইতে পারেন ।
বারফুইন

59

git diff --exit-codeকোনও পরিবর্তন হলে ননজারো ফিরিয়ে দেবে; git diff --quietকোন আউটপুট সঙ্গে একই। যেহেতু আপনি কার্যক্ষম গাছ এবং সূচকটি পরীক্ষা করতে চান, তাই ব্যবহার করুন

git diff --quiet && git diff --cached --quiet

অথবা

git diff --quiet HEAD

হয় এক যে আপনাকে বলা হবে যে সেখানে মঞ্জুরিবিহীন পরিবর্তনগুলি আছে যা মঞ্চস্থ হয়েছে কি না।


6
এগুলি সমতুল্য নয়। একক কমান্ড কেবল git diff --quite HEADআপনাকে জানায় যে কার্যকারী গাছটি পরিষ্কার কিনা, সূচকটি পরিষ্কার কিনা whether উদাহরণস্বরূপ, যদি fileHEAD ~ এবং HEAD এর মধ্যে পরিবর্তন করা হয়, তবে পরে git reset HEAD~ -- file, এটি 0 থেকে প্রস্থান করবে যদিও সূচীতে উপস্থিত পর্যায়যুক্ত পরিবর্তনগুলি রয়েছে (ডাব্লুটি == হেড, তবে সূচক! = হেড)।
ক্রিস জনসেন

2
সতর্কতা, এটি গিট আরএম, এএএএফএসের সাহায্যে মঞ্চ অঞ্চল থেকে সরানো ফাইলগুলি ধরবে না।
এনএমআর

24
নতুন (চিহ্নবিহীন) ফাইলগুলি সনাক্ত করে না git diff --quiet && git diff --cached --quiet
4LegsDrivenCat

17

@ নেপথরের উত্তরটি প্রসারিত:

if [[ -z $(git status -s) ]]
then
  echo "tree is clean"
else
  echo "tree is dirty, please commit changes before running this"
  exit
fi

1
এটা ভাল; আমি এটি পরীক্ষার মাধ্যমে $(git status -s "$file")এবং তারপরে একটি elseদফায় একক ফাইলগুলিকে স্বতঃস্মরণ করতে ব্যবহার করিgit add "$file"; git commit -m "your autocommit process" "$file"
toddkaufmann

আপনি করতে যে git status -sএকটি git status --porcelain ; git clean -ndপরিবর্তে, আবর্জনা ডিরেক্টরি এখানেও surfaced হবে অদৃশ্য যা git status
ইকমানাট

4

অন্যান্য উত্তরে নির্দেশিত হিসাবে, যেমন কমান্ড হিসাবে সহজ হিসাবে যথেষ্ট:

git diff-index --quiet HEAD --

আপনি যদি শেষ দুটি ড্যাশ বাদ দেন, আপনার নামের একটি ফাইল থাকলে কমান্ডটি ব্যর্থ হয় HEAD

উদাহরণ:

#!/bin/bash
set -e
echo -n "Checking if there are uncommited changes... "
trap 'echo -e "\033[0;31mFAILED\033[0m"' ERR
git diff-index --quiet HEAD --
trap - ERR
echo -e "\033[0;32mAll set!\033[0m"

# continue as planned...

সাবধানতার কথা: এই কমান্ডটি তালিবদ্ধ ফাইলগুলিকে উপেক্ষা করে।


2
যে উত্তরে মন্তব্যে ইঙ্গিত করা হয়েছে, এটি সদ্য যুক্ত হওয়া ফাইলগুলি সনাক্ত করতে পারে না
মাইনক্সিউ

না, এটি সূচি ফাইলগুলিতে নতুন যুক্ত হওয়া সনাক্ত করে। সবেমাত্র চেক করা হয়েছে।
সানমাই

প্রশ্ন দেখুন। আনট্রাক করা ফাইলগুলি কোনও পরিবর্তন নয় । git addএবং git cleanউদ্ধারে
সনমাই

4

স্টেস্ট না করা ও স্টেজড ফাইলগুলির তালিকা তৈরি করার জন্য আমি কিছু উপকারী গিট এলিয়াস তৈরি করেছি:

git config --global alias.unstaged 'diff --name-only'
git config --global alias.staged 'diff --name-only --cached'

তারপরে আপনি সহজে কাজগুলি করতে পারেন:

[[ -n "$(git unstaged)" ]] && echo unstaged files || echo NO unstaged files
[[ -n "$(git staged)" ]] && echo staged files || echo NO staged files

আপনার PATHডাকা জায়গায় কোথাও একটি স্ক্রিপ্ট তৈরি করে আপনি এটি আরও পঠনযোগ্য করতে পারেন git-has:

#!/bin/bash
[[ $(git "$@" | wc -c) -ne 0 ]]

এখন উপরোক্ত উদাহরণগুলি এটিকে সহজ করা যায়:

git has unstaged && echo unstaged files || echo NO unstaged files
git has staged && echo staged files || echo NO staged files

সম্পূর্ণতার জন্য এখানে তালিকার চিহ্নবিহীন এবং উপেক্ষা করা ফাইলগুলির জন্য অনুরূপ উপমা রয়েছে:

git config --global alias.untracked 'ls-files --exclude-standard --others'
git config --global alias.ignored 'ls-files --exclude-standard --others --ignored'

2

পাইথন এবং গিটপিথন প্যাকেজ সহ:

import git
git.Repo(path).is_dirty(untracked_files=True)

সংগ্রহস্থল পরিষ্কার না হলে সত্যটি ফেরত দেয়


এটি অন্যান্য মন্তব্যে উল্লিখিত কিছু "টাইমস্ট্যাম্প" সমস্যাগুলি এড়ানো হয়েছে
জেসন

1
দ্রষ্টব্য যে গিটপিথন কেবল গিট সিএলআই ব্যবহার করছে। আপনি যদি সেট LOGLEVEL=DEBUGকরে থাকেন তবে এটি চালানোর জন্য এটি ব্যবহার করে সমস্ত পোপেন আদেশগুলি দেখতে পাবেনgit diff
জেসন

-3

এখানে সর্বোত্তম, পরিষ্কার উপায়।

function git_dirty {
    text=$(git status)
    changed_text="Changes to be committed"
    untracked_files="Untracked files"

    dirty=false

    if [[ ${text} = *"$changed_text"* ]];then
        dirty=true
    fi

    if [[ ${text} = *"$untracked_files"* ]];then
        dirty=true
    fi

    echo $dirty
}

4
না, এটি সেরা নয়। git statusএটি একটি 'চীনামাটির বাসন' কমান্ড। স্ক্রিপ্টগুলিতে চীনামাটির বাসন কমান্ডগুলি ব্যবহার করবেন না যেহেতু তারা গিট সংস্করণের মধ্যে পরিবর্তন করতে পারে। পরিবর্তে 'প্লাম্বিং' কমান্ড ব্যবহার করুন।
spuder

3
আমি মনে করি আপনি যদি এটি ব্যবহার করার জন্য আপডেট করেন git status --porcelain(যা এই উদ্দেশ্যটির জন্য বোঝানো হয় - একটি স্থিতিশীল ফর্ম্যাট যা আপনি কোনও স্ক্রিপ্টে পার্স করতে পারেন), সম্ভবত -z (নিউলাইনের পরিবর্তে নাল-বিচ্ছিন্ন?) দিয়েও আপনি এই ধারণার সাথে দরকারী কিছু করতে পারেন । @ codyc4321 দেখতে stackoverflow.com/questions/6976473/... বিস্তারিত জানার জন্য
msouth
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.