Git में अंतिम प्रतिबद्ध को दो में विभाजित कैसे करें


277

मेरी दो कार्यकारी शाखाएँ हैं, मास्टर और फ़ोरम और मैंने फ़ोरम ब्रांच में कुछ संशोधन किए हैं , कि मैं मास्टर में चेरी-पिक करना चाहूँगा । लेकिन दुर्भाग्य से, मैं जिस चेरी-पिक के लिए प्रतिबद्ध हूं, उसमें कुछ संशोधन भी शामिल हैं जो मुझे नहीं चाहिए।

समाधान शायद किसी भी तरह गलत कमिट को डिलीट करने और दो अलग-अलग कमिट्स के साथ बदलने के लिए होगा, एक वे बदलाव जिनमें मैं मास्टर को चुनना चाहता हूं, और अन्य जो वहां नहीं हैं।

मैंने करने की कोशिश की है

git reset --hard HEAD^

जिसने सभी परिवर्तन हटा दिए, इसलिए मुझे वापस जाना पड़ा

git reset ORIG_HEAD

तो मेरा सवाल यह है कि आखिरी कमिट को दो अलग-अलग कमिट में विभाजित करने का सबसे अच्छा तरीका क्या है ?

जवाबों:


332

आपको सूचकांक का उपयोग करना चाहिए। मिश्रित रीसेट करने के बाद (" git रीसेट HEAD ^"), इंडेक्स में परिवर्तन का पहला सेट जोड़ें, फिर उन्हें प्रतिबद्ध करें। फिर बाकी काम करें।

आप एक फ़ाइल में किए गए सभी परिवर्तनों को इंडेक्स में डालने के लिए " गिट ऐड " का उपयोग कर सकते हैं । यदि आप किसी फ़ाइल में किए गए प्रत्येक संशोधन को चरणबद्ध नहीं करना चाहते हैं, तो केवल उनमें से कुछ, आप "गिट ऐड-पी" का उपयोग कर सकते हैं।

एक उदाहरण देखते हैं। मान लीजिए कि मेरे पास myfile नामक एक फ़ाइल थी, जिसमें निम्नलिखित पाठ शामिल हैं:

something
something else
something again

मैंने इसे अपनी अंतिम प्रतिबद्ध में संशोधित किया ताकि अब यह इस तरह दिखे:

1
something
something else
something again
2

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

पहले मैं हेड के माता-पिता के पास वापस जाता हूं, लेकिन मैं फाइल सिस्टम में संशोधनों को रखना चाहता हूं, इसलिए मैं तर्क के बिना "गिट रीसेट" का उपयोग करता हूं (जो तथाकथित "मिश्रित" रीसेट करेगा):

$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2

अब मैं "git ऐड-पी" का उपयोग उन बदलावों को जोड़ने के लिए करता हूं, जो मैं इंडेक्स के लिए करना चाहता हूं (= मैं उन्हें स्टेज करता हूं)। "git add -p" एक इंटरेक्टिव टूल है, जो आपसे पूछता है कि इंडेक्स में फाइल में क्या बदलाव होने चाहिए।

$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s    # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y  # yes, I want to stage this
@@ -1,3 +2,4 @@
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n   # no, I don't want to stage this

तब मैं यह पहला परिवर्तन करता हूं:

$ git commit -m "Added first line"
[master cef3d4e] Added first line
 1 files changed, 1 insertions(+), 0 deletions(-)

अब मैं अन्य सभी बदलाव कर सकता हूं (अर्थात अंतिम पंक्ति में रखा गया अंक "2"):

$ git commit -am "Added last line"
[master 5e284e6] Added last line
 1 files changed, 1 insertions(+), 0 deletions(-)

आइए लॉग की जाँच करें कि हमारे पास क्या है:

$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...

    Added last line

Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
 something
 something else
 something again
+2

Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...

    Added first line

Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again

1
मुझे पिछले एक-डेढ़ सप्ताह से मर्क्यूरियल से धीरे-धीरे आदत git reset [--patch|-p] <commit>पड़ रही है , और एक आसान शॉर्टकट कमांड है जिसे आप git add -pरीसेट करने के बाद होने वाली परेशानी से बचाने के लिए उपयोग कर सकते हैं । क्या मैं सही हू? जीआईटी 1.7.9.5 का उपयोग करना।
trojjer

2
यहां इस तकनीक पर थोड़ा और अधिक है, जिसमें रिबासिंग भी शामिल है अगर यह एक पुरानी प्रतिबद्धता थी, या आपको एन कमिट को एम कमिट में बदलने की आवश्यकता है: emmanuelbernard.com/blog/2014/04/14/…
क्रिस वेस्टिन

84

लक्ष्य:

  • मैं एक पिछले कमिट ( splitme) को दो में विभाजित करना चाहता हूं ।
  • मैं प्रतिबद्ध संदेश बनाए रखना चाहता हूं ।

योजना:

  1. एक से पहले इंटरैक्टिव रिबास splitme
  2. संपादित करें splitme
  3. दूसरी कमिट में विभाजित करने के लिए फ़ाइलों को रीसेट करें।
  4. संशोधन करें, संदेश बनाए रखें, आवश्यकतानुसार संशोधित करें।
  5. पहले कमिट से विभाजित की गई फ़ाइलों को वापस जोड़ें।
  6. एक नए संदेश के साथ प्रतिबद्ध।
  7. रिबास जारी रखें।

अगर splitmeहाल ही में कमिट किया गया तो रिबेस चरण (1 और 7) को छोड़ दिया जा सकता है।

git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue

अगर मैं चाहता था कि विभाजन की फाइलें पहले प्रतिबद्ध हों, तो मैं फिर से रीबेस करूंगा और ऑर्डर को स्विच करूंगा

git rebase -i splitme^
# swap order of splitme and 'just some files'

1
git reset HEAD^पहेली का गायब टुकड़ा था। के साथ अच्छी तरह से काम करता -pहै। धन्यवाद!
मारियस गेदमिनस

10
यह -- $filesतर्क नोट करने के लिए महत्वपूर्ण है git reset। रास्तों के पारित होने के साथ, git resetउन फ़ाइलों को संदर्भित कमिट की स्थिति में पुनर्स्थापित करता है , लेकिन कोई भी परिवर्तन नहीं करता है। यदि आप रास्तों को छोड़ देते हैं, तो आप अगले चरण में संशोधन करना चाहते हैं।
द्वंद्व अंकन

2
यह विधि स्वीकृत उत्तर की तुलना में आपको अपने पहले प्रतिबद्ध संदेश को फिर से कॉपी और पेस्ट करने से रोकती है।
केल्विन

इसके अलावा: यदि आप सभी फ़ाइलों को रीसेट करना चाहते हैं, तो बस उपयोग करें git reset HEAD^ -- .। बेहद आश्चर्यजनक रूप से, यह बिल्कुल व्यवहार नहीं है git reset HEAD^
अल्लिडोइसविन

52

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

कोई एक:

git reset --soft HEAD^

यह अंतिम प्रतिबद्ध को समाप्त करता है लेकिन सब कुछ छोड़ देता है। तब आप कुछ फ़ाइलों को अस्थिर कर सकते हैं:

git reset -- file.file

वैकल्पिक रूप से उन फ़ाइलों के कुछ हिस्सों को पुनर्स्थापित करें:

git add -p file.file

एक नया पहला काम करें:

git commit

मंच और बाकी बदलावों को एक दूसरी प्रतिबद्धता में करते हैं:

git commit -a

या:

पिछली बार किए गए परिवर्तनों में से सभी को पूर्ववत और अस्थिर करें:

git reset HEAD^

परिवर्तनों के पहले दौर का चयन करें:

git add -p

प्रतिबद्ध:

git commit

बाकी बदलाव करें:

git commit -a

(किसी भी चरण में, यदि आप एक ऐसी कमिट को खोल देते हैं जिसमें एक बिलकुल नई फ़ाइल जोड़ी गई है और इसे दूसरी कमेटी में जोड़ना चाहते हैं, तो आपको इसे मैन्युअल रूप से जोड़ना होगा क्योंकि commit -aपहले से ही ट्रैक की गई फ़ाइलों में केवल परिवर्तन होता है।)


22

भागो git gui, "अमेंड लास्ट कमिट" रेडियो बटन का चयन करें, और अनस्टेज (कमिट> अनस्टेज फ्रॉम कमिट, या Ctrl- U) ऐसे बदलाव जो आप पहले कमिट में नहीं जाना चाहते। मुझे लगता है कि इसके बारे में जाने का सबसे आसान तरीका है।

एक और चीज जो आप कर सकते हैं, वह है बदलाव के बिना चेरी-पिक ( git cherry-pick -n) और फिर मैन्युअल रूप से या git guiकमिट करने से पहले वांछित बदलावों का चयन करें।


15
git reset HEAD^

-हार्ड आपके परिवर्तनों को मार रहा है।


13

मुझे आश्चर्य है कि किसी ने सुझाव नहीं दिया git cherry-pick -n forum। यह नवीनतम forumप्रतिबद्ध से परिवर्तनों को चरणबद्ध करेगा, लेकिन उन्हें प्रतिबद्ध नहीं करेगा - फिर आप उन resetपरिवर्तनों को दूर कर सकते हैं जिनकी आपको आवश्यकता नहीं है और जो आप रखना चाहते हैं उसे प्रतिबद्ध करें।


3

डबल-रिवर्ट-स्क्वैश विधि

  1. एक और प्रतिबद्ध बनाएं जो अवांछित बदलावों को दूर करता है। (यदि यह फ़ाइल के अनुसार है, तो यह वास्तव में आसान है: git checkout HEAD~1 -- files with unwanted changesऔर git commit। यदि नहीं, तो मिश्रित परिवर्तनों वाली फाइलें आंशिक रूप से मंचित की जा सकती हैं git reset fileऔर git add -p fileएक मध्यवर्ती चरण के रूप में।) इसे वापस लाएं
  2. git revert HEAD- अभी तक एक और प्रतिबद्ध करें, जो अवांछित परिवर्तनों को वापस जोड़ता है। यह डबल रिवर्ट है
  3. अब किए गए 2 कमिट्स में से, स्प्लिट ( ) के लिए कमिट पर सबसे पहले स्क्वैश करें git rebase -i HEAD~3। यह प्रतिबद्ध अब अवांछित बदलावों से मुक्त हो गया है, जो दूसरे प्रतिबद्ध में हैं।

लाभ

  • प्रतिबद्ध संदेश को संरक्षित करता है
  • यहां तक ​​कि अगर विभाजन के लिए प्रतिबद्ध अंतिम एक नहीं है। इसके लिए केवल यह आवश्यक है कि अवांछित परिवर्तन बाद में होने वाले विवादों के साथ संघर्ष न करें

1

चूंकि आप चेरी-पिकिंग कर रहे हैं, आप कर सकते हैं:

  1. cherry-pick--no-commitविकल्प के साथ जोड़ा गया।
  2. resetऔर उपयोग add --patch, add --editया addआप क्या रखना चाहते हैं मंच के लिए।
  3. commit मंचन बदल जाता है।
    • मूल प्रतिबद्ध संदेश का पुनः उपयोग करने के लिए, आप जोड़ सकते हैं --reuse-message=<old-commit-ref> कमांड में --reedit-message=<old-commit-ref>विकल्प याcommit
  4. के साथ अस्थिर परिवर्तन दूर उड़ा दें reset --hard

मूल प्रतिबद्ध संदेश को संरक्षित या संपादित करने का दूसरा तरीका:

  1. cherry-pick सामान्य के रूप में मूल प्रतिबद्ध है।
  2. उन परिवर्तनों को उल्टा करें जिन्हें आप नहीं चाहते और उपयोग करें add उन्हें उलट दें और उलटफेर करने के लिए करें।
    • यह कदम आसान होगा यदि आप जो कुछ भी जोड़ रहे हैं उसे हटा रहे हैं, लेकिन थोड़ा मुश्किल है अगर आप जो जोड़ रहे हैं उसे हटा दें या बदलाव को उलट दें।
  3. commit --amend चेरी-उठाया प्रतिबद्ध पर उलट असर करने के लिए।
    • आपको फिर से वही प्रतिबद्ध संदेश मिलेगा, जिसे आप आवश्यकतानुसार रख या संशोधित कर सकते हैं।

0

यह उन मामलों के लिए लक्षित एक और समाधान हो सकता है जहां एक बड़ी प्रतिबद्धता है और एक छोटी मात्रा में फ़ाइलों को एक नई प्रतिबद्ध में स्थानांतरित करने की आवश्यकता है। यह सेट का काम करेगा<path> फाइलों के एचईएडी में अंतिम कमिट से बाहर निकाला जाए और सभी को एक नई कमेटी में ले जाया जाए। यदि कई कमिट्स की आवश्यकता होती है तो अन्य समाधानों का उपयोग किया जा सकता है।

पहले मंचित और अस्थिर क्षेत्रों में पैच बनाएं, जिसमें संशोधन से पहले और बाद में कोड को वापस करने के लिए परिवर्तन शामिल होंगे:

git reset HEAD^ <path>

$ git status
On branch <your-branch>
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   <path>

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   <path>

यह समझने के लिए कि क्या होने वाला है (तीर और टिप्पणियां कमांड का हिस्सा नहीं हैं):

git diff --cached   -> show staged changes to revert <path> to before HEAD
git diff            -> show unstaged changes to add current <path> changes

<path>अंतिम प्रतिबद्ध में परिवर्तन वापस करें:

git commit --amend  -> reverts changes on HEAD by amending with staged changes

<path>परिवर्तनों के साथ नई प्रतिबद्धता बनाएँ :

git commit -a -m "New Commit" -> adds new commit with unstaged changes

इसमें नई कमेटी बनाने का प्रभाव होता है जिसमें आखिरी कमिटमेंट से निकाले गए बदलाव होते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.