git - गिट के साथ एक नई शाखा में सबसे हालिया प्रतिबद्धताओं को ले जाएं




git-branch branching-and-merging (8)

गिट स्टैश का उपयोग करके बहुत आसान समाधान

अगर:

  • आपका प्राथमिक उद्देश्य master वापस रोल करना है, और
  • आप परिवर्तन रखना चाहते हैं लेकिन विशेष रूप से व्यक्तिगत प्रतिबद्धता की परवाह नहीं करते हैं, और
  • आपने अभी तक धक्का नहीं दिया है, और
  • आप यह आसान होना चाहते हैं और अस्थायी शाखाओं और अन्य सिरदर्द से जटिल नहीं हैं

फिर निम्नलिखित बहुत आसान है (शाखा master पर शुरू करना जिसमें तीन गलत कार्य हैं):

git reset HEAD~3
git stash
git checkout newbranch
git stash pop

लाइन नंबर से यह क्या करता है

  1. पिछले तीन काम (और उनके संदेश) को master करने के लिए पूर्ववत करता है, लेकिन सभी काम करने वाली फाइलों को बरकरार रखता है
  2. हेड ~ 3 राज्य के बराबर master वर्किंग पेड़ बनाने, सभी कामकाजी फ़ाइल परिवर्तनों को दूर करता है
  3. मौजूदा शाखा newbranch स्विच newbranch
  4. आपकी कार्यशील निर्देशिका में किए गए परिवर्तनों को लागू करता है और छिद्र को साफ़ करता है

अब आप सामान्य रूप से git add और git commit उपयोग कर सकते हैं। सभी नए newbranch को नए newbranch जोड़ा जाएगा।

यह क्या नहीं करता है

  • यह आपके पेड़ को छेड़छाड़ करने वाली यादृच्छिक अस्थायी शाखाओं को नहीं छोड़ता है
  • यह गलत काम करता है और संदेशों को प्रतिबद्ध नहीं करता है, इसलिए आपको इस नई प्रतिबद्धता के लिए एक नया प्रतिबद्ध संदेश जोड़ना होगा

लक्ष्य

ओपी ने कहा कि लक्ष्य परिवर्तन खोने के बिना "उन कामों से पहले मास्टर को वापस लेना" था और यह समाधान ऐसा करता है।

मैं सप्ताह में कम-से-कम एक बार ऐसा करता हूं जब मैं गलती से develop बजाय master लिए नई प्रतिबद्धता करता हूं। आम तौर पर मेरे पास रोलबैक के लिए केवल एक ही प्रतिबद्धता है जिसमें लाइन 1 पर git reset HEAD^ का उपयोग git reset HEAD^ मामले में केवल एक प्रतिबद्ध रोलबैक करने का एक आसान तरीका है।

अगर आप मास्टर के अपस्ट्रीम में बदलाव को धक्का देते हैं तो ऐसा न करें

किसी और ने उन परिवर्तनों को खींच लिया होगा। यदि आप केवल अपने स्थानीय मास्टर को फिर से लिख रहे हैं, तो इसका कोई प्रभाव नहीं पड़ता है जब इसे ऊपर की ओर धकेल दिया जाता है, लेकिन सहयोगियों को एक लिखित इतिहास को दबाकर सिरदर्द हो सकता है।

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

मैं इस से कैसे जा सकता हूं

master A - B - C - D - E

इसके लिए?

newbranch     C - D - E
             /
master A - B 

सामान्य रूप में...

सिकोरा द्वारा उजागर विधि इस मामले में सबसे अच्छा विकल्प है। लेकिन कभी-कभी सबसे आसान नहीं होता है और यह एक सामान्य विधि नहीं है। एक सामान्य विधि के लिए गिट चेरी-पिक का उपयोग करें:

ओपी चाहता है कि यह प्राप्त करने के लिए, यह एक 2-चरणीय प्रक्रिया है:

चरण 1 - नोट जो मास्टर से आता है जो आप एक newbranch पर चाहते हैं

निष्पादित

git checkout master
git log

ध्यान दें कि (3 कहें) हैश आप newbranch पर चाहते हैं। यहां मैं उपयोग करूंगा:
सी प्रतिबद्ध: 9aa1233
डी प्रतिबद्ध: 453ac3d
ई प्रतिबद्ध: 612ecb3

नोट: आप पहले सात अक्षर या पूरे प्रतिबद्ध हैश का उपयोग कर सकते हैं

चरण 2 - उन्हें newbranch पर newbranch

git checkout newbranch
git cherry-pick 612ecb3
git cherry-pick 453ac3d
git cherry-pick 9aa1233

या (गिट 1.7.2+ पर, श्रेणियों का उपयोग करें)

git checkout newbranch
git cherry-pick 612ecb3~1..9aa1233

गिट चेरी-पिक उन तीनों को न्यूब्रैंच पर लागू करता है।


सबसे पिछले जवाब खतरनाक रूप से गलत हैं!

यह मत करो:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

अगली बार जब आप git rebase git pull --rebase (या git pull --rebase ) git pull --rebase उन 3 newbranch चुपचाप newbranch से हटा दिया जाएगा! (नीचे स्पष्टीकरण देखें)

इसके बजाए ऐसा करें:

git reset --keep HEAD~3
git checkout -t -b newbranch
git cherry-pick [email protected]{2}
  • सबसे पहले यह 3 सबसे हालिया --keep को छोड़ देता है ( --keep की तरह है --keep लेकिन सुरक्षित, असम्बद्ध परिवर्तनों को फेंकने के बजाए विफल रहता है)।
  • फिर यह newbranch बंद कर newbranch
  • फिर यह चेरी-पिक्स उन 3 को वापस newbranch पर ले newbranch । चूंकि अब उन्हें किसी शाखा द्वारा संदर्भित नहीं किया जाता है, यह गिट के reflog का उपयोग करके करता है: [email protected]{2} वह प्रतिबद्धता है जिसे HEAD 2 ऑपरेशंस पहले संदर्भित करता था, यानी हम 1 से पहले। newbranch जांच की गई और 2. git reset इस्तेमाल किया गया 3 कामों को त्यागने के लिए git reset करें।

चेतावनी: डिफ़ॉल्ट रूप से रीफ्लॉग सक्षम है, लेकिन यदि आपने इसे मैन्युअल रूप से अक्षम कर दिया है (उदाहरण के लिए "बेयर" गिट रिपोजिटरी का उपयोग करके), आप git reset --keep HEAD~3 चलाने के बाद 3 को वापस ले पाएंगे git reset --keep HEAD~3

एक विकल्प जो रिफ्लॉग पर भरोसा नहीं करता है:

# newbranch will omit the 3 most recent commits.
git checkout -b newbranch HEAD~3
git branch --set-upstream-to=oldbranch
# Cherry-picks the extra commits from oldbranch.
git cherry-pick ..oldbranch
# Discards the 3 most recent commits from oldbranch.
git branch --force oldbranch oldbranch~3

(यदि आप चाहें तो आप @{-1} - पूर्व चेक आउट शाखा - oldbranch बजाय oldbranch )।

तकनीकी स्पष्टीकरण

पहले उदाहरण के बाद 3 git rebase क्यों बंद कर देगा? ऐसा इसलिए है क्योंकि कोई तर्क के साथ git rebase डिफ़ॉल्ट रूप से --fork-point विकल्प को सक्षम बनाता है, जो स्थानीय --fork-point का उपयोग करता है ताकि अपस्ट्रीम शाखा को मजबूती से धक्का दिया जा सके।

मान लीजिए कि जब आपने एम 1, एम 2, एम 3 को नियुक्त किया है तो आपने मूल / मास्टर को ब्रांच किया है, फिर तीन ने खुद को बनाया है:

M1--M2--M3  <-- origin/master
         \
          T1--T2--T3  <-- topic

लेकिन फिर कोई व्यक्ति एम 2 को हटाने के लिए बल-पुशिंग मूल / मास्टर द्वारा इतिहास को फिर से लिखता है:

M1--M3'  <-- origin/master
 \
  M2--M3--T1--T2--T3  <-- topic

अपने स्थानीय रिफ्लॉग का उपयोग करके, git rebase देख सकता है कि आपने मूल / मास्टर शाखा के पहले अवतार से फोर्क किया है, और इसलिए एम 2 और एम 3 काम करता है वास्तव में आपकी विषय शाखा का हिस्सा नहीं है। इसलिए यह उचित रूप से मानता है कि एम 2 को अपस्ट्रीम शाखा से हटा दिया गया था, इसलिए जब आप विषय शाखा का पुन: उपयोग कर लेते हैं तो आप इसे अपनी विषय शाखा में नहीं चाहते हैं:

M1--M3'  <-- origin/master
     \
      T1'--T2'--T3'  <-- topic (rebased)

यह व्यवहार समझ में आता है, और आम तौर पर पुन: प्रयास करते समय करना सही होता है।

तो कारण निम्न आदेश विफल:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch

ऐसा इसलिए है क्योंकि वे गलत स्थिति में रिफ्लॉग छोड़ देते हैं। गिट ने newbranch को एक संशोधन में अपस्ट्रीम शाखा से बाहर newbranch रूप में देखा है जिसमें 3 काम शामिल हैं, फिर reset --hard को हटाने के लिए अपस्ट्रीम के इतिहास को फिर से लिखता है, और अगली बार जब आप git rebase चलाते हैं तो यह उन्हें किसी भी अन्य प्रतिबद्धता की तरह छोड़ देता है अपस्ट्रीम से हटा दिया गया है।

लेकिन इस विशेष मामले में हम चाहते हैं कि उन 3 को विषय शाखा के हिस्से के रूप में माना जाए। इसे प्राप्त करने के लिए, हमें पहले संशोधन में अपस्ट्रीम को फोर्क करने की आवश्यकता है जिसमें 3 काम शामिल नहीं हैं। यही सुझाव है कि मेरे सुझाए गए समाधान करते हैं, इसलिए वे दोनों सही स्थिति में रीफ्लॉग छोड़ देते हैं।

अधिक जानकारी के लिए, गिट रिबेस और गिट मर्ज-बेस डॉक्स में --fork-point की परिभाषा देखें।


1) एक नई शाखा बनाएं, जो आपके सभी परिवर्तनों को new_branch में ले जाती है।

git checkout -b new_branch

2) फिर पुरानी शाखा में वापस जाओ।

git checkout master

3) गिट रिबेस करें

git rebase -i <short-hash-of-B-commit>

4) फिर खुले संपादक में पिछले 3 प्रतिबद्ध जानकारी शामिल हैं।

...
pick <C's hash> C
pick <D's hash> D
pick <E's hash> E
...

5) उन सभी 3 कामों में drop लिए pick बदलें। फिर संपादक को सहेजें और बंद करें।

...
drop <C's hash> C
drop <D's hash> D
drop <E's hash> E
...

6) अब मौजूदा शाखा ( master ) से पिछले 3 काम हटा दिए गए हैं। शाखा शाखा से पहले + हस्ताक्षर के साथ शाखा को बलपूर्वक धक्का दें।

git push origin +master

आप यह कर सकते हैं यह सिर्फ 3 सरल कदम है जिसका मैंने उपयोग किया था।

1) नई शाखा बनाएं जहां आप हालिया अपडेट करना चाहते हैं।

git branch <branch name>

2) नई शाखा पर प्रतिबद्धता के लिए हालिया कमेटी आईडी खोजें।

git log

3) उस आईडी को कॉपी करें कि नोट करें कि हालिया प्रतिबद्ध सूची शीर्ष पर होती है। तो आप अपनी प्रतिबद्धता पा सकते हैं। आप इसे संदेश के माध्यम से भी पाते हैं।

git cherry-pick d34bcef232f6c...

आप प्रतिबद्ध आईडी की कुछ सीमा भी प्रदान कर सकते हैं।

git cherry-pick d34bcef...86d2aec

अब आपका काम पूरा हो गया। यदि आपने सही आईडी और सही शाखा चुनी है तो आप सफलता प्राप्त करेंगे। तो इससे पहले सावधान रहें। अन्यथा एक और समस्या हो सकती है।

अब आप अपना कोड दबा सकते हैं

git push


इतिहास को फिर से लिखने के बिना ऐसा करने के लिए (यानी यदि आपने पहले से ही काम किया है):

git checkout master
git revert <commitID(s)>
git checkout -b new-branch
git cherry-pick <commitID(s)>

तब दोनों शाखाओं को बल के बिना धकेल दिया जा सकता है!


बस इस स्थिति में था:

Branch one: A B C D E F     J   L M  
                       \ (Merge)
Branch two:             G I   K     N

मैंने प्रदर्शन किया:

git branch newbranch 
git reset --hard HEAD~8 
git checkout newbranch

मुझे उम्मीद थी कि प्रतिबद्धता मैं सिर होगी, लेकिन प्रतिबद्धता एल अब है ...

इतिहास में सही स्थान पर उतरने के लिए सुनिश्चित करना सुनिश्चित करें कि प्रतिबद्धता के हैश के साथ काम करना आसान हो

git branch newbranch 
git reset --hard #########
git checkout newbranch

यह उन्हें तकनीकी अर्थ में "स्थानांतरित" नहीं करता है लेकिन इसका एक ही प्रभाव है:

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)




branching-and-merging