मैं अपने अंतिम X को एक साथ Git का उपयोग करते हुए कैसे कर सकता हूं?
मैं अपने अंतिम X को एक साथ Git का उपयोग करते हुए कैसे कर सकता हूं?
जवाबों:
मैनुअलgit rebase -i <after-this-commit>
में वर्णित "स्क्वैश" या "फिक्सअप" के साथ दूसरे और बाद में "पिक" का उपयोग करें और बदलें ।
इस उदाहरण में, <after-this-commit>
या तो SHA1 हैश है या वर्तमान शाखा के HEAD से संबंधित स्थान है जहां से रीमेस कमांड के लिए कमिट का विश्लेषण किया जाता है। उदाहरण के लिए, यदि उपयोगकर्ता पिछले कमांड में वर्तमान कमांड से 5 कमिट्स देखना चाहता है git rebase -i HEAD~5
।
<after-this-commit>
?
<after-this-commit>
प्रतिबद्ध है X + 1 यानी सबसे पुराने माता-पिता के लिए आप स्क्वैश करना चाहते हैं।
rebase -i
दृष्टिकोण और के बीच का अंतर reset --soft
, rebase -i
मुझे प्रतिबद्ध लेखक को बनाए रखने की reset --soft
अनुमति देता है , जबकि मुझे फिर से जोड़ने की अनुमति देता है। कभी-कभी मुझे लेखक की जानकारी को बनाए रखने के लिए अभी तक पुल अनुरोधों को स्वीकार करना पड़ता है। कभी-कभी मुझे अपने स्वयं के कमिट पर नरम रीसेट करने की आवश्यकता होती है। वैसे भी दोनों महान जवाब के लिए Upvotes।
आप इसे आसानी से git rebase
या बिना आसानी से कर सकते हैं git merge --squash
। इस उदाहरण में, हम पिछले 3 कमिट्स को स्क्वैश करेंगे।
यदि आप स्क्रैच से नया कमिट संदेश लिखना चाहते हैं, तो यह पर्याप्त है:
git reset --soft HEAD~3 &&
git commit
यदि आप नई प्रतिबद्ध संदेश को मौजूदा प्रतिबद्ध संदेशों (जैसे कि पिक / स्क्वैश / स्क्वैश /… / स्क्वैश git rebase -i
इंस्ट्रक्शन लिस्ट आप के साथ शुरू करेंगे) के संयोजन के साथ शुरू करना चाहते हैं, तो आपको उन संदेशों को निकालने और पास करने की आवश्यकता है उन्हें git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
उन दोनों विधियों ने पिछले तीनों को एक ही तरीके से एक नई प्रतिबद्धता में बदल दिया। सॉफ्ट रिसेट सिर्फ HEAD को आखिरी कमिट में बताता है कि आप स्क्वैश नहीं करना चाहते हैं। नरम रीसेट द्वारा न तो सूचकांक और न ही काम करने वाले पेड़ को छुआ जाता है, सूचकांक को अपनी नई प्रतिबद्ध के लिए वांछित स्थिति में छोड़ देता है (यानी इसमें पहले से ही उन सभी परिवर्तनों को शामिल किया गया है जिन्हें आप "फेंक" देते हैं)।
git rebase --squash-recent
, या यहां तक कि git commit --amend-many
।
branch@{upstream}
(या सिर्फ @{upstream}
वर्तमान शाखा के लिए; दोनों ही मामलों में, अंतिम भाग संक्षिप्त रूप में देखा जा सकता है @{u}
; gitrevisions देखें )। यह आपके "अंतिम पुश किए गए कमिट" से अलग हो सकता है (जैसे कि अगर किसी और ने कुछ ऐसा धक्का दिया, जो आपके सबसे हाल के पुश को बनाए और फिर आपने उसे प्राप्त किया), लेकिन ऐसा लगता है कि आप जो चाहते हैं उसके करीब हो सकता है।
push -f
लेकिन अन्यथा यह प्यारा था, धन्यवाद।
git push --force
बाद में भी उपयोग करने की आवश्यकता है ताकि यह प्रतिबद्ध हो जाए
आप इसके लिए उपयोग कर सकते हैं git merge --squash
, जो की तुलना में थोड़ा अधिक सुरुचिपूर्ण है git rebase -i
। मान लीजिए कि आप मास्टर हैं और आप अंतिम 12 को एक में बदलना चाहते हैं।
चेतावनी: पहले सुनिश्चित करें कि आप अपना काम कर रहे हैं - git status
साफ है कि जाँच करें (क्योंकि git reset --hard
मंचन और अस्थिर परिवर्तन फेंक देंगे)
फिर:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
के लिए प्रलेखनgit merge
--squash
अधिक विस्तार से विकल्प का वर्णन करता है।
अद्यतन: अपने जवाबgit reset --soft HEAD~12 && git commit
में क्रिस जॉन्सन द्वारा सुझाए गए सरल से अधिक इस पद्धति का एकमात्र वास्तविक लाभ यह है कि आपको हर प्रतिबद्ध संदेश के साथ पूर्वनिर्मित संदेश मिल जाता है जिसे आप स्क्वैश कर रहे हैं।
git rebase -i
, लेकिन आप एक कारण नहीं देते। Tentatively -1 यह क्योंकि यह मुझे लगता है कि वास्तव में विपरीत सच है और यह एक हैक है; क्या आप विशेष रूप से के लिए डिज़ाइन किए git merge
गए चीजों में से एक को करने के लिए मजबूर करने के लिए आवश्यक से अधिक कमांड का प्रदर्शन नहीं कर रहे हैं git rebase
?
git merge --squash
भी एक स्क्रिप्ट में उपयोग करने के लिए आसान है। मूलतः, तर्क यह था कि आपको इसके लिए "अन्तरक्रियाशीलता" की आवश्यकता नहीं है git rebase -i
।
git merge --squash
रिबासिंग की तुलना में चाल / हटा / नाम बदलने की स्थिति में मर्ज संघर्ष का उत्पादन करने की संभावना कम है, खासकर यदि आप स्थानीय शाखा से विलय कर रहे हैं। (अस्वीकरण: केवल एक अनुभव के आधार पर, मुझे सही करें अगर यह सामान्य मामले में सच नहीं है!)
HEAD@{1}
केवल सुरक्षित पक्ष पर होने के बजाय एक अस्थायी टैग का उपयोग करता हूं जैसे कि जब आपके वर्कफ़्लो को एक पावर आउटेज आदि द्वारा एक घंटे के लिए बाधित किया जाता है
मैं git reset
जब संभव हो तब परहेज करने की सलाह देता हूं - विशेष रूप से गिट-नौसिखियों के लिए। जब तक आपको वास्तव में कमिट की संख्या के आधार पर एक प्रक्रिया को स्वचालित करने की आवश्यकता नहीं है, तब तक कम विदेशी तरीका है ...
git merge --squash (working branch name)
git commit
स्क्वैश के आधार पर प्रतिबद्ध संदेश को पूर्व निर्धारित किया जाएगा।
gitk
कि आप जिस स्क्वैशिंग को कोड कर रहे हैं उसे लेबल करने के लिए GUI इंटरफ़ेस का उपयोग करें और जिस आधार पर स्क्वैश करना है उस पर भी लेबल लगाएँ। सामान्य स्थिति में, ये दोनों लेबल पहले से मौजूद होंगे, इसलिए चरण (1) को छोड़ दिया जा सकता है।
git branch your-feature && git reset --hard HEAD~N
सबसे सुविधाजनक तरीका मिल गया है। हालाँकि, इसमें फिर से git रीसेट शामिल है, जिसे इस उत्तर ने टालने की कोशिश की।
क्रिस जॉन्सन के जवाब के आधार पर ,
बैश से एक वैश्विक "स्क्वैश" उपनाम जोड़ें: (या विंडोज पर गेट बैश)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... या विंडोज कमांड कमांड प्रॉम्प्ट का उपयोग कर:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
~/.gitconfig
अब
आपके पास यह उपनाम होना चाहिए:
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
उपयोग:
git squash N
... जो स्वचालित रूप से पिछले N
कमिट्स को सम्मिलित करता है, समावेशी है।
नोट: परिणामी प्रतिबद्ध संदेश क्रम में सभी स्क्वैस्ड कमिट्स का संयोजन है। यदि आप इससे नाखुश हैं, तो आप git commit --amend
इसे मैन्युअल रूप से संशोधित कर सकते हैं । (या, अपने स्वाद से मेल खाने के लिए उपनाम संपादित करें।)
git squash -m "New summary."
और N
स्वचालित रूप से निर्धारित किया है के रूप में अप्रकाशित की संख्या।
git commit --amend
संदेश को और बदलने के लिए उपयोग कर सकते हैं , लेकिन यह उपनाम आपको प्रतिबद्ध संदेश में क्या होना चाहिए, इसकी एक अच्छी शुरुआत है।
इस आसान ब्लॉग पोस्ट की बदौलत मैंने पाया कि आप इस कमांड का उपयोग अंतिम 3 कमिट्स को स्क्वैश करने के लिए कर सकते हैं:
git rebase -i HEAD~3
यह आसान है क्योंकि यह तब भी काम करता है जब आप किसी ट्रैकिंग जानकारी / रिमोट रेपो के साथ स्थानीय शाखा में हों।
कमांड इंटरएक्टिव रिबेस संपादक को खोलेगा जो तब आपको सामान्य रूप से पुन: व्यवस्थित करने, स्क्वैश, पुन: लिखने आदि की अनुमति देता है।
इंटरएक्टिव रिबेस संपादक का उपयोग करना:
इंटरएक्टिव रिबेस संपादक आखिरी तीन कमिट दिखाता है। यह बाधा HEAD~3
कमान चलाते समय निर्धारित की गई थी git rebase -i HEAD~3
।
सबसे हालिया प्रतिबद्ध, HEAD
पहली पंक्ति 1 पर प्रदर्शित होता है। यह लाइनें एक #
टिप्पणी / प्रलेखन के साथ शुरू होती हैं।
प्रदर्शित प्रलेखन बहुत स्पष्ट है। किसी भी लाइन पर आप pick
कमांड को अपनी पसंद के कमांड से बदल सकते हैं ।
मैं कमांड का उपयोग करना पसंद करता हूं fixup
इस "स्क्वाश" के रूप ऊपर की लाइन पर कमिट में बदलाव करता है और कमिट का मैसेज छोड़ देता है।
जैसा कि लाइन 1 पर प्रतिबद्ध है HEAD
, ज्यादातर मामलों में आप इसे छोड़ देंगेpick
। आप का उपयोग नहीं कर सकते हैं squash
या के fixup
रूप में प्रतिबद्ध स्क्वैश करने के लिए कोई अन्य प्रतिबद्ध नहीं है।
आप आवागमन के क्रम को भी बदल सकते हैं। यह आपको स्क्वैश या फ़िक्सअप करने की अनुमति देता है जो आसन्न कालानुक्रमिक नहीं हैं।
एक व्यावहारिक हर रोज का उदाहरण
मैंने हाल ही में एक नई सुविधा के लिए प्रतिबद्ध किया है। तब से, मैंने दो बग फिक्स किए हैं। लेकिन अब मैंने जो नया फीचर किया है उसमें मैंने एक बग (या शायद सिर्फ एक स्पेलिंग एरर) खोज लिया है। कैसा कष्टकर! मैं अपने प्रतिबद्ध इतिहास को प्रदूषित करने वाली एक नई प्रतिबद्धता नहीं चाहता!
पहली चीज जो मैं करता हूं वह गलती को ठीक करना है और टिप्पणी के साथ एक नई प्रतिबद्धता बनाना है squash this into my new feature!
।
मैं तब (या इस मामले में ) नई सुविधा का प्रतिबद्ध SHA चलाता हूं git log
या gitk
प्राप्त करता हूं 1ff9460
।
अगला, मैं इंटरएक्टिव रिबेस संपादक को साथ लाता हूं git rebase -i 1ff9460~
। ~
प्रतिबद्ध के बाद SHA संपादक बताता है शामिल करने के लिए है कि संपादक में करते हैं।
इसके बाद, मैं fe7f1e0
फीचर कमिट के नीचे फिक्स ( ) युक्त कमेट को स्थानांतरित करता हूं , और इसमें बदलाव pick
करता हूं fixup
।
संपादक को बंद करते समय, फिक्स्ड फीचर कमिट में स्क्वैश हो जाएगा और मेरी कमिट हिस्ट्री अच्छी और साफ दिखेगी!
जब सभी कमिट स्थानीय हैं, तो यह अच्छी तरह से काम करता है, लेकिन अगर आप रिमोट से पहले से धकेल दिए गए किसी भी हिट को बदलने की कोशिश करते हैं, तो आप वास्तव में अन्य देवों के लिए समस्या पैदा कर सकते हैं जिन्होंने एक ही शाखा की जाँच की है!
pick
लाइन 1 में छोड़ दें । यदि आप लाइन 1 पर कमिट करते हैं squash
या चुनते हैं fixup
, तो git एक मैसेज दिखाएगा, जिसमें कहा जा सकता है कि "त्रुटि: पिछले कमिट के बिना 'फिक्स' नहीं कर सकता है"। फिर यह आपको इसे ठीक करने का विकल्प देगा: "आप इसे 'git rebase --edit-todo' से ठीक कर सकते हैं और फिर 'git rebase --continue' चला सकते हैं।" या आप सिर्फ गर्भपात कर सकते हैं और शुरू कर सकते हैं: "या आप रिबेट को 'गिट रिबेस - वेबोर्ट' के साथ गर्भपात करा सकते हैं।"
यदि आप TortoiseGit का उपयोग करते हैं, तो आप कार्य कर सकते हैं Combine to one commit
:
Show Log
Combine to one commit
संदर्भ मेनू से चयन करेंयह फ़ंक्शन स्वचालित रूप से सभी आवश्यक एकल गिट चरणों को निष्पादित करता है। Unfortunatly केवल Windows के लिए उपलब्ध है।
ऐसा करने के लिए आप निम्नलिखित git कमांड का उपयोग कर सकते हैं।
git rebase -i HEAD~n
n (= 4 यहाँ) अंतिम प्रतिबद्ध की संख्या है। फिर आपको निम्नलिखित विकल्प मिले,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
सबसे नीचे हाल में pick
एक कमिट और squash
अन्य की तरह अपडेट करें ,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
इस लेख के आधार पर मैंने इस विधि को अपने usecase के लिए आसान पाया।
मेरी My देव ’शाखा 96 कमिट द्वारा / उत्पत्ति / देव’ से आगे थी (इसलिए इन कमिटों को अभी तक रिमोट से नहीं धकेला गया था)।
मैं बदलाव को आगे बढ़ाने से पहले इन कमिट्स को एक साथ जोड़ना चाहता था। मैं 'मूल / देव' की स्थिति के लिए शाखा को रीसेट करने का पूर्वाभास करता हूं (यह 96 हिट से सभी परिवर्तन छोड़ देगा) और फिर एक ही बार में परिवर्तन करने के लिए प्रतिबद्ध हैं:
git reset origin/dev
git add --all
git commit -m 'my commit message'
जिस शाखा में आप कमिट्स को जोड़ना चाहते हैं, उसे चलाएं:
git rebase -i HEAD~(n number of commits back to review)
उदाहरण:
git rebase -i HEAD~1
यह टेक्स्ट एडिटर को खोलेगा और आपको प्रत्येक स्क्वैश के साथ 'पिक' को 'स्क्वैश' के साथ स्विच करना होगा अगर आप चाहेंगे कि ये कमिट्स एक साथ मर्ज हो जाएं। प्रलेखन से:
उदाहरण के लिए, यदि आप सभी कमिट्स को एक में मिलाना चाहते हैं, तो 'पिक' आपके द्वारा की गई पहली प्रतिबद्धता है और भविष्य के सभी (पहले से नीचे रखे गए) को 'स्क्वैश' में सेट किया जाना चाहिए। यदि विम का उपयोग कर रहे हैं, तो उपयोग करें : x तो संपादक को बचाने और बाहर निकलने के लिए इन्सर्ट मोड में ।
फिर रिबास जारी रखने के लिए:
git rebase --continue
इस पर और अपने प्रतिबद्ध इतिहास को फिर से लिखने के अन्य तरीकों के लिए इस उपयोगी पोस्ट को देखें
--continue
विम और विम :x
क्या करता है।
एनोमिस का उत्तर अच्छा है, लेकिन मैंने इस बारे में असुरक्षित महसूस किया इसलिए मैंने कुछ स्क्रीनशॉट जोड़ने का फैसला किया।
देखें कि आप कहां हैं git log
। सबसे महत्वपूर्ण है, पहली स् वश की हैश को खोजें जिसे आप स्क्वैश नहीं करना चाहते हैं। तो केवल:
git rebase -i [your hash]
मेरे मामले में निष्पादित करें :
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
मेरे मामले में, मैं उस समय जो कुछ पहली बार हुआ था, उस पर सब कुछ छीनना चाहता हूं। आदेश पहली से आखिरी तक है, ठीक उसी तरह जैसे दूसरे तरीके से git log
। मेरे मामले में, मुझे चाहिए:
यदि आपने केवल एक कमिट किया है और बाकी को स्क्वैश किया है, तो आप एक कमिट मैसेज एडजस्ट कर सकते हैं:
बस। एक बार जब आप इसे बचा :wq
लेते हैं ( ), तो आप कर रहे हैं। इसके साथ एक नज़र रखना git log
।
git log
1) कम शॉर्ट हैश की पहचान करें
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
यहां तक कि git log --oneline
शॉर्ट हैश पाने के लिए भी इस्तेमाल किया जा सकता है।
2) यदि आप अंतिम दो प्रतिबद्ध करना चाहते हैं (मर्ज)
# git rebase -i deab3412
3) यह nano
विलय के लिए एक संपादक को खोलता है । और यह नीचे की तरह दिखता है
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) उस शब्द pick
का नाम बदलें squash
जो पहले मौजूद है abcd1234
। नाम बदलने के बाद यह नीचे की तरह होना चाहिए।
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) अब nano
एडिटर को सेव और बंद करें । बचाने के लिए दबाएं ctrl + o
और दबाएं Enter
। और फिर दबाएँctrl + x
संपादक से बाहर निकलने के लिए ।
6) तब nano
संपादक अपडेट के लिए फिर से खुलता है, यदि आवश्यक हो तो इसे अपडेट करें।
7) अब इसका स्क्वैश सफलतापूर्वक हो गया है, आप लॉग की जाँच करके इसे सत्यापित कर सकते हैं।
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) अब रेपो पर पुश करें। +
शाखा के नाम से पहले हस्ताक्षर जोड़ने के लिए ध्यान दें । इसका मतलब है जबरदस्ती धक्का देना।
# git push origin +master
नोट: यह ubuntu
शेल पर गिट का उपयोग करने पर आधारित है । यदि आप अलग-अलग ओएस ( Windows
या Mac
) का उपयोग कर रहे हैं तो ऊपर के कमांड संपादक के अलावा समान हैं। आपको अलग-अलग संपादक मिल सकते हैं।
git add <files>
--fixup
विकल्प का उपयोग करने के लिए प्रतिबद्ध OLDCOMMIT
होना चाहिए और उस पर होना चाहिए जिस पर हमें इस कमिट को मर्ज (स्क्वैश) करना है।git commit --fixup=OLDCOMMIT
अब यह HEAD के शीर्ष पर एक नई प्रतिबद्धता बनाता है fixup1 <OLDCOMMIT_MSG>
।
OLDCOMMIT
।git rebase --interactive --autosquash OLDCOMMIT^
यहाँ ^
पिछले करने का मतलब है OLDCOMMIT
। यह rebase
कमांड एक संपादक (विम या नैनो) पर इंटरैक्टिव विंडो खोलता है, जिस पर हमें कुछ भी करने की आवश्यकता नहीं है बस बचाने और बाहर निकलने के लिए पर्याप्त है। क्योंकि इसमें दिया गया विकल्प स्वचालित रूप से नवीनतम प्रतिबद्ध को पुरानी प्रतिबद्ध के बगल में ले जाएगा और ऑपरेशन fixup
को स्क्वैश के बराबर में बदल देगा । फिर रिबास जारी है और खत्म।
--amend
साथ नए बदलाव जोड़ने की आवश्यकता है, तो इसका उपयोग किया जा सकता है git-commit
। # git log --pretty=oneline --abbrev-commit
cdababcd Fix issue B
deab3412 Fix issue A
....
# git add <files> # New changes
# git commit --amend
# git log --pretty=oneline --abbrev-commit
1d4ab2e1 Fix issue B
deab3412 Fix issue A
....
यहां --amend
अंतिम बदलावों के लिए नए बदलावों का विलय किया गया है cdababcd
और नई प्रतिबद्ध आईडी बनाई गई है1d4ab2e1
अंतिम 10 स्क्वैश को 1 सिंगल कमिट में करना है:
git reset --soft HEAD~10 && git commit -m "squashed commit"
यदि आप भी स्क्वैश कमिट के साथ रिमोट ब्रांच को अपडेट करना चाहते हैं:
git push -f
यदि आप एक सुदूर शाखा (जिसे feature-branch
गोल्डन रिपॉजिटरी) कहा जाता है ) से क्लोन किया गया है golden_repo_name
, तो यहाँ आपके द्वारा एक में स्क्वैश करने की तकनीक है:
गोल्डन रेपो की जाँच करें
git checkout golden_repo_name
निम्नानुसार से एक नई शाखा (गोल्डन रेपो) बनाएँ
git checkout -b dev-branch
स्क्वैश आपके स्थानीय शाखा के साथ विलय कर देता है जो आपके पास पहले से है
git merge --squash feature-branch
अपने परिवर्तन करें (यह एकमात्र ऐसी प्रतिबद्धता होगी जो देव-शाखा में जाती है)
git commit -m "My feature complete"
अपने स्थानीय भंडार में शाखा को पुश करें
git push origin dev-branch
क्या वास्तव में सुविधाजनक हो सकता है:
आप के शीर्ष पर स्क्वैश करना चाहते हैं, कहते हैं खोजें d43e15
।
अब उपयोग करें
git reset d43e15
git commit -am 'new commit name'
यह सुपर-डुपर कुल्डी है, लेकिन एक तरह से शांत तरीके से, इसलिए मैं इसे रिंग में टॉस करूंगा:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
अनुवाद: गिट के लिए एक नया "संपादक" प्रदान करते हैं, अगर फ़ाइलनाम को संपादित किया जाना है git-rebase-todo
(संवादात्मक रिबेस प्रॉम्प्ट), लेकिन सभी "पिक" को "स्क्वैश" में बदल देता है, और अन्यथा वीम स्पॉन्ज करता है - ताकि जब आपको संकेत दिया जाए स्क्वैश किए गए संदेश को संपादित करने के लिए, आपको विम मिलेगा। (और जाहिर है कि मैं शाखा फू पर पिछले पांच कमिट्स को तोड़ रहा था, लेकिन आप इसे पसंद कर सकते हैं।)
मैं शायद वही करूँगा जो मार्क लोंगेयर ने सुझाया था , हालाँकि।
यदि आप हर कमिट को एक ही कमिट में स्क्वीज़ करना चाहते हैं (जैसे पहली बार सार्वजनिक रूप से किसी प्रोजेक्ट को जारी करते समय), तो कोशिश करें:
git checkout --orphan <new-branch>
git commit
मुझे लगता है कि ऐसा करने का सबसे आसान तरीका यह है कि नई शाखा को मास्टर से दूर कर दिया जाए और सुविधा शाखा का मर्ज - स्क्वैश किया जाए।
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
फिर आपके पास सभी बदलाव करने के लिए तैयार हैं।
सरल एक-लाइनर जो हमेशा काम करता है, यह देखते हुए कि आप वर्तमान में उस शाखा पर हैं जिसे आप स्क्वैश करना चाहते हैं, मास्टर वह शाखा है जिसकी उत्पत्ति हुई है, और नवीनतम कमिट में वह प्रतिबद्ध संदेश और लेखक है जिसका आप उपयोग करना चाहते हैं:
git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
यदि उदाहरण के लिए आप अंतिम 3 को एक शाखा में एक कमिट के लिए भेजना चाहते हैं (दूरस्थ रिपॉजिटरी) उदाहरण के लिए: https://bitbucket.org
मैंने जो किया है
(MASTER)
Fleetwood Mac Fritz
║ ║
Add Danny Lindsey Stevie
Kirwan Buckingham Nicks
║ ╚═══╦══════╝
Add Christine ║
Perfect Buckingham
║ Nicks
LA1974══════════╝
║
║
Bill <══════ YOU ARE EDITING HERE
Clinton (CHECKED OUT, CURRENT WORKING DIRECTORY)
Https://github.com/fleetwood-mac/band-history रिपॉजिटरी के इस बहुत संक्षिप्त इतिहास में आपने बिल क्लिंटन को मूल ( MASTER
) फ्लीटवुड मैक कमिट में विलय करने के लिए एक पुल अनुरोध खोला है ।
आपने पुल अनुरोध खोला और GitHub पर आप इसे देखते हैं:
चार काम:
यह सोचकर कि कोई भी कभी भी पूर्ण भंडार इतिहास पढ़ने की परवाह नहीं करेगा। (वास्तव में एक भंडार है, ऊपर दिए गए लिंक पर क्लिक करें!) आप इन कमानों को स्क्वैश करने का निर्णय लेते हैं। इसलिए तुम जाओ और दौड़ो git reset --soft HEAD~4 && git commit
। तो फिर आप git push --force
अपने पीआर को साफ करने के लिए GitHub पर जाएं।
और क्या होता है? आपने अभी-अभी सिंगल कमिट किया है जो फ्रिट्ज से बिल क्लिंटन तक मिलता है। क्योंकि आप भूल गए थे कि कल आप इस परियोजना के बकिंघम निक संस्करण पर काम कर रहे थे। और git log
जो आप GitHub पर देखते हैं उससे मेल नहीं खाता।
git checkout
उन्हेंgit reset --soft
वहgit commit
से सीधे कि warps से करने के लिएअन्य उत्कृष्ट उत्तरों के अलावा, मैं यह जोड़ना चाहूंगा कि कैसे git rebase -i
हमेशा मुझे प्रतिबद्ध आदेश के साथ भ्रमित करता है - नए से पुराना या इसके विपरीत? तो यह मेरा वर्कफ़्लो है:
git rebase -i HEAD~[N]
, जहां एन सबसे हाल ही में एक से शुरू होने वाले कमिट की संख्या है, जिसमें मैं शामिल होना चाहता हूं । तो git rebase -i HEAD~5
इसका मतलब होगा "अंतिम 5 स्क्वैश एक नए में शुरू होता है";इस तरह एक वर्कफ़्लो से संबंधित प्रश्न के उत्तर के बारे में क्या?
merge --squash
पीआर के बाद डेवलपर के लिए यह आसान होगा , लेकिन टीम ने सोचा कि इससे प्रक्रिया धीमी हो जाएगी।)मैंने इस पृष्ठ पर उस तरह का वर्कफ़्लो नहीं देखा है। (यह मेरी आंखें हो सकती हैं।) अगर मैं rebase
सही ढंग से समझूं, तो कई मर्जों के लिए कई संघर्ष संकल्पों की आवश्यकता होगी । मैं उस बारे में सोचना भी नहीं चाहता!
तो, यह हमारे लिए काम करने लगता है।
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
// सभी परिवर्तनों को चरण में रखता हैgit commit 'one message to rule them all'
git push
मुझे लगता है कि 'एन' कमिट को निर्दिष्ट करने के लिए एक अधिक सामान्य समाधान नहीं है, बल्कि उस शाखा / कमिट-आईडी के बारे में जिसे आप शीर्ष पर रखना चाहते हैं। यह एक विशिष्ट कमिट तक कमियों को गिनने की तुलना में कम त्रुटि वाला है - सीधे टैग को निर्दिष्ट करें, या यदि आप वास्तव में गिनना चाहते हैं तो आप HEAD ~ N निर्दिष्ट कर सकते हैं।
मेरे वर्कफ़्लो में, मैं एक शाखा शुरू करता हूं, और उस शाखा पर मेरी पहली प्रतिबद्धता लक्ष्य को सारांशित करती है (यानी यह आमतौर पर है कि मैं सार्वजनिक रिपॉजिटरी को सुविधा के लिए 'अंतिम' संदेश के रूप में धक्का दूंगा।) तो जब मैं पूरा हो जाता हूं। मैं करना चाहता हूं git squash master
पहले संदेश पर वापस जाना चाहता हूं और फिर धक्का देने के लिए तैयार हूं।
मैं उपनाम का उपयोग करता हूं:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
ऐसा करने से पहले इतिहास को दरकिनार कर दिया जाएगा - इससे आपको एक पुरानी प्रतिबद्ध आईडी को कंसोल से हथियाने का मौका मिलता है, अगर आप वापस करना चाहते हैं। (सोलारिस उपयोगकर्ता ध्यान दें कि यह GNU sed -i
विकल्प का उपयोग करता है , मैक और लिनक्स उपयोगकर्ता इसके साथ ठीक होना चाहिए।)
git squash master
जब हम गुलाम की जाँच करते हैं तो हम उसका उपयोग करते हैं। क्या होगा? क्या हम संघर्ष को छिपाएंगे?
प्रश्न में यह अस्पष्ट हो सकता है कि "अंतिम" से क्या अभिप्राय है।
उदाहरण के git log --graph
लिए निम्नलिखित (सरलीकृत) आउटपुट:
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
फिर समय से अंतिम हिट H0, मर्ज, B0 हैं। उन्हें स्क्वैश करने के लिए आपको प्रतिबद्ध एच 1 पर अपनी मर्ज की गई शाखा को रिबेट करना होगा।
समस्या यह है कि H0 में H1 और H2 शामिल हैं (और आम तौर पर मर्ज करने से पहले और बाद में ब्रांच करने के बाद) अधिक होता है जबकि B0 नहीं। इसलिए आपको कम से कम H0, मर्ज, H1, H2, B0 से बदलाव का प्रबंधन करना होगा।
पुन: उपयोग करना संभव है, लेकिन अलग-अलग तरीकों से फिर दूसरों के उत्तर में उल्लेख किया गया है:
rebase -i HEAD~2
यह आपको विकल्प विकल्प दिखाएगा (जैसा कि अन्य उत्तरों में बताया गया है):
pick B1
pick B0
pick H0
H0 लेने के बजाय स्क्वैश लगाएं:
pick B1
pick B0
s H0
सहेजें और बाहर निकलने के बाद रिबास एच 1 के बाद बदले में कमिट लागू करेगा। इसका मतलब है कि यह आपको फिर से संघर्षों को हल करने के लिए कहेगा (जहां HEAD पहली बार H1 होगा और फिर लागू होते ही जमा हो जाएगा)।
रिबेस करने के बाद आप स्क्वैस्ड H0 और B0 के लिए संदेश चुन सकते हैं:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
PS यदि आप केवल BO के लिए कुछ रीसेट करते हैं: (उदाहरण के लिए, इसका उपयोग करके reset --mixed
यहां और अधिक विस्तार से बताया गया है https://stackoverflow.com/a/18690845/2405850 ):
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
तब आप H0, H1, H2 के B0 परिवर्तनों में स्क्वैश करते हैं (ब्रांचिंग के बाद और विलय से पहले परिवर्तनों के लिए पूरी तरह से कम हो जाते हैं।