इंटरैक्टिव रीबेस वही औजार है जिसे मैं तब खोलता हूं जब फीचर ब्रांच प्रयोगशाला की कॉपी जैसी लगे: पांच अधूरे कमिट, टाइपो पर टाइपो का फिक्स, और ऐसा संदेश जिसे मैं कभी मर्ज न करूं। सही जगह पर यह शोर को छोटी कहानी बना देता है जिसे रिव्यूअर पढ़ सके। गलत ब्रांच पर यह वह इतिहास बदल देता है जिस पर और लोग पहले से काम कर चुके हैं, और टीम चैट जल उठती है।

यह वही प्लेबुक है जो मैं असली टीमों में चलाता हूं: कमांड, टोडो के जरूरी क्रियापद, कब रुकें, और गड़बड़ होने पर कैसे निकलें।


इंटरैक्टिव रीबेस असल में क्या करता है

सामान्य रीबेस आपके कमिट किसी और आधार (अक्सर main) के ऊपर फिर चलाता है। इंटरैक्टिव भी वही करता है, पर पहले एक टोडो सूची खोलता है ताकि हर कमिट दोबारा चलाने से पहले बदला जा सके।

# मौजूदा ब्रांच के आखिरी ४ कमिट फिर लिखना
git rebase -i HEAD~4

# अपडेटेड main पर ब्रांच फिर चलाना, रास्ते में संपादन के साथ
git fetch origin
git rebase -i origin/main

गिट संपादक में ऐसी पंक्तियां खोलता है (सबसे पुराना ऊपर):

pick a1b2c3d add login form
pick d4e5f6a fix typo in label
pick 7890abc wip validation
pick bcdef01 tests for login

हर पंक्ति की शुरुआत का क्रियापद बदलो (और चाहो तो क्रम बदलो या पंक्ति हटाओ)। सेव कर बंद करो। गिट नए प्लान के अनुसार कमिट फिर चलाता है।

दो नियम जो ज्यादातर हादसे रोकते हैं:

१. केवल वे कमिट फिर लिखो जो साझा रिमोट ब्रांच पर न हों जहां से दूसरे पुल करते हैं (या जो सिर्फ तुम्हारी हों)।
२. जोखिम वाले रीबेस से पहले रिकवरी बिंदु नोट करो: git rev-parse HEAD, या ORIG_HEAD और reflog पर भरोसा (नीचे)।


टोडो के वे क्रियापद जो सच में काम आते हैं

पहले दिन सब याद रखने की जरूरत नहीं। ये छह लगभग सारा टीम काम ढक लेते हैं।

क्रियापद असर कब इस्तेमाल
pick कमिट जस का तस डिफ़ॉल्ट; मत छेड़ो
reword डिफ वही, संदेश बदलो टाइपो, अधूरा संदेश, टिकट आईडी गायब
edit रुककर अमेंड या कमिट तोड़ना फाइल छूट गई; एक की जगह दो कमिट
squash पिछले में मिलाओ; मिला हुआ संदेश संपादित जुड़े डब्ल्यूआईपी जो एक कहानी बनें
fixup पिछले में मिलाओ; यह संदेश फेंको छोटे मरम्मत: लिंट, इंपोर्ट, टेस्ट
drop (या पंक्ति मिटाओ) कमिट हटाओ प्रयोग जो कभी शिप न होना चाहिए

exec भी है: हर कमिट के बाद कमांड चलाने को (गंदी श्रृंखला साफ करते समय npm test के लिए)। रोज के पीआर साफ-सफाई में कम चलता है।

स्क्वैश बनाम फिक्सअप

दोनों एक कमिट को ऊपर वाले में समेटते हैं। फर्क संदेश में है।

  • squash: मिला संदेश लिखने के लिए संपादक खुलेगा। जब बच्चे कमिट में असली इरादा हो जिसे अंतिम संदेश में रखना हो।
  • fixup: बच्चे का संदेश फेंक दिया जाता है। जब वह सिर्फ मरम्मत का शोर हो (टेस्ट ठीक करो, भूल सुधार)।

उदाहरण टोडो:

pick a1b2c3d add rate limiter middleware
fixup d4e5f6a fix off-by-one in window
fixup 7890abc missing unit test
reword bcdef01 document env vars

नतीजा: दो कमिट। पहले में तीनों डिफ और मूल मिडलवेयर संदेश (बाद में रीवर्ड न किया हो तो)। दूसरे में अपना ट्री, साफ संदेश।

जब काम करते-करते ही फिक्सअप चाहिए हो:

# छोटा फिक्स जो पिछले कमिट का हिस्सा है
git commit --fixup HEAD

# बाद में रीबेस में ऑटोस्क्वैश
git rebase -i --autosquash origin/main

--autosquash fixup! ... और squash! ... कमिट को लक्ष्य के नीचे ले जाता है और सही क्रियापद लगाता है। संपादक में पुष्टि फिर भी तुम्हारी।


कोड छुए बिना रीवर्ड

खराब संदेश सबसे आम सफाई है। डिफ छूने की जरूरत नहीं।

git rebase -i HEAD~3
# जिन पंक्तियों पर ध्यान हो, "pick" को "reword" करो

हर reword पर गिट रुकता है, संदेश संपादक खोलता है, फिर आगे बढ़ता है। जब खराब संदेश टिप कमिट न हो, तो git commit --amend से यही बेहतर।

अगर टिप ही है और पुश नहीं हुआ (या ब्रांच सिर्फ तुम्हारी):

git commit --amend
# या सिर्फ संदेश:
git commit --amend -m "feat(auth): validate session before refresh"

एडिट: इतिहास के बीच अमेंड या कमिट तोड़ना

edit उस कमिट पर रीबेस रोकता है। वर्किंग ट्री उसी स्नैपशॉट पर होता है। आम काम:

पुराने कमिट में फाइल छूट गई

git rebase -i HEAD~5
# लक्ष्य कमिट को "edit" करो
# जब गिट रुके:
git add path/to/missing-file
git commit --amend --no-edit
git rebase --continue

एक कमिट को दो में तोड़ना

# "edit" पॉज पर:
git reset HEAD^
git add -p   # पहली तार्किक छमाही
git commit -m "first half"
git add -p
git commit -m "second half"
git rebase --continue

git reset HEAD^ बदलाव ट्री में छोड़ता है ताकि फिर स्टेज कर सको। काम मिट नहीं रहा; कमिट फिर काटे जा रहे हैं।


कमिट का क्रम बदलना

कभी कहानी उल्टी होती है: टेस्ट उस कोड से पहले जिसे वे जांचते हैं, या फीचर के बीच रिफैक्टर।

टोडो सूची में पंक्तियां हिलाओ। सबसे पुराना ऊपर ही रहे; पंक्तियों का क्रम नया इतिहास है।

pick aaa1111 add API handler
pick bbb2222 add unit tests for handler
pick ccc3333 wire route in main

बाद वाला कमिट पहले वाले पर निर्भर हो तो क्रम बदलने से संघर्ष हो सकते हैं। ठीक है। सुलझाओ, git add, git rebase --continue। निर्भरता असली हो तो नींव वाला कमिट पहले रखो।


पूरी सफाई पास (रोज का पीआर रिवाज)

पीआर खोलने या अपडेट से पहले अक्सर चाहिए:

१. ब्रांच मौजूदा main पर आधारित हो।
२. डब्ल्यूआईपी शोर गया हो।
३. संदेश टीम शैली में हों (टिकट, दायरा, क्यों)।

git fetch origin
git rebase -i origin/main

टोडो का खाका:

pick 111aaaa feat: add checkout retry
fixup 222bbbb wip
fixup 333cccc fix tests
reword 444dddd more logging
pick 555eeee docs: note retry env flag

फिर:

# अगर ब्रांच पहले पुश हो चुकी थी, इतिहास बदला:
git push --force-with-lease

हमेशा --force के बजाय --force-with-lease। लीज तब मना करता है जब पिछले फेच के बाद रिमोट हिल चुका हो (किसी और ने पुश किया)। सस्ता सीट बेल्ट।


रीबेस कब न करें

इंटरैक्टिव रीबेस कमिट एसएचए बदल देता है। पुराने एसएचए पर जो कुछ निर्भर है, वह टकराएगा।

इन पर रीबेस मत करो:

  • main / master / साझा रिलीज ब्रांच जहां से बहुत लोग पुल करते हैं। पूर्ण विराम।
  • कोई भी ब्रांच जहां कई लोग पुश करते हैं, जब तक साफ समझौता और फ्रीज विंडो न हो।
  • वे कमिट जो मर्ज से अन्य लंबी-जीवित ब्रांच में पहले से घुस चुके। डुप्लिकेट या गंदा दोहरा इतिहास बनता है।
  • सार्वजनिक टैग और रिलीज एसएचए जिन्हें सीआई, डिप्लॉय या ऑडिट पिन करते हैं।

मर्ज चुनो (या इतिहास मत छेड़ो) जब:

  • ब्रांच साझा इंटीग्रेशन हो।
  • ऑडिटर को मूल कमिट श्रृंखला का ठीक-ठीक रिकॉर्ड चाहिए।
  • हर सहयोगी के साथ फोर्स-पुश समन्वय पर भरोसा न हो।

फीचर काम का सुरक्षित डिफ़ॉल्ट: अपनी फीचर ब्रांच को main पर रीबेस करो, लोकल साफ करो, अपनी फीचर रिमोट पर फोर्स-विद-लीज, पीआर खोलो/अपडेट करो। main कभी मत फिर लिखो।

कुछ टीमें रिमोट ब्रांच पर रीबेस पूरी तरह बंद रखती हैं और सिर्फ गिटहब/गिटलैब पर स्क्वैश-ऑन-मर्ज चलती हैं। यह वैध नीति है। इंटरैक्टिव रीबेस फिर भी पहले पुश से पहले, या सिर्फ तुम्हारी ब्रांच पर काम आता है।


रीबेस के दौरान संघर्ष

संघर्ष असफलता नहीं। गिट रुका है ताकि तुम फैसला लो।

# कौन-से पथ टकराए
git status

# फाइलें ठीक करो, फिर:
git add path/that/you/fixed
git rebase --continue

# या पूरा रीबेस छोड़कर वापस:
git rebase --abort

बीच में साफ ट्री चाहिए सोचने को:

git rebase --abort   # रीबेस-पूर्व अवस्था (जहां संभव)

--abort आपातकालीन निकास है। आधे-अधूरे ट्री और "बाद में ठीक करूंगा" से बेहतर।


गलतियों से वापसी

ओरिज_हेड

कई रीबेस ऑपरेशन ORIG_HEAD को ऑपरेशन से पहले की टिप पर सेट करते हैं।

# पहले कहां थे
git log --oneline ORIG_HEAD -5

# ब्रांच टिप हार्ड रीसेट (केवल मौजूदा टिप के लिए विध्वंसक)
git reset --hard ORIG_HEAD

हार्ड रीसेट तभी जब समझ हो कि फिर-लिखी टिप हटाकर रीबेस-पूर्व टिप रख रहे हो। बिना कमिट का काम अलग मुद्दा है; पहले कमिट या स्टैश।

रेफलॉग असली जाल है

हर टिप हिलना लोकल पर कुछ समय दर्ज रहता है (अक्सर डिफ़ॉल्ट ~९० दिन, कॉन्फिग पर निर्भर)।

git reflog
# उदाहरण पंक्तियां:
# abc1234 HEAD@{0}: rebase (finish): returning to refs/heads/feature/x
# def5678 HEAD@{1}: rebase (start): checkout origin/main
# 999aaaa HEAD@{2}: commit: wip

खराब रीबेस से पहले का एसएचए ढूंढो (HEAD@{n}), फिर:

git reset --hard HEAD@{2}
# या
git reset --hard 999aaaa

रेफलॉग लोकल है। दूसरे क्लोन पर नहीं बचाता। उसी मशीन पर बचाता है जहां इतिहास फिर लिखा, और "पांच मिनट पहले गलत चीज स्क्वैश कर दी" के लिए अक्सर काफी है।

गिराया गया कमिट जो अभी भी ऑब्जेक्ट डेटाबेस में हो

अगर कमिट ड्रॉप किया पर संदेश का टुकड़ा याद हो:

git fsck --lost-found
# या लटकते कमिट खोजो
git log --all --oneline --grep='partial message'

# एसएचए मिलते ही:
git show deadbeef
git branch rescue/deadbeef deadbeef

फिर उस रेस्क्यू ब्रांच से चेरी-पिक या रीसेट।

खराब फोर्स पुश वापस (समन्वय जरूरी)

अगर टूटी टिप फोर्स-पुश हो गई और किसी ने फेच कर लिया:

१. अच्छे एसएचए को अपने (या उनके) रेफलॉग से लाओ।
२. अच्छे एसएचए पर git push --force-with-lease
३. टीम को बताओ: सिर्फ उसी फीचर ब्रांच पर git fetch और git reset --hard origin/your-branch

इसीलिए साझा ब्रांच पर फोर्स-पुश प्रक्रिया की समस्या है, सिर्फ गिट की नहीं।


टीम नियम जो रीबेस को उपयोगी रखते हैं

कुछ रीति-रिवाज जो काम करते दिखे:

१. फीचर ब्रांच डिस्पोजेबल इतिहास हैं। साफ रखो। अगर पीआर में पहले से साफ कमिट हैं तो स्क्वैश-ऑन-मर्ज वैकल्पिक।
२. main कभी मत फिर लिखो। होस्ट सेटिंग में सुरक्षित रखो।
३. फोर्स-विद-लीज सिर्फ अपनी ब्रांच पर। बड़ी संस्था में ब्रांच नाम में अपना हैंडल रखो।
४. फोर्स-पुश के बाद सीआई फिर चले। ज्यादातर होस्ट करते हैं; जांचो।
५. कोड करते समय छोटे फिक्सअप, रिव्यू से पहले ऑटोस्क्वैश। लोकल फ्लो तेज, पीआर पठनीय।
६. दो लोग लंबी ब्रांच साझा करें तो सबके रीबेस की जगह main से मर्ज, या एक इतिहास मालिक तय करो।


त्वरित संदर्भ

# आखिरी एन कमिट पर इंटरैक्टिव रीबेस
git rebase -i HEAD~N

# अपडेटेड main पर
git fetch origin && git rebase -i origin/main

# काम करते हुए फिक्सअप कमिट
git commit --fixup <sha-or-HEAD>

# टोडो में फिक्सअप लागू
git rebase -i --autosquash origin/main

# संघर्ष प्रवाह
git add <files> && git rebase --continue
git rebase --abort

# फीचर ब्रांच फिर लिखने के बाद
git push --force-with-lease

# रिकवरी
git reflog
git reset --hard ORIG_HEAD
git reset --hard HEAD@{n}

बंद मानसिक मॉडल

इंटरैक्टिव रीबेस को "अतीत मिटाना" नहीं, पैच श्रृंखला संपादित करना समझो। पुराने कमिट अक्सर गार्बेज कलेक्शन तक रेफलॉग में रहते हैं। साझा कहानी वही है जो तुम पुश करते हो।

रिव्यू सस्ता बनाने को इस्तेमाल करो: कम कमिट, ईमानदार संदेश, मौजूदा main पर सीधी कहानी। जिस क्षण कमिट साझा अनुबंध बन जाएं, रोक दो। टोडो का कोई भी क्रियापद नहीं, यही सीमा साफ इतिहास को टीम हादसे से अलग करती है।