8 जून 2026
GitDeveloper ToolsProductivity

Git के डिफ़ॉल्ट सेटिंग्स आपका समय बर्बाद कर रहे हैं

ग्यारह ग्लोबल git सेटिंग्स और बीस एलियस जो git के बंद करके शिप किए गए रोज़मर्रा के झुंझलाहटों को खत्म कर देते हैं: अपस्ट्रीम ब्रांच, मर्ज नॉइज़, आइडेंटिटी की गड़बड़ी, और बार-बार आने वाले rebase कॉन्फ़्लिक्ट।

11 मिनट पढ़ें

यह वह git कॉन्फ़िग है जो मैं हर मशीन पर चलाता हूं, ग्यारह ग्लोबल सेटिंग्स और बीस एलियस, हर एक इसलिए मौजूद है क्योंकि यह एक ख़ास रोज़मर्रा की झुंझलाहट खत्म करता है। यह सब चुरा लो।

कुछ समय पहले, एक टीममेट ने मुझे एक बिल्कुल नई ब्रांच पुश करते देखा और रोक दिया:

"रुको, यह अभी काम कैसे कर गया? बिना --set-upstream के?"

एक लाइन का कॉन्फ़िग। वह सालों से यह workaround टाइप करता आ रहा था।

वही बातचीत इस आर्टिकल की वजह है। ज़्यादातर डेवलपर्स git को फ़ैक्ट्री डिफ़ॉल्ट्स पर चलाते हैं, और git के फ़ैक्ट्री डिफ़ॉल्ट्स आपके लिए डिज़ाइन नहीं किए गए। वे कम्पैटिबिलिटी के लिए डिज़ाइन किए गए हैं। Git आपको एक बार चौंकाने की बजाय हज़ार बार टोकना पसंद करेगा।

तो हर कोई चुपचाप वही रोज़मर्रा का टैक्स चुकाता है, ज़्यादातर बिना नोटिस किए:

  • fatal: The current branch has no upstream branch, इतनी बार फिक्स टाइप की कि यह मसल मेमोरी बन गई
  • मर्ज कमिट्स हिस्ट्री को गंदा कर देते हैं क्योंकि एक साधारण pull मर्ज करता है
  • हर Mac प्रोजेक्ट पर हर git status में .DS_Store दिखता रहना
  • पांचवीं बार वही rebase कॉन्फ़्लिक्ट सुलझाना
  • पर्सनल ईमेल से ऑफ़िस रिपॉज़ में कमिट करना

इनमें से हर एक git के साथ आने वाला एक-लाइन का फिक्स है, बस बंद किया हुआ।

git के फ़ैक्ट्री डिफ़ॉल्ट्स का रोज़मर्रा का टैक्स: हर झुंझलाहट और उसकी एक-लाइन फिक्स

आगे जो है वह मेरा असली कॉन्फ़िग है, वह जो मेरे साथ हर मशीन पर जाता है। git जो कुछ भी सपोर्ट करता है उसका ढेर नहीं: यहां हर लाइन ने एक असली झुंझलाहट खत्म करके अपनी जगह कमाई है। दो हिस्से: पहले ग्लोबल सेटिंग्स, क्योंकि वे git का बर्ताव हर जगह बदलती हैं; फिर एलियस, क्योंकि वे यह बदलते हैं कि आप इसे कितनी तेज़ी से चला सकते हैं।

🪪 पहला हिस्सा: आइडेंटिटी, वह सेटिंग जो आपको शर्मिंदा कर सकती है

उस सेटिंग से शुरू करो जिसके नतीजे होते हैं:

git config --global user.name "Paurush Rai"
git config --global user.email "personal@email.com"

साफ़ है। लेकिन यहां वह हिस्सा है जो ज़्यादातर डेवलपर्स कभी सेट नहीं करते: ऑटोमैटिक वर्क/पर्सनल रूटिंग।

मैं एम्प्लॉयर का कोड ~/Developer/company/ के तहत रखता हूं। ~/.gitconfig में एक ब्लॉक:

[includeIf "gitdir:~/Developer/company/"]
    path = ~/.gitconfig-work

और ~/.gitconfig-work में बस यह होता है:

[user]
    email = work@company.com

includeIf रिपॉज़ के लोकेशन के आधार पर git आइडेंटिटी ऑटोमैटिकली रूट करता है

अब आइडेंटिटी इस बात से तय होती है कि रिपॉज़ कहां रहती है। company/ में कुछ भी क्लोन करो → वर्क ईमेल, ऑटोमैटिकली। बाकी सब → पर्सनल। न कुछ याद रखना, न प्रति-रिपॉज़ सेटअप, न कॉर्पोरेट ऑडिट लॉग में पर्सनल ईमेल, और न वीकेंड साइड प्रोजेक्ट्स पर वर्क ईमेल।

(ध्यान दो कि वर्क फ़ाइल में क्या नहीं है: नाम। includeIf ग्लोबल कॉन्फ़िग के ऊपर लेयर होता है, तो वर्क फ़ाइल सिर्फ़ वही घोषित करती है जो अलग है, ईमेल। बाकी सब इनहेरिट होता है।)

यह जितना दिखता है उससे ज़्यादा मायने रखता है, क्योंकि कमिट ईमेल परमानेंट होते हैं। ग़लत आइडेंटिटी से पुश करो और यह हमेशा के लिए हिस्ट्री में रह जाता है; GitHub कमिट को उसी अकाउंट का बताता है जिसका वह ईमेल है। आइडेंटिटी रिपॉज़ की एक प्रॉपर्टी होनी चाहिए, न कि इसकी कि आपने आख़िरी बार क्या टाइप करना याद रखा।

⚙️ पहला हिस्सा, जारी: बर्ताव वाली सेटिंग्स

ग्यारह लाइनें। हर एक एक ख़ास, बार-बार आने वाली झुंझलाहट खत्म करती है।

फिर कभी "no upstream branch" न देखो

git config --global push.autoSetupRemote true

वह एरर जो हर डेवलपर ने रट लिया है, fatal: The current branch has no upstream branch, इसलिए मौजूद है ताकि git सीधी बात करने की इजाज़त मांग सके। यह सेटिंग वह इजाज़त हमेशा के लिए दे देती है। नई ब्रांच पर पहला पुश बस काम कर जाता है। (यही वह लाइन है जिसने मेरे टीममेट को बीच वाक्य में रोक दिया था।)

ग़लती से मर्ज कमिट बनने से रोको

git config --global pull.rebase true

डिफ़ॉल्ट git pull एक fetch + merge है, यही वजह है कि "Merge branch 'main' of github.com..." जैसे कमिट आपकी हिस्ट्री पर वॉलपेपर की तरह चिपक जाते हैं। इसके साथ, pull आपके लोकल कमिट को जो आया है उसके ऊपर दोबारा चलाता है। लीनियर हिस्ट्री, कोई नॉइज़ नहीं।

नई रिपॉज़ को main पर शुरू करो

git config --global init.defaultBranch main

वरना हर git init master पर शुरू होता है और आप बाद में इसका नाम बदलते हो। एक लाइन, फिर कभी इसके बारे में सोचना नहीं पड़ता।

मरी हुई ब्रांच जमा करना बंद करो

git config --global fetch.prune true

जब रिमोट पर कोई ब्रांच डिलीट होती है (ज़्यादातर मर्ज हो चुकी PRs), आपकी लोकल कॉपी origin/that-branch की हमेशा बनी रहती है। यह हर fetch पर पुरानी रेफ़रेंस को ऑटो-डिलीट कर देता है। आपकी ब्रांच लिस्ट सच बनी रहती है।

हर रिपॉज़ से हमेशा के लिए .DS_Store बैन करो

git config --global core.excludesfile ~/.gitignore_global
echo ".DS_Store" > ~/.gitignore_global

एक ग्लोबल इग्नोर फ़ाइल हर रिपॉज़ के अपने .gitignore के ऊपर लागू होती है। macOS का कचरा, एडिटर की स्वैप फ़ाइलें, एक बार में निपटा दो, पूरी मशीन पर, हर प्रोजेक्ट में अलग से नहीं।

कॉन्फ़्लिक्ट रिज़ॉल्वर की तिकड़ी

git config --global merge.conflictstyle zdiff3
git config --global rerere.enabled true
git config --global rebase.autostash true

तीन सेटिंग्स जो मिलकर कॉन्फ़्लिक्ट रिज़ॉल्यूशन को बदल देती हैं:

zdiff3 कॉन्फ़्लिक्ट मार्कर्स में एक तीसरा सेक्शन जोड़ता है, वह ओरिजिनल टेक्स्ट जहां से दोनों तरफ़ शुरू हुआ था। स्टैंडर्ड मार्कर आपको "यह वाला" और "वह वाला" दिखाते हैं और आपको इरादा अंदाज़ा लगाने पर छोड़ देते हैं। कॉमन एन्सेस्टर देखना अंदाज़ा लगाने को पढ़ने में बदल देता है।

zdiff3 कॉन्फ़्लिक्ट मार्कर्स दोनों तरफ़ के साथ ओरिजिनल कॉमन एन्सेस्टर भी दिखाते हैं

rerere ("reuse recorded resolution") ग्यारहों में सबसे छिपा हुआ हिट है। Git रिकॉर्ड करता है कि आपने हर कॉन्फ़्लिक्ट कैसे सुलझाया, और जब वही कॉन्फ़्लिक्ट फिर आए (rebase को कॉन्फ़्लिक्ट दोहराना पसंद है), यह आपका रिज़ॉल्यूशन ऑटोमैटिकली दोहरा देता है। पांचवां वैसा ही कॉन्फ़्लिक्ट अपने आप सुलझ जाता है।

autostash "cannot rebase: you have unstaged changes" वाला नाटक ख़त्म कर देता है। Git आपका काम स्टैश करता है, rebase करता है, और वापस रीस्टोर कर देता है। जो आप कर रहे थे वह बचा रहता है।

क्वालिटी-ऑफ़-लाइफ़, दो लाइनें

git config --global diff.algorithm histogram
git config --global branch.sort -committerdate

Histogram डिफ़ॉल्ट Myers एल्गोरिदम से काफ़ी साफ़ डिफ़ लाता है, उन बिखरे हुए ब्लॉक्स में से कम जहां git बेमतलब लाइनों को जोड़ देता है। और हाल की एक्टिविटी के हिसाब से ब्रांच सॉर्ट करने का मतलब है कि git branch सबसे पहले वह दिखाता है जिस पर आप असल में काम कर रहे हैं, अल्फ़ाबेटिकल पुरातत्व नहीं।

⌨️ दूसरा हिस्सा: एलियस

सेटिंग्स git का बर्ताव बदलती हैं। एलियस आपकी रफ़्तार बदलते हैं। मैं चुनी हुई बीस रखता हूं, इस हिसाब से बांटी हुई कि वे क्या बचाते हैं।

बीस git एलियस, चार ग्रुप्स में बंटे हुए: डेली ड्राइवर्स, साफ़ नज़र, बिना डर के अनडू, और प्रो मूव्स

डेली ड्राइवर्स

st     = status -sb
cm     = commit -m
sw     = switch
co     = checkout
amend  = commit --amend --no-edit

status -sb एक नोट लायक है: यह दो-लाइन का status है। ब्रांच स्टेट प्लस बदली हुई फ़ाइलें, बिना उस सलाह के पैराग्राफ़ों के जो आपने सालों पहले पढ़ना बंद कर दिया।

साफ़ नज़र

lg     = log --oneline --graph --decorate -20
last   = log -1 HEAD --stat
d      = diff
ds     = diff --staged
whoami = !echo "$(git config user.name) <$(git config user.email)>"

git lg मेरा "मैं कहां हूं" है, बीस कमिट, ग्राफ़ के रूप में खींचे हुए। और git whoami पहले हिस्से का लूप बंद करता है: किसी भी रिपॉज़ में इसे चलाओ और यह ठीक-ठीक बताता है कि अगले कमिट पर कौन-सी आइडेंटिटी दस्तख़त करेगी। company/ में यह मेरा वर्क ईमेल दिखाता है; बाकी जगह, पर्सनल। भरोसा, एक कमांड में वेरिफ़ाई।

बिना डर के अनडू

unstage = restore --staged
undo    = reset --soft HEAD~1
wip     = !git add -A && git commit -m "wip: checkpoint"

undo बिना कुछ बर्बाद किए कमिट वापस लेता है, बदलाव स्टेजिंग में वापस आ जाते हैं। wip किसी जोखिम भरी सर्जरी से पहले सब कुछ स्नैपशॉट कर लेता है। ज़्यादातर git की घबराहट यह न जानने से आती है कि वापस जाने का सुरक्षित रास्ता क्या है; यही वह सुरक्षित रास्ता हैं।

प्रो मूव्स

pf      = push --force-with-lease
fixup   = commit --fixup
ri      = rebase -i --autosquash
cleanup = !git branch --merged | grep -vE "^\*|main|master" | xargs git branch -d

pf सबसे ज़रूरी है: --force-with-lease सिर्फ़ तब फ़ोर्स-पुश करता है जब रिमोट वहीं हो जहां आपने आख़िरी बार देखा था, मतलब यह किसी टीममेट के बीच में आए काम को ओवरराइट करने से भौतिक रूप से इनकार कर देता है। कोई भी सिचुएशन ऐसी नहीं जहां कच्चा --force बेहतर विकल्प हो। इसे एलियस करने का मतलब है मेरी उंगलियां कभी ख़तरनाक वर्ज़न नहीं टाइप करतीं।

fixup + ri जोड़ी साफ़-हिस्ट्री वर्कफ़्लो है: एक फिक्स कमिट करो जो किसी पुराने कमिट को टारगेट करता है, फिर एक इंटरैक्टिव rebase सब कुछ ऑटोमैटिकली अपनी जगह फ़ोल्ड कर देता है।

🎯 वह हिस्सा जो इसे परमानेंट बनाता है

कॉन्फ़िग के बारे में यही बात है: इसे बनाना आसान है। इसे बनाए रखना असली समस्या है। एक कॉन्फ़िग जो सिर्फ़ आपकी मौजूदा मशीन पर रहता है, वह कॉन्फ़िग है जिसे आप अपनी अगली मशीन पर याददाश्त से दोबारा बनाएंगे।

मेरी ~/.gitconfig कोई अलग-थलग फ़ाइल नहीं है, यह एक dotfiles रिपॉज़ में एक सिमलिंक है जो हर बदलाव को होते ही ऑटो-कमिट और पुश कर देती है। जब मैंने हाल ही में एक नया एलियस जोड़ा, एक बैकग्राउंड एजेंट ने इसे GitHub पर कमिट कर दिया था इससे पहले कि मैं टेस्ट करना खत्म करता।

(वह सिस्टम, सिमलिंक और एक launchd एजेंट, बिना cron, बिना थर्ड-पार्टी टूल, अपनी अलग कहानी है, जो मैंने अलग से लिखी है।)

नतीजा: यह पूरा सेटअप, आइडेंटिटी रूटिंग और सभी बीस एलियस समेत, एक install.sh से किसी भी मशीन पर पहुंच जाता है। एक बार कॉन्फ़िगर करो, हमेशा के लिए रखो।

📋 पूरी चीज़, कॉपी-पेस्ट के लिए तैयार

# identity (edit these!)
git config --global user.name "Your Name"
git config --global user.email "you@personal.com"
 
# behavior
git config --global init.defaultBranch main
git config --global push.autoSetupRemote true
git config --global pull.rebase true
git config --global fetch.prune true
git config --global core.excludesfile ~/.gitignore_global
echo ".DS_Store" > ~/.gitignore_global
git config --global merge.conflictstyle zdiff3
git config --global rerere.enabled true
git config --global rebase.autostash true
git config --global diff.algorithm histogram
git config --global branch.sort -committerdate
 
# aliases
git config --global alias.st "status -sb"
git config --global alias.cm "commit -m"
git config --global alias.sw "switch"
git config --global alias.co "checkout"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.lg "log --oneline --graph --decorate -20"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.d "diff"
git config --global alias.ds "diff --staged"
git config --global alias.unstage "restore --staged"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.wip '!git add -A && git commit -m "wip: checkpoint"'
git config --global alias.pf "push --force-with-lease"
git config --global alias.fixup "commit --fixup"
git config --global alias.ri "rebase -i --autosquash"
git config --global alias.cleanup '!git branch --merged | grep -vE "^\*|main|master" | xargs git branch -d'
git config --global alias.root "rev-parse --show-toplevel"
git config --global alias.aliases "config --get-regexp ^alias"
git config --global alias.whoami '!echo "$(git config user.name) <$(git config user.email)>"'

साथ ही आइडेंटिटी रूटिंग, अगर आप वर्क कोड को एक अलग डायरेक्टरी में रखते हो:

git config --global includeIf."gitdir:~/Developer/company/".path ~/.gitconfig-work
printf '[user]\n    email = you@work.com\n' > ~/.gitconfig-work

सबक

इनमें से कोई भी सेटिंग अकेले प्रभावशाली नहीं है। यही तो बात है।

Git के डिफ़ॉल्ट्स इस बात पर ऑप्टिमाइज़ हैं कि किसी को कभी न चौंकाया जाए, जिसका मतलब है कि वे सबको टोकते हैं। ऊपर की हर लाइन एक बार-बार आने वाली रुकावट को ख़ामोशी में बदल देती है, और ख़ामोशी बढ़ती है। हर उस रिपॉज़ में कुछ सेकंड बचाना और एक ग़लत-ईमेल कमिट टालना गुणा करो जो आप कभी छुओगे, और यह आधे घंटे की कॉन्फ़िगरेशन टूलिंग पर बिताया गया आपका सबसे हाई-लीवरेज समय है।

मेरे टीममेट ने उसी दोपहर push.autoSetupRemote सेट कर लिया था जिस दिन उसने इसे देखा। वह workaround जो वह सालों से टाइप कर रहा था, एक लाइन से ग़ायब हो गया, बस किसी को यह टैक्स न चुकाते देखने की ज़रूरत थी यह जानने के लिए कि यह वैकल्पिक था।

इस आर्टिकल को लिखित रूप में वही पल समझो। cat ~/.gitconfig चलाओ और देखो कि असल में उसमें क्या है।

डिफ़ॉल्ट्स कम्पैटिबिलिटी के लिए हैं। कॉन्फ़िगरेशन आपके लिए है।

आपके gitconfig में क्या है?

मैं हमेशा अगले एक-लाइन फिक्स की तलाश में रहता हूं। अगर आपके पास कोई सेटिंग या एलियस है जिसने अपनी जगह कमाई है, वैसे ही मुझे मेरे आधे मिले।

ब्लॉग से और

सभी देखें