एक से पहले पुश करने के लिए कई कमांडों का संयोजन


130

यह सवाल न केवल इस कार्य को पूरा करने के तरीके से संबंधित है, बल्कि यह करने के लिए कि क्या यह अच्छा है या बुरा व्यवहार।

विचार करें कि स्थानीय रूप से मैं मास्टर शाखा पर सबसे अधिक काम करता हूं, लेकिन मैंने एक सामयिक शाखा बनाई है जिसे मैं "topical_xFeature" कहूंगा। "Topical_xFeature" पर काम करने और मास्टर शाखा पर अन्य कार्य करने के लिए आगे और पीछे स्विच करने की प्रक्रिया में, यह पता चलता है कि मैंने "topical_xFeature" शाखा पर एक से अधिक प्रतिबद्ध किए हैं, लेकिन प्रत्येक प्रतिबद्ध के बीच, मैंने कोई काम नहीं किया है धक्का दें।

पहले , क्या आप इस बुरे व्यवहार पर विचार करेंगे? प्रति शाखा प्रति एक प्रतिबद्ध के साथ रहना समझदारी नहीं होगी? किन मामलों में एक शाखा पर एक धक्का देने से पहले कई बार अच्छा होगा?

दूसरा , मैं एक पुश के लिए मास्टर शाखा में topical_xFeature शाखा पर कई कमिट लाने के लिए सबसे अच्छा कैसे करूंगा? क्या इसके बारे में चिंता न करने के लिए यह एक उपद्रव है और केवल उस धक्का को करें जहां कई कमिट्स को धक्का दिया जाता है, या किसी तरह कमिट्स को एक में विलय करना और फिर धक्का देना कम कष्टप्रद है? फिर, यह कैसे करना है?

जवाबों:


139

आपके पहले प्रश्न के लिए, नहीं, एक साथ कई कमिट्स को धकेलने में कुछ भी गलत नहीं है। कई बार, आप अपने काम को कुछ छोटे, तार्किक तरीकों से तोड़ना चाहते हैं, लेकिन पूरी श्रृंखला तैयार होने के बाद ही उन्हें धक्का दें। या आप डिस्कनेक्ट होने के दौरान स्थानीय रूप से कई कमिट कर सकते हैं, और एक बार फिर से कनेक्ट होने पर आप उन सभी को धक्का देते हैं। अपने आप को धक्का देने के लिए खुद को सीमित करने का कोई कारण नहीं है।

मुझे आमतौर पर लगता है कि प्रत्येक को एक एकल, तार्किक, सुसंगत परिवर्तन रखने के लिए एक अच्छा विचार है, जिसमें वह सब कुछ शामिल है जो उसे काम करने की आवश्यकता है (इसलिए, यह आपके कोड को टूटी हुई स्थिति में नहीं छोड़ता है)। यदि आपके पास दो कमिट हैं, लेकिन वे कोड को तोड़ने का कारण बनेंगे यदि आपने केवल पहले एक को लागू किया है, तो दूसरी प्रतिबद्ध को पहले में स्क्वैश करना एक अच्छा विचार हो सकता है। लेकिन अगर आपके पास दो कमिट हैं जहां हर एक एक उचित बदलाव करता है, तो उन्हें अलग-अलग कमिट के रूप में धकेलना ठीक है।

यदि आप एक साथ कई आवागमन स्क्वैश करना चाहते हैं, तो आप उपयोग कर सकते हैं git rebase -i। यदि आप शाखा पर हैं topical_xFeature, तो आप दौड़ेंगे git rebase -i master। यह एक संपादक विंडो खोलेगा, जिसमें उपसर्गों के सूचीबद्ध उपसर्ग होंगे pick। आप सभी को बदल सकते हैं लेकिन पहले को squash, जो उन सभी परिवर्तनों को रखने के लिए गिट को बताएगा, लेकिन उन्हें पहले प्रतिबद्ध में स्क्वैश करेगा। ऐसा करने के बाद, masterअपनी सुविधा शाखा में देखें और मर्ज करें:

git checkout topical_xFeature
git rebase -i master
git checkout master
git merge topical_xFeature

वैकल्पिक रूप से, अगर आप सिर्फ में स्क्वैश सब कुछ करना चाहते हैं topical_xFeatureमें master, तुम बस निम्नलिखित कर सकता है:

git checkout master
git merge --squash topical_xFeature
git commit

आप जो चुनते हैं, वह आपके ऊपर है। आम तौर पर, मैं कई छोटे कमिट होने के बारे में चिंता नहीं करता, लेकिन कभी-कभी आप अतिरिक्त मामूली कमेंट्स से परेशान नहीं होना चाहते हैं, इसलिए आप उन्हें एक में स्क्वैश करें।


1
--Squash के साथ मर्ज होने के बाद, मैं विषय शाखा को हटा नहीं पा रहा हूं git branch -d topic। Git यह पहचानने में सक्षम क्यों नहीं है कि सभी परिवर्तन विलय कर दिए गए हैं?
बाल्की

7
@balki क्योंकि Git का पता लगाता है कि क्या पैच दिए गए मर्ज के आधार पर मर्ज किए गए हैं या नहीं। स्क्वैश करना उन्हें बदलता है; वे एक नई कमिट बन जाते हैं, और जबकि वह नई कमिट अन्य लोगों की तरह ही होती है, Git यह नहीं बता सकता है कि, यह केवल यह बता सकता है कि यदि वे समान कमिट ID (SHA-1) हैं । एक बार जब आप इसे स्क्वैश करते हैं, तो आपको पुरानी शाखा git branch -D topicको हटाने के लिए इसे जबरन हटाने के लिए गिट को बताने की आवश्यकता होती है।
ब्रायन कैंपबेल

66

इस तरह से मैं आमतौर पर कोड को पुश करने से पहले एक ही प्रतिबद्ध में कई कॉमेट्स को संयोजित करने का पालन करता हूं।

इसे प्राप्त करने के लिए, मेरा सुझाव है कि आप GIT द्वारा प्रदान की गई ' स्क्वैश ' अवधारणा का उपयोग करें ।

नीचे दिए गए चरणों का पालन करें।

1) Git रिबेस मैं मास्टर (के बजाय मास्टर आप भी एक विशिष्ट उपयोग कर सकते हैं प्रतिबद्ध)

रिबेज इंटरेक्टिव एडिटर खोलें, जहां यह आपके सभी कमिट्स को दिखाएगा। मूल रूप से जहां आपको उन कमिटों की पहचान करने की आवश्यकता होती है, जिन्हें आप एकल कमिट में मर्ज करना चाहते हैं।

कल्पना कीजिए कि ये आपके कमिट हैं और एडिटर में कुछ इस तरह दिखाए गए हैं।

pick f7f3f6d changed my name a bit    
pick 310154e updated README formatting and added blame   
pick a5f4a0d added cat-file  

यह ध्यान रखना महत्वपूर्ण है कि ये कमेंट्स विपरीत क्रम में सूचीबद्ध हैं, जैसा कि आप आमतौर पर लॉग कमांड का उपयोग करके देखते हैं। मतलब, पुरानी प्रतिबद्धता पहले दिखाई जाएगी।

2) अंतिम प्रतिबद्ध परिवर्तनों के लिए 'पिक' को 'स्क्वैश' में बदलें । ऐसा कुछ नीचे दिखाया गया है। ऐसा करने पर, आपके पिछले 2 कमिट पहले वाले में विलय हो जाएंगे।

pick f7f3f6d changed my name a bit         
squash 310154e updated README formatting and added blame   
squash a5f4a0d added cat-file

यदि आप संयोजन करने के लिए बहुत सारे हैं, तो आप संक्षिप्त रूप का भी उपयोग कर सकते हैं:

p f7f3f6d changed my name a bit         
s 310154e updated README formatting and added blame   
s a5f4a0d added cat-file

संपादन उपयोग 'i' के लिए, यह संपादक को प्रविष्टि के लिए सक्षम करेगा। ध्यान रखें कि सबसे अधिक (सबसे पुरानी) प्रतिबद्धता को समाप्त नहीं किया जा सकता क्योंकि इसके साथ संयोजन करने के लिए कोई पिछली प्रतिबद्धता नहीं है। तो इसे चुनना होगा या 'पी'। डालने मोड से बाहर निकलने के लिए 'Esc' का उपयोग करें।

3) अब, निम्नलिखित कमांड के साथ संपादक को बचाएं: wq

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

आशा है कि यह आपकी मदद करेगा।


5
शायद यह दूसरों के लिए स्पष्ट है लेकिन, जब आप "गिट रिबास -आई" कहते हैं, तो आपको यह भी निर्दिष्ट करने की आवश्यकता है कि आप किस पर शुरू करते हैं। जब मैंने इस उदाहरण का अनुसरण करने की कोशिश की तो यह कुछ नहीं था। इसलिए, इस उदाहरण में, यह "git rebase -i xxxxx" होगा जहां xxxxx f7f3f6d कालानुक्रमिक रूप से पहले सही है। एक बार जब मुझे पता चला कि सब कुछ ठीक उसी तरह से काम कर रहा है जैसा कि ऊपर वर्णित है।
nukeguy

यह दिलचस्प है @nukeguy, मेरे पास कोई मुद्दा नहीं था जो एक विशिष्ट प्रतिबद्ध को निर्दिष्ट नहीं करता था। यह सिर्फ वहाँ क्या था डिफ़ॉल्ट रूप से।
जेक्रोक्स

शायद @nukeguy की तरह, git rebase -i HEAD~2मुझे शुरू करने के लिए एक उपयोगी जगह थी। तब यह उत्तर मददगार था। फिर, मैंने git statusदिखाया कि "आपकी शाखा और 'मूल / सुविधा / xyz' ने अलग-अलग मोड़ लिया है, और क्रमशः 1 और 1 अलग-अलग हिट करता है।" तो मैं करने के लिए आवश्यक git push origin feature/xyz --force-with-leaseदेखें stackoverflow.com/a/59309553/470749 और freecodecamp.org/forum/t/...
रयान

11

पहला : कुछ भी नहीं आपको बताता है कि प्रति धक्का प्रति शाखा केवल एक प्रतिबद्ध है: एक धक्का एक प्रकाशन तंत्र है जो आपको एक दूरस्थ रेपो पर एक स्थानीय इतिहास (यानी आवागमन का एक संग्रह) प्रकाशित करने की अनुमति देता है।

दूसरा : git merge --no-ff topical_xFeatureपुश करने से पहले एक एकल विषय के रूप में आपके विषय के काम पर मास्टर रिकॉर्ड करेगा master
(इस तरह, आप topical_xFeatureआगे के प्रस्तावों के लिए चारों ओर रहते हैं , कि आप masterअगले मर्ज पर एक नई प्रतिबद्धता के रूप में रिकॉर्ड कर सकते हैं - एफएफ।
यदि छुटकारा पाना topical_xFeatureलक्ष्य है, तो git merge --squashसही विकल्प है, जैसा कि ब्रायन कैंपबेल में विस्तृत है। का जवाब है ।)


मुझे लगता है कि --squash, वह नहीं --no-ffजो आप चाहते हैं। --no-ffएक मर्ज कमेटी बनाएंगे, लेकिन इसमें से सभी कमिट्स भी छोड़ देंगे topical_xFeature
ब्रायन कैंपबेल

@ ब्रायन: मैं सहमत हूं और आपके जवाब को बढ़ा-चढ़ाकर पेश कर रहा हूं, लेकिन मैंने सबसे पहले सोचा था कि -नहीं- ff विकल्प क्योंकि मैं topical_featureब्रांच को इधर-उधर रखना चाहता था , और सिर्फ masterब्रांच पर एक ही कमिट दर्ज करना चाहता था ।
VonC

8

मास्टर शाखा में स्विच करें और सुनिश्चित करें कि आप अद्यतित हैं।

git checkout master

git fetch मूल / मास्टर पर अपडेट प्राप्त करने के लिए यह आवश्यक हो सकता है (आपके git config पर निर्भर करता है)

git pull

मास्टर शाखा में सुविधा शाखा को मर्ज करें।

git merge feature_branch

मूल की स्थिति के लिए मास्टर शाखा को रीसेट करें।

git reset origin/master

Git अब सभी परिवर्तनों को अस्थिर परिवर्तन मानता है। हम इन परिवर्तनों को एक प्रतिबद्ध के रूप में जोड़ सकते हैं। जोड़ रहा है। अनटैक की गई फ़ाइलों को भी जोड़ देगा।

git add --all

git commit

रेफरी: https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit


3
इस उत्तर का पालन करना आसान है और वास्तव में कल्पना करना आसान है।
jokab

6
  1. पहले चुनें कि आप किसके लिए चाहते हैं कि सब कुछ बाद में आए।

    git reflog
    5976f2b HEAD@{0}: commit: Fix conflicts
    80e85a1 HEAD@{1}: commit: Add feature
    b860ddb HEAD@{2}: commit: Add something
    
  2. अपने चयनित सिर पर रीसेट करें (मैंने चुना है HEAD@{2})

    git reset b860ddb --soft
    
  3. git status (बस तसल्ली के लिए)

  4. अपनी नई कमिट जोड़ें

    git commit -m "Add new commit"
    

नोट: HEAD@{0}& HEAD@{1}क्या अब 1 कमिट में मर्ज हो गए हैं, यह कई कमिट्स के लिए भी किया जा सकता है।

git reflog फिर से प्रदर्शित होना चाहिए:

git reflog
5976f2b HEAD@{0}: commit: Add new commit
b860ddb HEAD@{1}: commit: Add something

0

एक उपकरण एक में कई Commits स्वचालित करने के लिए

जैसा कि कोंडल कोलीपाका कहते हैं । "गिट रिबेस-आई" का उपयोग करना

"गिट रिबेस" का तर्क

"Git rebase -i" का उपयोग करते समय, git चालू .it / rebase-merge डायरेक्टरी में git-rebase-todo फाइल जेनरेट करता है, और फिर git एडिटर को इनवॉइस करता है कि यूजर्स को प्रोसेसिंग के लिए git-rebase-todo फाइल को एडिट करने दें। तो उपकरण को पूरा करने की जरूरत है:

  1. हमारे द्वारा प्रदान किए गए टूल में गिट एडिटर को संशोधित करें;
  2. उपकरण git-rebase-todo फ़ाइल को संसाधित करता है।

डिफ़ॉल्ट गिट संपादक को संशोधित करें

git config core.editor #show current default git editor
git config --local --replace-all  core.editor NEW_EDITOR # set the local branch using NEW_EDITOR as git editor

इसलिए, टूल को git एडिटर को बदलने और git-rebase-todo फाइल को प्रोसेस करने की आवश्यकता है। नीचे अजगर का उपयोग कर उपकरण:

#!/usr/bin/env python3
#encoding: UTF-8

import os
import sys

def change_editor(current_file):
    os.system("git config --local --replace-all  core.editor " + current_file) # Set current_file as git editor
    os.system("git rebase -i") # execute the "git rebase -i" and will invoke the python file later with git-rebase-todo file as argument
    os.system("git config --local --replace-all core.editor vim") # after work reset the git editor to default

def rebase_commits(todo_file):
    with open(todo_file, "r+") as f:
        contents = f.read() # read git-rebase-todo's content
        contents = contents.split("\n")
        first_commit = True
        f.truncate()
        f.seek(0)
        for content in contents:
            if content.startswith("pick"):
                if first_commit:
                    first_commit = False
                else:
                    content = content.replace("pick", "squash") # replace the pick to squash except for the first pick
            f.write(content + "\n")

def main(args):
    if len(args) == 2:
        rebase_commits(args[1]) # process the git-rebase-todo
    else:
        change_editor(os.path.abspath(args[0])) # set git editor

if __name__ == "__main__":
    main(sys.argv)

Ref: https://liwugang.github.io/2019/12/30/git_commits_en.html


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