इस पेज पर

git status

संक्षेप में: git status एक read-only कमांड है, जो आपकी working डायरेक्टरी, staging area (index) और commit history (HEAD) की मौजूदा स्थिति देखता है। इन तीन अवस्थाओं के बीच तेज़ three-way comparison करके यह बताता है कि कौन-सी फ़ाइलें untracked, modified या अगले commit के लिए staged हैं। disk पर बदलाव लिखने से पहले repository की स्थिति देखते रहने के लिए यह सबसे प्रमुख tool है।


git status वास्तव में क्या करता है?

Git को अच्छी तरह समझने के लिए यह मानना छोड़ना होगा कि वह केवल फ़ाइल diffs ट्रैक करने वाला tool है। इसके बजाय Git को content के तीन अलग-अलग trees के manager के रूप में देखें। ये trees आपके code के lifecycle के अलग-अलग चरणों को दिखाते हैं:

  1. Working Directory (या Working Tree): आपके operating system के filesystem पर मौजूद वास्तविक sandbox। जब आप VS Code या Vim में फ़ाइल edit करते हैं, तो सीधे Working Directory बदलती है।
  2. Index (या Staging Area): .git/index में स्टोर binary cache फ़ाइल। यह pre-commit manifest की तरह काम करती है—एक single flat डायरेक्टरी listing, जिसमें अगले commit में जाने वाले exact फ़ाइल paths, permissions और फ़ाइलें के SHA-1 hashes होते हैं।
  3. HEAD (Last Commit): आपकी current branch के tip पर मौजूद commit object का pointer। HEAD repository के सबसे हाल के checkpoint को दिखाता है।
graph LR
    subgraph "The Three Trees of Git"
        A[Working Directory<br>Local Files] -->|git add| B[Index / Staging Area<br>.git/index]
        B -->|git commit| C[HEAD<br>Last Commit]
    end
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px

जब आप git status चलाते हैं, Git पूरी commit history का full scan नहीं करता। इसके बजाय वह अत्यधिक optimized three-way diff चलाता है:

  • तुलना A: Index बनाम HEAD। Git staging area (.git/index) के path-and-hash mappings की तुलना HEAD द्वारा pointed tree object से करता है। अगर Index में किसी फ़ाइल का hash HEAD से अलग है, या फ़ाइल Index में है लेकिन HEAD में नहीं है, तो उसे “Changes to be committed” (staged) माना जाता है।
  • तुलना B: Working Directory बनाम Index। Git आपकी hard drive की current फ़ाइलें की तुलना Index में स्टोर path-and-hash mappings से करता है। अगर working डायरेक्टरी में फ़ाइल की state उसके staging record से अलग है, तो उसे “Changes not staged for commit” (modified) माना जाता है।
  • तुलना C: Working Directory बनाम Index (Untracked Check)। Working डायरेक्टरी में मिली ऐसी हर फ़ाइल, जिसका Index में कोई corresponding entry नहीं है (और जो .gitignore rules से ignored भी नहीं है), “Untracked फ़ाइलें” मानी जाती है।

Stat Cache: git status इतना तेज़ क्यों है?

सैकड़ों हज़ार फ़ाइलें वाले बड़े project में working डायरेक्टरी की हर फ़ाइल को hash करके Index से compare करना git status को बहुत धीमा कर देगा।

इसे रोकने के लिए Git Stat Caching तकनीक इस्तेमाल करता है। .git/index फ़ाइल में हर tracked फ़ाइल का metadata होता है, जिसमें शामिल हैं:

  • mtime: आखिरी modification का timestamp।
  • ctime: आखिरी metadata change का timestamp।
  • dev / ino: filesystem device और inode numbers।
  • uid / gid: user और group owners।
  • फ़ाइल size: bytes में फ़ाइल का size।

जब आप git status चलाते हैं, Git working डायरेक्टरी की फ़ाइलें के filesystem stats के लिए operating system से पूछता है (बहुत तेज़ lstat() system call)। अगर फ़ाइल size, inode या modification time .git/index में cached values से match करते हैं, तो Git मानता है कि फ़ाइल content बदला नहीं है। वह फ़ाइल content पढ़ना और SHA-1 hash फिर से calculate करना छोड़ देता है। केवल stat metadata अलग होने पर Git फ़ाइल खोलेगा, उसका hash बनाएगा और differences जाँचेगा।


.git/ के अंदर क्या होता है (व्यावहारिक पड़ताल)

आइए एक fresh repository बनाकर देखें कि फ़ाइल lifecycle के हर चरण में आंतरिक फ़ाइल comparisons बदलने पर git status कैसे व्यवहार करता है।

चरण 1: Repository initialize करें

आइए git init से एक clean repository initialize करते हैं।

$ mkdir git-status-demo && cd git-status-demo
$ git init
Initialized empty Git repository in /git-status-demo/.git/

अगर हम .git डायरेक्टरी की स्थिति देखें, तो अभी कोई index फ़ाइल नहीं है और HEAD एक डिफ़ॉल्ट branch की ओर point करता है, जिसमें कोई commit नहीं है।

$ cat .git/HEAD
ref: refs/heads/main

$ ls -l .git/index
ls: cannot access '.git/index': No such file or directory

अब git status चलाएँ:

$ git status
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

पर्दे के पीछे: Git ने .git/index खोजा। वह नहीं मिला, इसलिए उसने तय किया कि tracked फ़ाइलें की संख्या शून्य है। उसने .git/HEAD पढ़कर current branch (main) ढूँढी, branch reference को resolve किया (no commits yet होने के कारण वह अभी मौजूद नहीं है), और निष्कर्ष निकाला कि कोई commit नहीं है।

चरण 2: Untracked फ़ाइल जोड़ें

आइए README.md नाम की फ़ाइल बनाएँ।

$ echo "# Git Status Demo" > README.md

अब git status देखें:

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	README.md

nothing added to commit but untracked files present (use "git add" to track)

पर्दे के पीछे:

  1. Git working डायरेक्टरी scan करता है और README.md पाता है।
  2. वह .git/index पढ़ने की कोशिश करता है। Index फ़ाइल अब भी मौजूद नहीं है।
  3. File working डायरेक्टरी में है लेकिन Index में नहीं, इसलिए Git उसे untracked mark करता है।

चरण 3: File stage करें

git add से फ़ाइल stage करें।

$ git add README.md

.git/ के अंदर तुरंत दो चीज़ें होती हैं:

  1. Git README.md के content को compress करके .git/objects/ में नया blob object लिखता है।
  2. Git .git/index फ़ाइल बनाता है और README.md की entry लिखता है, जिसमें उसके फ़ाइल stats और blob का SHA-1 hash शामिल होता है।

Plumbing कमांड git ls-files --stage से Index entry verify करें:

$ git ls-files --stage
100644 c5d3bc8d139371ff4cf9e97623b2255fb722b2d9 0	README.md

.git/objects/ में blob मौजूद है या नहीं, यह देखें:

$ git cat-file -t c5d3bc8d139371ff4cf9e97623b2255fb722b2d9
blob

$ git cat-file -p c5d3bc8d139371ff4cf9e97623b2255fb722b2d9
# Git Status Demo

अब git status चलाएँ:

$ git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   README.md

पर्दे के पीछे:

  1. Git .git/HEAD -> refs/heads/main पढ़ता है। Reference refs/heads/main अब भी मौजूद नहीं है (अभी कोई commit नहीं है)।
  2. Git .git/index पढ़ता है और एक entry पाता है: README.md, जो blob c5d3bc8d1393... की ओर point करती है।
  3. HEAD खाली है और Index में README.md है, इसलिए Index में ऐसी फ़ाइल है जो HEAD में नहीं है। इस कारण फ़ाइल को staged for commit (new फ़ाइल) दिखाया जाता है।
  4. Git README.md के working-डायरेक्टरी stat की तुलना .git/index में cached stat से करता है। दोनों match करते हैं, इसलिए कोई unstaged modification नहीं है।

चरण 4: Commit बनाएँ

git commit से बदलाव commit करें।

$ git commit -m "Initial commit"
[main (root-commit) 55a420b] Initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

अब git status देखें:

$ git status
On branch main
nothing to commit, working tree clean

पर्दे के पीछे:

  1. Commit ने एक commit object (hash: 55a420b...) और repository state दिखाने वाला tree object बनाया।
  2. Git ने .git/refs/heads/main को इस नए commit object के hash से update किया।
  3. git status चलने पर वह HEAD -> refs/heads/main -> commit 55a420b resolve करता है।
  4. वह commit 55a420b के tree (जिसमें README.md blob c5d3bc8d1393... के साथ listed है) की तुलना staging index .git/index से करता है (जिसमें वही README.md फ़ाइल और blob c5d3bc8d1393... है)। Hash identical हैं, इसलिए कोई staged changes नहीं हैं।
  5. वह Index stats की तुलना filesystem stats से करता है। वे match करते हैं, इसलिए कोई modified changes नहीं हैं।

चरण 5: File modify करें

Working डायरेक्टरी में README.md modify करें:

$ echo "# Git Status Demo" > README.md
$ echo "Added a new line of text." >> README.md

अब git status चलाएँ:

$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

पर्दे के पीछे:

  1. Git README.md पर lstat() call करता है और उसका metadata पढ़ता है। Modified time (mtime) और फ़ाइल size .git/index की entry की तुलना में बदल गए हैं।
  2. Git README.md खोलता है और modified content का SHA-1 hash calculate करता है (नया hash: c7cb148f2e21f06939fe9ac90d42a302294f12dd)।
  3. यह computed hash .git/index में स्टोर hash (c5d3bc8d1393...) से अलग है, इसलिए Git फ़ाइल को modified but unstaged बताता है।
  4. Git Index entry की तुलना HEAD के tree entry से करता है। दोनों में c5d3bc8d1393... है, इसलिए कोई staged changes नहीं हैं।
graph TD
    subgraph "Three-Way Hash Comparison"
        HEAD["HEAD Commit Tree<br>Hash: c2ba505..."]
        Index["Staging Index<br>Hash: c2ba505..."]
        Work["Working Directory<br>Hash: d78be55..."]
    end
    HEAD ===|Staged: Match| Index
    Index---|Modified: Mismatch| Work

कमांड विकल्प और उन्नत उपयोग

git status सरल है, लेकिन कई advanced options इसे scripting, debugging और complex states देखने के लिए अधिक powerful बनाते हैं।

1. Short Format (--short या -s)

बहुत-सी modified फ़ाइलें के साथ डिफ़ॉल्ट verbose output भारी लग सकता है। Short format बदलावों को compact two-column layout में दिखाता है।

$ git status -s
 M README.md
?? new_script.js

Columns Staging Area (column 1) और Working Directory (column 2) को दिखाते हैं:

  • M (col 1 में space, col 2 में M): फ़ाइल working डायरेक्टरी में modified है, लेकिन modification staged नहीं है।
  • M (col 1 में M, col 2 में space): फ़ाइल modified है और बदलाव Index में staged है।
  • MM (दोनों columns): फ़ाइल modified हुई, वे बदलाव staged हुए, और working डायरेक्टरी में फ़ाइल फिर modified हुई।
  • A : फ़ाइल staging area में नई add हुई है।
  • ??: फ़ाइल untracked है।

2. Ignored फ़ाइलें शामिल करना (--ignored)

Default रूप से .gitignore patterns से match होने वाली फ़ाइलें status में पूरी तरह छिपी रहती हैं। अगर आप समझना चाहते हैं कि कोई specific फ़ाइल track क्यों नहीं हो रही, तो --ignored flag इस्तेमाल करें।

$ echo "logs/" > .gitignore
$ mkdir logs && touch logs/debug.log
$ git status --ignored
On branch main
...
Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
	logs/

3. --porcelain से scripting

अगर shell script, git alias या CI/CD script में repository dirty है या नहीं जाँचना हो, तो standard git status output को कभी parse न करें (यह Git versions के बीच बदल सकता है)। इसके बजाय --porcelain इस्तेमाल करें।

$ git status --porcelain
 M README.md
?? new_script.js

--porcelain flag guarantee करता है कि output format backwards-compatible और Git के future versions में stable रहेगा। यह predictable machine-readable format में output देता है और colors व helper text हटा देता है।

Bash script में repository में uncommitted changes जल्दी जाँचने के लिए:

if [ -z "$(git status --porcelain)" ]; then
    echo "Working directory is clean. Proceeding..."
else
    echo "Error: You have uncommitted changes!" >&2
    exit 1
fi

वास्तविक स्थिति: File permissions और line endings

कभी-कभी git status फ़ाइल को modified दिखाता है, लेकिन git diff चलाने पर code में कोई बदलाव दिखाई नहीं देता। आम तौर पर इसके दो कारण होते हैं: line endings या फ़ाइल mode changes।

स्थिति A: File permissions (chmod)

Git executable bits ट्रैक करता है (100755 executables के लिए, 100644 regular फ़ाइलें के लिए)। अगर आप या कोई script फ़ाइल की permissions बदलते हैं (जैसे chmod +x script.sh), तो Git फ़ाइल को modified बताएगा।

अगर project में फ़ाइल permissions मायने नहीं रखतीं (जैसे cross-platform Windows/macOS/Linux team में), तो permission changes ignore करने के लिए Git configure कर सकते हैं:

$ git config core.filemode false

स्थिति B: Line ending inconsistencies (LF बनाम CRLF)

Windows systems परंपरागत रूप से lines समाप्त करने के लिए Carriage Return और Line Feed (CRLF) इस्तेमाल करते हैं, जबकि Linux और macOS Line Feed (LF) इस्तेमाल करते हैं। अगर text editor line endings अपने-आप बदल देता है, तो binary hashes अलग होने के कारण Git पूरी फ़ाइल को modified mark कर देगा।

Line-ending mismatch को globally ठीक करने के लिए Git की autocrlf setting configure करें:

# On Windows
$ git config --global core.autocrlf true

# On macOS/Linux
$ git config --global core.autocrlf input

आम pitfalls और गलतियाँ

1. Subdirectory में git status चलाना

अगर आप nested subdirectory से git status चलाते हैं, तो Git डिफ़ॉल्ट रूप से paths को उसी subdirectory के सापेक्ष दिखाता है। इससे paths कभी-कभी confusing लग सकते हैं। आप जहाँ से भी कमांड चला रहे हों, paths को root डायरेक्टरी के सापेक्ष दिखाने के लिए चलाएँ:

$ git status --relative=false

2. Staged फ़ाइल फिर भी “Changes not staged for commit” में दिखती है

Beginners के लिए यह classic confusion है। अगर आप git add file.txt से फ़ाइल stage करते हैं और फिर editor खोलकर file.txt में एक और line जोड़ते हैं, तो git status फ़ाइल को दो बार दिखाएगा:

Changes to be committed:
	modified:   file.txt

Changes not staged for commit:
	modified:   file.txt

ऐसा इसलिए होता है क्योंकि git add चलाते समय Git ने फ़ाइल का exact snapshot stage किया था। उसके बाद के edits केवल working डायरेक्टरी में हैं और उन्हें फिर से stage करना होगा।

3. .gitignore में फ़ाइल होने पर भी वह दिख रही है

अगर कोई फ़ाइल .gitignore में जोड़ने से पहले ही Git में tracked थी, तो बदलने पर वह git status में दिखती रहेगी। .gitignore केवल untracked फ़ाइलें को track होने से रोकता है। File को computer से delete किए बिना tracking रोकने के लिए उसे Index से हटाएँ:

$ git rm --cached path/to/file.txt

कमांड त्वरित संदर्भ

CommandDescription
git statusStatus को full verbose format (डिफ़ॉल्ट) में दिखाता है।
git status -s / --shortStatus को condensed, two-column format में दिखाता है।
git status -b / --branchBranch और tracking branch details दिखाता है (short format में context जोड़ता है)।
git status --ignored.gitignore से ignored फ़ाइलें दिखाता है।
git status --porcelainMachine parsing और scripting के लिए optimized output।
git status -uallUntracked डायरेक्टरी के अंदर की individual फ़ाइलें दिखाता है, केवल डायरेक्टरी name नहीं।

FAQ (लोग अक्सर पूछते हैं)

git status “On branch main, nothing to commit, working tree clean” क्यों कहता है?

इस message का अर्थ है कि Git के तीनों trees पूरी तरह aligned हैं। Working Directory की सभी फ़ाइलें के SHA-1 hashes आपके Staging Index (.git/index) में listed hashes से match करते हैं और वे hashes HEAD commit के tree में registered hashes से भी match करते हैं। करने या record करने के लिए कोई modification नहीं है।

`git status को कैसे पता चलता है कि फ़ाइल का नाम बदला गया है?

Git renames को explicitly track नहीं करता। वह उनका पता लगाता है। जब एक path पर फ़ाइल delete और दूसरे path पर add होती है, तो git status Index पढ़ता है और content hashes compare करता है। Deleted फ़ाइल और added फ़ाइल का content identical (या बहुत similar) हो, तो Git similarity index calculate करके फ़ाइल को renamed report करता है (जैसे renamed: old_file.txt -> new_file.txt)।

क्या git status चलाने से मेरी फ़ाइलें बदल सकती हैं?

नहीं। आपकी working डायरेक्टरी और commit history के संबंध में git status पूरी तरह read-only है। यह फ़ाइलें inspect करता और metadata compare करता है। अधिकतम, performance सुधारने के लिए यह .git/index में stat cache को current filesystem times के अनुसार update कर सकता है, लेकिन आपके source code को कभी modify नहीं करेगा और changes revert नहीं करेगा।

Remote branch से पीछे/आगे हूँ या नहीं, यह git status से कैसे जाँचूँ?

अगर आपकी local branch किसी remote branch (जैसे origin/main) को track करती है, तो git status आपकी local branch के HEAD reference की तुलना cached remote-tracking reference (.git/refs/remotes/origin/main) से करेगा। यह “Your branch is ahead of ‘origin/main’ by 2 commits” या “Your branch is behind…” जैसे messages दिखाएगा। ध्यान रखें कि यह आपके last fetch पर आधारित है; git status remote server से query नहीं करता। इसलिए up-to-date tracking information के लिए पहले git fetch चलाएँ।


अपना ज्ञान जाँचें

क्विज़ लोड हो रही है…