4 पॉइंट द्वारा GN⁺ 2025-01-18 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Git में अगर गलती वाली स्थिति का नाम न पता हो, तो समाधान खोजना मुश्किल होता है; इसलिए यह सामग्री आम रिकवरी scenarios के हिसाब से commands तुरंत ढूंढकर इस्तेमाल करने के लिए व्यवस्थित की गई है
  • अगर repository को बुरी तरह बिगाड़ दिया हो या delete/merge की गलती वापस करनी हो, तो git reflog से काम का इतिहास ढूंढकर git reset HEAD@{index} से पिछली स्थिति में लौट सकते हैं
  • आखिरी commit में छोटी correction या message बदलना हो तो git commit --amend से जल्दी कर सकते हैं, लेकिन जो commit पहले ही public/shared branch पर push हो चुका हो, उस पर इसका इस्तेमाल नहीं करना चाहिए
  • अगर गलत branch में commit कर दिया हो, तो reset, stash, checkout, stash pop flow या cherry-pick से उसे move कर सकते हैं, लेकिन push हुआ है या नहीं, इसके आधार पर सुरक्षित तरीका बदलता है
  • remote repository की स्थिति में forcefully restore करने वाले reset --hard और git clean -d --force untracked files तक हटा सकते हैं, इसलिए चलाने से पहले जांच जरूरी है

Git की गलतियां recover करना मुश्किल क्यों है

  • Git में गलती करना आसान है, और problem ठीक करने के लिए अक्सर उस concept का नाम पहले से जानना पड़ता है, तभी आप उसे search कर पाते हैं
  • यह सामग्री Git में अक्सर आने वाली खराब स्थितियों को सरल English और command examples के साथ व्यवस्थित करती है
  • यह complete reference नहीं है, और वही काम करने के दूसरे तरीके भी हो सकते हैं

repository को पुरानी स्थिति में वापस लाना

  • जब repository बहुत बिगड़ गई हो या delete की गई चीजें वापस लानी हों, तो git reflog से काम का history देखें
git reflog


# सभी branches में Git operations की list देख सकते हैं


# हर item में HEAD@{index} format का index होता है
git reset HEAD@{index}
  • reflog इन situations में इस्तेमाल किया जा सकता है
    • गलती से delete की गई चीजें recover करना
    • repository बिगाड़ देने वाले attempt को हटाना
    • खराब merge के बाद recover करना
    • उस point पर वापस जाना जहां चीजें सच में काम कर रही थीं

आखिरी commit को ठीक करने का तरीका

  • अगर आखिरी commit के तुरंत बाद छोटी correction add करनी हो, तो git commit --amend --no-edit का इस्तेमाल करें
# बदलावों के बाद
git add . # या अलग-अलग files add करें
git commit --amend --no-edit
  • यह command नए changes को आखिरी commit में शामिल कर देती है
  • यही काम नया commit बनाकर फिर rebase -i से merge करके भी किया जा सकता है, लेकिन amend काफी तेज है
  • public/shared branch पर पहले से push हो चुके commit पर amend का इस्तेमाल नहीं करना चाहिए
  • सिर्फ आखिरी commit message बदलना हो तो यह command इस्तेमाल करें
git commit --amend


# निर्देशों के अनुसार commit message बदलें

गलत branch में commit हो जाए तो

  • अगर गलती से master में commit कर दिया, लेकिन वह नई branch में होना चाहिए था, तो current state से नई branch बनाएं और master का आखिरी commit हटाएं
git branch some-new-branch-name
git reset HEAD~ --hard
git checkout some-new-branch-name
  • यह तरीका उन commits के लिए सही नहीं है जिन्हें पहले ही public/shared branch पर push कर दिया गया हो
  • अगर आपने पहले कुछ और attempts किए हैं, तो HEAD~ के बजाय HEAD@{number-of-commits-back} जैसे form की जरूरत पड़ सकती है
  • अगर पूरी तरह गलत branch में commit कर दिया हो, तो reset --soft, stash, checkout, stash pop flow से उसे move किया जा सकता है
git reset HEAD~ --soft
git stash
git checkout name-of-the-correct-branch
git stash pop
git add . # या अलग-अलग files add करें
git commit -m "your message here"
  • इसी स्थिति में cherry-pick इस्तेमाल करने का तरीका भी है
git checkout name-of-the-correct-branch
git cherry-pick master
git checkout master
git reset HEAD~ --hard

changes और पुराने commits को वापस करना

  • अगर आपने file बदली है लेकिन git diff खाली है, तो हो सकता है आपने उसे पहले ही staging में डाल दिया हो, इसलिए --staged flag चाहिए
git diff --staged
  • कुछ commits पहले के change को वापस करना हो, तो git log से hash ढूंढें और git revert चलाएं
git log
git revert [saved hash]
  • git revert उस commit को undo करने वाला नया commit बनाता है
  • पूरे commit के बजाय सिर्फ किसी खास file को वापस करना हो, तो file का पुराना version index में डालकर commit करने वाला flow इस्तेमाल करें
git log
git checkout [saved hash] -- path/to/file
git commit -m "Wow, you don't have to copy-paste to undo"

remote repository की स्थिति में forcefully restore करना

  • repository delete करके फिर से clone करने के बजाय, remote repository की state से match कराने वाली Git commands इस्तेमाल की जा सकती हैं
git fetch origin
git checkout master
git reset --hard origin/master
git clean -d --force
  • git reset --hard origin/master branch को remote master की state से match कर देता है
  • git clean -d --force untracked files और directories delete कर देता है
  • हर खराब branch के लिए checkout, reset, clean दोहराना होगा
  • ये operations destructive और unrecoverable हैं, इसलिए चलाने से पहले सावधानी जरूरी है

scope और योगदान

  • यह सामग्री complete Git reference नहीं, बल्कि trial and error से मिले practical recovery procedures का collection है
  • translation जोड़ने में मदद करना चाहें, तो GitHub पर PR submit कर सकते हैं

1 टिप्पणियां

 
GN⁺ 2025-01-18
Hacker News की रायें
  • मैं कुछ चीज़ें बदलना चाहूंगा: हमेशा git checkout की जगह git switch इस्तेमाल करूंगा, और reset --hard से जितना हो सके बचूंगा
    उदाहरण के लिए, “अगर किसी ऐसे commit को गलती से master पर कर दिया जो नई branch में होना चाहिए था”, तो इसे git branch some-new-branch-name, git switch -d HEAD~, git switch -C master, git switch some-new-branch-name के क्रम में संभाला जा सकता है
    “गलत branch पर commit कर दिया” वाली स्थिति में भी सही branch पर git switch करने के बाद git cherry-pick master, git switch -d master~, git switch -C master से निपटूंगा
    “सब छोड़कर remote state पर वापस लौटना” भी git fetch origin, git restore -WS ., git clean -d --force, git switch -d origin/master, git switch -C master की तरह बनाऊंगा

    • Git का internal model blobs, commit tree, और commit pointers के रूप में खूबसूरत है, लेकिन command-line interface से उसका अंतर बहुत बड़ा है
      Git model अच्छी तरह समझने पर भी ये recipes सहज नहीं लगतीं, और हर command के अजीब व्यवहार तक जानने पड़ते हैं
      जैसे git switch -c some-new-branch-name पहले से है, लेकिन केवल branch को किसी दूसरे commit पर ले जाने के लिए git move-branch master HEAD~ जैसी command ज़्यादा intuitive लगेगी
    • मैं git checkout की जगह git switch और git restore इस्तेमाल करने की दिशा का विरोध नहीं कर रहा, लेकिन ये commands Git v2.23 में आई थीं और वह release करीब 5 साल पहले की है
      help page में अब भी THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. की warning मौजूद है
      बेशक यह warning command बनने के लगभग शुरुआती समय से ही थी, और 5 साल बाद अब शायद इसे experimental न कहने का समय आ गया है
      फिर भी git checkout ज़्यादा backward compatible है, और कहा जा सकता है कि यह उस समय के Git usage को दिखाता है जब यह website मूल रूप से बनाई गई थी
      https://github.com/git/git/blob/757161efcca150a9a96b312d9e78...
      https://github.com/git/git/releases/tag/v2.23.0
      https://github.com/git/git/commit/4e43b7ff1ea4b6f16b93a432b6...
    • changes को staging area में डालते समय default रूप से git add . सिखाना अच्छा नहीं है
      specific files को साफ़-साफ़ जोड़ना बाद में “अरे, गड़बड़ हो गई” कहने की गुंजाइश कम करता है
    • मैं जानना चाहता हूं कि इस तरीके की सलाह देने का आधार क्या है
      यह समझना चाहता हूं कि switch, checkout से बेहतर क्यों है और reset --hard क्यों नहीं इस्तेमाल करना चाहिए
    • reset --hard से बचो” का क्या मतलब है, समझ नहीं आ रहा
      सच में जानना चाहता हूं कि यह पर्याप्त क्यों नहीं है, और मैं इसे alias git-restore-file='git restore --source=HEAD --' के साथ काफ़ी बार इस्तेमाल करता हूं, और यह ठीक काम करता लगता है
  • Git सीखते समय basic path के तौर पर GUI client recommend करना शुरू करना चाहिए
    इससे ऐसी समस्याओं का एक-तिहाई हिस्सा सुलझ जाएगा, और एक और एक-तिहाई तो पैदा ही नहीं होगा
    बाद में अगर command line तेज़ लगे तो तब इस्तेमाल कर सकते हैं; पहले लोगों को visually देखना चाहिए कि वे tree के साथ कैसे interact करते हैं
    निजी तौर पर मुझे fork.dev पसंद है, लेकिन आजकल clients ज़्यादातर एक जैसे हैं

    • मैं सहमत हूं कि कई मामलों में GUI, Git को बेहतर user experience देता है
      Magit इस्तेमाल करने पर “cherry-pick रोकना” जैसी action interface में discoverable होती है, और दूसरे “X रोकना” operations जैसा ही shortcut इस्तेमाल करती है
      अगर मुझे सिर्फ़ Git command line इस्तेमाल करनी पड़ती, तो शायद समझ ही नहीं आता कि कहां से शुरू करूं
      interactive rebase के दौरान मैंने एक ऐसा commit भी delete कर दिया था जिसे नहीं हटाना चाहिए था, लेकिन हर rebase शुरू होने के समय reflog में accessible snapshot बन जाता है, इसलिए गलत rebase को वापस करना safe होता है
      Magit का reflog UI, log UI जैसा ही है, इसलिए पहली बार देखने पर भी मैं भटका नहीं; लेकिन Git CLI होता तो शायद समझ नहीं पाता कि क्या हो रहा है
    • Git-compatible alternative के रूप में jj recommend करना शुरू किया है
      jj को बिना arguments चलाने पर commit tree का relevant हिस्सा और current position दिखती है, यह बात अच्छी है
      आप जिस commit पर अभी काम कर रहे हैं, linked branch और history, repository में दूसरी active branches, और हर commit का message व changes की स्थिति एक नज़र में दिख जाती है, इसलिए direction फिर से पकड़ने में यह शानदार है
    • Git beginners को मैं हमेशा सलाह देता हूं कि अपने लिए सही UI खोजें और command line से ज़्यादा उसी का इस्तेमाल करें
      लेकिन लगभग कोई नहीं सुनता, और आखिर में CLI पर जूझते हुए branch बिगाड़ लेते हैं, main से पीछे रह जाते हैं और rebase से डरने लगते हैं
      UI में कई चीज़ें drag-and-drop या मिलते-जुलते तरीके से हल हो सकती हैं, लेकिन यह कुछ-कुछ आत्म-यातना जैसा लगता है
    • अगर tree के साथ interact करने का तरीका visually देखना है, तो एक interactive tutorial है जिसने मेरे साथियों की मदद की: https://learngitbranching.js.org/
    • पहले version control GUI frontend इस्तेमाल करने के अनुभव से, जब सब ठीक चल रहा हो तो वह ठीक है, लेकिन एक बार चीज़ें उलझ जाएं और उन्हें साफ़ करना पड़े तो किसी के लिए मदद करना मुश्किल हो जाता था
      interface भले ही भयानक हो, टीम के बाकी लोग जो interface इस्तेमाल करते हैं वही इस्तेमाल करना संवाद के लिए आसान था, और online troubleshooting material भी आम तौर पर “सामान्य तरीका” मानकर चलता है, इसलिए उसका उपयोग करना बेहतर रहता था
  • यह सोचकर काफ़ी अजीब लगता है कि अप्रैल 2025 में Git को 20 साल हो जाएंगे
    मैं उस समय इस फील्ड में था, और याद है कि SVN या CVS की जगह लेने के लिए git, darcs, bazaar में से क्या सीखना चाहिए, इस पर सोच रहा था
    पता नहीं Mercurial भी आज़माया था या नहीं
    सोचता हूं कि क्या “GitHub effect” ने version control system के क्षेत्र में नए entrants की ज़रूरत को व्यावहारिक रूप से खत्म कर दिया
    शायद किसी बिंदु पर yak shaving पर्याप्त रूप से खत्म हो चुकी थी

    • GitHub effect, सभी network effects की तरह, सचमुच मौजूद है, लेकिन इसका मतलब यह नहीं कि सुधार असंभव है
      मैं पूरी तरह jj पर शिफ्ट हो चुका हूं, और Git compatibility होने की वजह से मुझे दूसरों के साथ बदलने का इंतज़ार नहीं करना पड़ता
      GitHub के कई पहलुओं से मैं धीरे-धीरे और ज़्यादा निराश हो रहा हूं, इसलिए उम्मीद है कि किसी दिन सब लोग उससे भी आगे बढ़ेंगे, लेकिन उस दिशा में आगे का रास्ता इतना सीधा नहीं दिखता
    • SVN हमेशा अच्छे से काम करता था
      SVN intuitive है और 99% मामलों में इतना अच्छा चलता है कि लोगों को अलग से “सिखाने” की ज़रूरत नहीं पड़ती
      काश हम सब 1337 hacker बनने का नाटक छोड़ दें और मान लें कि Git ज़्यादातर लोगों के लिए ज़रूरत से ज़्यादा भारी tool है
    • कोई भी सुधार कम-से-कम Git compatible होना चाहिए, जैसे jj है
  • मुझे लगता है कि Git क्या करता है, इसका मेरा mental model काफ़ी अच्छा है, लेकिन command ज़रा भी complex होते ही arguments याद नहीं रहते
    commands न तो discoverable हैं और न ही याद रखने में आसान
    पता नहीं text UI खराब है, या tree को manipulate करने जैसी चीज़ को text में समझाना ही मुश्किल है

  • इस thread में hg और Mercurial के search results देखकर अच्छा लगा
    अभी भी विश्वास नहीं होता कि Mercurial distributed version control की लड़ाई हार गया, और मेरे हिसाब से यह बेहतर tool है

    • आज के हिसाब से भी Mercurial बिना शक बेहतर tool है
      usable है, stable है, production में परखा हुआ है, और actively supported है
      यह “जो बदलाव देखना चाहते हो, वही बनो” जैसा है, तो बस इस्तेमाल करो
      इसके हार जाने जैसी भाषा counterproductive है, और ऐसे शब्दों से आने वाला implicit discouragement Mercurial की adoption rate को कम बनाए रखता है
      hosting कम-से-कम Sourcehut और heptapod.host पर उपलब्ध है
      मैं एक निजी Heptapod instance भी चला रहा हूं, जो Gitlab fork में Mercurial का direct support जोड़े हुए है, और बस ठीक से काम करता है
    • दिलचस्प है, लेकिन सोच रहा हूं कि क्या इसका GitHub link है
    • Mercurial धीमा tool है
    • अगर Mercurial hosting चाहिए तो यह hosting इस्तेमाल कर सकते हैं: https://hg.reactionary.software/
  • Git कई मायनों में intuition के खिलाफ जाता है, इसलिए यह उन technologies में से एक रहा जो आखिर तक दिमाग में ठीक से नहीं बैठी
    अगर आपने इसे लंबे समय से इस्तेमाल नहीं किया है, तो लगभग हर काम के लिए Google खोजना या man page देखना पड़ सकता है

    • SVN से शुरू करके Git पर आया, तो फर्क सीखना पड़ा, लेकिन कई मायनों में यह ज़्यादा आसान लगा
      खासकर जब बड़े codebase को SVN में कई branches के साथ manage करने और फिर merge करने की दहशत झेल चुके हों, तो दिखता है कि Git उस हिस्से में बेहिसाब बेहतर है
      शुरुआत से Git में आने वाले लोगों के लिए learning curve कहीं ज़्यादा बड़ा हो सकता है, लेकिन कभी-कभी अब भी समझना मुश्किल होता है कि लोग कहां अटकते हैं
    • कल history से एक file delete करने की कोशिश की
      built-in तरीका filter-branch इस्तेमाल करने पर लंबी देरी के साथ warning आती है कि Control+C दबाएं और filter-repo नाम का third-party Python script download करें
  • गर्व की बात नहीं है, लेकिन मेरा सबसे ज़्यादा इस्तेमाल होने वाला “सब गड़बड़ हो गया” Git operation है local repository delete करना, फिर से clone करना, और changes दोबारा apply करना
    95% मामलों में यह बहुत अच्छे से काम करता है, बाकी में DevOps वाले से मदद मांगता हूं

    • Git को लगभग 15 साल इस्तेमाल किया है, और ऐसे program/product भी दो बार बनाए हैं जो अंदरूनी तौर पर Git इस्तेमाल करके खास नतीजे देते हैं, फिर भी Git में थोड़ा risky काम करने से पहले मैं कभी-कभी cp -R .git ../git-backup जैसा कुछ कर लेता हूं
      क्योंकि अगर बहुत बुरी तरह बिगाड़ दूं, तो पूरी .git directory को पुराने copy से बदल सकता हूं
      किसी खास operation या operations के group को सही तरीके से revert करने का तरीका खोजने से यह कहीं तेज़ है
    • आप अकेले नहीं हैं: https://xkcd.com/1597/
  • Git के बारे में जो बात मैं चाहता हूं कि लोग ज़रूर आत्मसात करें, वह यह है कि Git एक append-only data store है
    काम को repository में डालना है तो commit करें, और एक बार काम अंदर चला गया तो Git command से उसे हटाया नहीं जा सकता
    reflog भी इसी principle पर काम करता है
    आप जो भी करें, पुराने branch state पर लौटकर data store से काम restore कर सकते हैं
    लेकिन अगर commit नहीं किया, तो Git आपकी मदद नहीं कर सकता, इसलिए बस commit करें
    हमेशा commit करें, और अगर यह बहुत भारी लगता है या बार-बार भूल जाते हैं, तो tooling ठीक करनी चाहिए
    अगर आप पूरे दिन code लिखते हैं, तो आम तौर पर कम-से-कम हर घंटे एक बार commit करना चाहिए

  • छोटी-सी बात है, लेकिन git reflog देखते ही मुझे यह re-flog जैसा दिखता है
    शायद इसलिए यह command ठीक से याद नहीं रहती, और अवचेतन में इसे “reference log” की तरह सोच नहीं पाता
    इसके बजाय ऐसा लगता है जैसे Git से किसी चीज़ को फिर से सस्ते में बेचने को कह रहा हूं

  • मैं Git यूज़र नहीं हूँ, लेकिन ऐसी चीज़ें देखकर यह सोच और मजबूत होती है कि git commit अपने आप में अर्थहीन है; असल में मायने सिर्फ उस समय का है जब commit push या merge होता है
    यह टेक्स्ट फ़ाइल सेव करने जैसा है
    हर बार फ़ाइल सेव करते समय कोई छोटा message नहीं लिखते, इसलिए बस आगे बढ़ जाना चाहिए

    • अगर यह बदलाव कठिन debugging यात्रा के अंत में आया है और संभावना है कि दूसरे लोग बाद में इसे फिर reference करेंगे, तो message लिखता हूँ
      छोटा नहीं; बदलाव जितना छोटा हो, कभी-कभी explanation उतना ही लंबा हो जाता है
      बड़े प्रभाव वाले 2–3 lines के बदलाव पर मैंने 2–3 paragraphs भी लिखे हैं
    • local commit और remote commit का मकसद अलग है, यह बहुत साफ़ लगता है
      local commit उस point पर checkpoint बनाने का तरीका है जहाँ सब कुछ compile होकर काम करता है
      ताकि बदलावों को stash किया जा सके या कुछ बिगड़ जाए तो काम कर रही state पर वापस लौटा जा सके
      push करने से पहले reset करके उन्हें उचित commits में बाँट दें तो remote history साफ़ रहती है और wip dummy नहीं बनती
      या PR को squash merge करके दोनों तरफ़ के फ़ायदे भी लिए जा सकते हैं
    • commit बहुत महत्वपूर्ण है, क्योंकि यह Git को internally फ़ाइलों की copy बनाने की क्रिया करवाता है
      हालांकि more fixes जैसे बेअर्थ message डालने की ज़रूरत नहीं है
      आमतौर पर (WIP) फीचर-नाम जैसा initial commit बनाता हूँ, फिर संतुष्ट होने तक बार-बार amend commit करता हूँ और अंत में message से (WIP) हटा देता हूँ
    • तुलना टेक्स्ट फ़ाइल सेव करने से की जाती है, लेकिन बहुत से लोग हर रात सोने से पहले अपने दिन पर एक छोटा note भी लिखते हैं
      मुझे Git revision log भी ऐसी ही डायरी जैसा लगता है
      यह अलग TODO document से ज़्यादा व्यवस्थित होता है और पहले किए गए काम को पढ़ने में आसान तरीके से समझाने के लिए प्रेरित करता है
      कितना वापस लौटना है यह तय करते समय उस समय commit करते हुए क्या सोच रहे थे, यह जानना उपयोगी हो सकता है; और अगर approach गलत थी, तो postmortem analysis में भी मदद मिलती है
      merge या push न हुआ काम अगर लक्ष्य वाले अलग-अलग changes के रूप में व्यवस्थित हो, तो उनमें से कुछ अच्छे और कुछ खराब होने पर सिर्फ अच्छे हिस्से बचाए रखना कहीं ज़्यादा आसान हो जाता है
    • push से पहले तक सब कुछ local है, इसलिए जैसा चाहें वैसा कर सकते हैं
      फिर भी technically commit अर्थहीन नहीं है
      commit न हो तो push या merge करने के लिए कोई target भी नहीं होता
      non-technical रूप से भी, किसी चीज़ को क्यों बदला जा रहा है, इसे plain text में दर्ज करना बहुत उपयोगी है
      अगर ऐसी explanation बहुत बार लिखनी पड़ रही है, तो “change” की unit को और छोटा करना चाहिए, या साथ-साथ छुई जा रही चीज़ों को और चुनिंदा करना चाहिए
      अगर Git नहीं इस्तेमाल करते, तो version control और change management किससे करते हैं, यह जानने की उत्सुकता है