मैं इस अप-टू-डेट Git उपशीर्षक को धक्का क्यों नहीं दे सकता?


88

मैं उन कुछ परियोजनाओं के साथ Git उपशीर्षक का उपयोग कर रहा हूं, जिन पर मैं काम कर रहा हूं, उनके बीच कुछ आधार कोड साझा करने के लिए। आधार कोड अक्सर अद्यतन हो जाता है, और उन्नयन परियोजनाओं में से किसी में भी हो सकता है, उन सभी के साथ अंततः अद्यतन हो रहा है।

मैं एक समस्या में भाग गया हूं, जहां git रिपोर्ट करता है कि मेरा सबट्री डेट अप करने के लिए है, लेकिन पुश रिजेक्ट हो जाता है। उदाहरण के लिए:

#! git subtree pull --prefix=public/shared project-shared master
From github.com:****
* branch            master     -> FETCH_HEAD
Already up-to-date.

अगर मैं धक्का दूं, तो मुझे संदेश देना चाहिए कि धक्का देने के लिए कुछ नहीं है ... सही है? सही? :(

#! git subtree push --prefix=public/shared project-shared master
git push using:  project-shared master
To git@github.com:***
! [rejected]        72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:***'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

इसका क्या कारण रह सकता है? क्यों फेल हो रहा है धक्का?


क्यों नहीं तुम क्या git तुम्हें बता रहा है: git पुल?
एलेक्सवियन

8
Git पुल का मेरे सवाल से कोई लेना-देना नहीं है। लेकिन हां, git पुल मुझे एक अप-टू-डेट संदेश देता है, क्योंकि मूल रेपो में कुछ भी नया नहीं है।
mateusz

1
ऐसा लगता है कि आप जिस शाखा पर हैं, उसके पीछे मास्टर हेड है - उदाहरण के लिए, ... -> A -> B -> C, जहां दूरस्थ मास्टर HEAD C पर है, लेकिन आपकी वर्तमान शाखा A पर है (या ए के एक असंबद्ध कुछ वंशज)। मुझे यकीन है कि मैं अपने इतिहास को देखूंगा।
मार्क लीटन फिशर

मुझे भी यही तकलीफ़ है। मैं --rejoinसबट्री पुश को तेज करने के लिए उपयोग कर रहा हूं । जब मैं मैन्युअल रूप से सबट्री पुश के माध्यम से कदम बढ़ाता हूं, तो चल रहा है subtree split --rejoin, स्प्लिट सबट्री ब्रांच में केवल पिछले रिजनॉइन का इतिहास होता है, जब इसमें सामान्य रूप से पूरा सबट्री इतिहास होता है। मेरे लिए, यह गैर-फास्ट-फॉरवर्ड त्रुटि का तत्काल कारण है। मुझे अभी भी यकीन नहीं है कि सबट्री स्प्लिट एक छोटा इतिहास क्यों पैदा कर रहा है।
22

जवाबों:


98

मुझे इस ब्लॉग की टिप्पणी https://coderwall.com/p/ssxp5q पर उत्तर मिला

यदि आप "अपडेट को अस्वीकार कर दिया गया है क्योंकि आपकी वर्तमान शाखा की नोक पीछे है। दूरस्थ परिवर्तन (जैसे 'गिट पुल') को मर्ज करें" समस्या जब आप धक्का दे रहे हैं (जो भी कारण के कारण, जीआईटी इतिहास के साथ खराब हो रहा है) फिर आपको git कमांड को घोंसला बनाने की आवश्यकता होगी ताकि आप उसे एक धक्का दे सकें। उदाहरण के लिए, ऊपर दिया गया उदाहरण:

git push heroku `git subtree split --prefix pythonapp master`:master --force

2
मेरी मदद की! धन्यवाद।
माइकल फॉरेस्ट

8
विंडोज पर इस कमांड को कैसे चलाएं? मुझे मिल रहा हैerror: unknown option 'prefix'
पिलाउ

3
कमाल है, यह सिर्फ मेरा दिन बचा लिया :)
bpipat

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

11
मेरे पास इस बात की पहचान करने का कठिन समय था कि उत्तर में क्या संबंध herokuऔर क्या है pythonappgit push <your subtree's origin> `git subtree split --prefix=Path/to/subtree master`:master --force
हेरोकू

39

खिड़कियों पर नेस्टेड कमांड काम नहीं करता है:

git push heroku `git subtree split --prefix pythonapp master`:master --force

आप बस पहले नेस्टेड बिट चला सकते हैं:

git subtree split --prefix pythonapp master

यह (बहुत संख्या के बाद) एक टोकन लौटाएगा, जैसे

157a66d050d7a6188f243243264c765f18bc85fb956

इसका उपयोग कमांड में करें, जैसे:

git push heroku 157a66d050d7a6188f243243264c765f18bc85fb956:master --force

यह एक बहुत क्लीनर समाधान है। मेरे लिये कार्य करता है!
इंफिनिटी

जब मैं git सबट्री स्प्लिट रन करता हूं --prefix subtreedirectoryname मास्टर, मुझे घातक अस्पष्ट तर्क 'मास्टर' मिलता है: अज्ञात संशोधन या कार्यशील ट्री में नहीं पथ
Demodave

यह एक महान समाधान है, मैं बस मिल रहा git subtreeहै पहले एक आदेश नहीं है। आपके समाधान का उपयोग करने के बाद मैं अपने सभी रेपो के बजाय हरको को एक फ़ोल्डर तैनात करने में सक्षम था
pakman198

महान समाधान और समय की बचत
निश्रग शाह

29

--ontoध्वज का उपयोग करें :

# DOESN'T WORK: git subtree push --prefix=public/shared project-shared master --onto=project-shared/master

[संपादित करें: दुर्भाग्य से अंतर्निहित के लिए subtree pushआगे नहीं है , इसलिए ऑपरेशन को दो आदेशों में किया जाना है! उस काम के साथ, मैं देखता हूं कि मेरे आदेश अन्य उत्तरों में से एक में समान हैं, लेकिन स्पष्टीकरण अलग है इसलिए मैं इसे वैसे भी ले जाऊंगा।]--ontosplit

git push project-shared $(git subtree split --prefix=public/shared --onto=project-shared/master):master

या यदि आप बैश का उपयोग नहीं कर रहे हैं:

git subtree split --prefix=public/shared --onto=project-shared/master
# This will print an ID, say 0123456789abcdef0123456789abcdef,
# which you then use as follows:
git push project-shared 01234567:master

मैंने इसे समझने के लिए git-subtree स्रोत के माध्यम से घंटों समय व्यतीत किया, इसलिए मुझे आशा है कि आप इसकी सराहना करेंगे;)

subtree pushदौड़ने से शुरू होता है subtree split, जो आपके प्रतिबद्ध इतिहास को एक प्रारूप में फिर से लिखता है जिसे पुश करने के लिए तैयार होना चाहिए। जिस तरह से यह होता है, वह public/shared/किसी भी पथ के सामने से छीन लेता है, जो उसके पास होता है, और उन फ़ाइलों के बारे में कोई भी जानकारी निकालता है जो उसके पास नहीं हैं। इसका मतलब यह है कि भले ही आप गैर-स्क्वैश खींचते हों, सभी अपस्ट्रीम उप-रिपॉजिटरी कमिटमेंट की उपेक्षा की जाती है क्योंकि वे फाइलों को उनके नंगे रास्तों से नाम देते हैं। (कमिट करता है कि किसी भी फाइल को टच न करेंpublic/shared/, या मर्ज करता है जो माता-पिता के समान हैं, भी ढह जाते हैं। [संपादित करें: इसके अलावा, मैंने तब से कुछ स्क्वैश का पता लगा लिया है, इसलिए अब मैं यह सोच रहा हूं कि अगर आप नॉन-स्क्वैश किया गया है, और फिर सरलीकृत मर्ज कमिंग के रूप में वर्णित है, तो एक और उत्तर गैर-स्क्वैश पथ का चयन करने का प्रबंधन करता है और स्क्वैश किए गए पथ को छोड़ दें।]) अपशॉट है, वह सामान जो पुश करने की कोशिश करता है, जिसमें किसी ऐसे काम को सम्‍मिलित किया गया है, जिसे आप वर्तमान होस्ट रिपॉजिटरी के लिए प्रतिबद्ध किसी व्यक्ति से कर रहे हैं, लेकिन उप-रिपॉजिटरी या किसी अन्य होस्ट के माध्यम से सीधे काम करने वाले लोग भंडार।

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


2
मैं इस उत्तर को एक के रूप में सुझा रहा हूं, जिसने मुझे पहले से ही दो बार मदद की थी। और वर्णन यह है कि मुझे यह समझने की ज़रूरत है कि सही जगह पर विभाजन और धक्का कैसे काम करता है। धन्यवाद।
कामिल वोज्नियाक

2
"प्रोजेक्ट-शेयर्ड" क्या है?
कॉलिन डी

1
@ColinD "प्रोजेक्ट-शेयर्ड" रिमोट का नाम है। यह एक ऐसा नाम है जिसे आपने तब चुना होगा जब उस स्थान को लाने के लिए और धक्का देने के लिए कॉन्फ़िगर किया गया हो। आप के साथ रीमोट की एक सूची प्राप्त कर सकते हैं git remote -v
तेरह

@ इस घंटे में आपके द्वारा खर्च किए गए घंटों ने मेरा दिन बना दिया। धन्यवाद!
जून

1
मैंने पाया कि यह बग हमेशा तब होता है जब आपके उप भंडार में एक निर्देशिका होती है जिसका नाम उपसर्ग के समान होता है, उदाहरण के लिए आप उप भंडार को "libxxx" के रूप में मुख्य भंडार में जोड़ते हैं, और आपके उप भंडार में "libxxx" नामक उप निर्देशिका भी होती है। "। इस मामले में git गलत तरीके से उप रिपॉजिटरी में किए गए व्यवहार को मुख्य रिपॉजिटरी में मानते हैं और उन्हें विभाजित करने का प्रयास करते हैं। --ontoविकल्प प्रतिबद्ध है कि उप भंडार में पहले से ही कर रहे हैं की पहचान करने के लिए git मदद करता है।
कॉसिन

14

"GitHub पृष्ठों" प्रकार के ऐप के लिए, जहाँ आप g-Pages शाखा में "dist" सबट्री तैनात करते हैं, समाधान कुछ इस तरह दिख सकता है

git push origin `git subtree split --prefix dist master`:gh-pages --force

मैं इसका उल्लेख करता हूं क्योंकि यह ऊपर दिए गए हरोकू उदाहरणों से थोड़ा अलग दिखता है। आप देख सकते हैं कि मेरा "डिस्ट" फोल्डर मेरे रेपो की मास्टर ब्रांच पर मौजूद है, और फिर मैं इसे gh-pages ब्रांच में एक सबट्री के रूप में धकेलता हूं, जो मूल पर भी है।


3

मैंने पहले भी इस समस्या का सामना किया है, और यहाँ है कि मैंने इसे कैसे हल किया।

मुझे पता चला कि मेरे पास एक शाखा थी जो स्थानीय मास्टर शाखा से जुड़ी नहीं थी। यह शाखा मौजूद है और इसकी बस शून्य में लटकी हुई है। आपके मामले में, शायद इसका नाम हैproject-shared । मान लिया जाये कि यह मामला है और जब आप एक कर git branchआप एक स्थानीय देख सकते हैं project-sharedशाखा है, तो आप कर सकते हैं ' संलग्न ' अपने मौजूदा करने के लिए नए प्रतिबद्ध project-sharedएक करके शाखा:

git subtree split --prefix=public/shared --onto public-shared --branch public-shared

जिस तरह से मुझे समझ में आया है कि इस मामले में इसकी स्थानीय शाखा git subtreeनई शाखा बनाना शुरू करेगी । फिर शाखा का अर्थ है एक शाखा बनाना, जो सिर्फ पुरानी शाखा को बदल देती है ।--ontopublic-sharedpublic-shared

यह public-sharedशाखा के सभी पिछले SHA को रखेगा । अंत में, आप एक कर सकते हैं

git push project-shared project-shared:master

यह मानते हुए कि आपके पास एक project-sharedरिमोट भी है; यह स्थानीय शाखा को दूरस्थ की शाखा को शून्य project-shared शाखा में धकेल देगा ।masterproject-shared


3

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

यह कैसे काम करता है यह समझने के लिए एक उदाहरण देखें (जिसे आप आसानी से पुन: पेश कर सकते हैं)। निम्नलिखित इतिहास पर विचार करें (रेखा प्रारूप है: प्रतिबद्ध [वृक्ष] विषय):

% git log --graph --decorate --pretty=oneline --pretty="%h [%t] %s"
*   E [z] Merge branch 'master' into side-branch
|\
| * D [z] add dir/file2.txt
* | C [y] Revert "change dir/file1.txt"
* | B [x] change dir/file1.txt
|/
*   A [w] add dir/file1.txt

इस उदाहरण में, हम विभाजित कर रहे हैं dir । कमिट करता है Dऔर Eएक ही पेड़ है z, क्योंकि हम प्रतिबद्ध हैं C, जो पूर्ववत करते हैं B, इसलिए B-Cअनुक्रम इसके लिए dirकुछ भी नहीं करता है , हालांकि इसमें परिवर्तन होता है।

अब विभाजन करते हैं। पहले हम कमिट पर अलग हुए C

% git log `git subtree split -P dir C` ...
* C' [y'] Revert "change dir/file1.txt"
* B' [x'] change dir/file1.txt
* A' [w'] add dir/file1.txt

आगे हम कमिट पर बंट गए E

% git log `git subtree split -P dir E` ...
* D' [z'] add dir/file2.txt
* A' [w'] add dir/file1.txt

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

आमतौर पर आप इस त्रुटि का उपयोग करके सहन कर सकते हैं push --force, क्योंकि गिराए गए कामों में आमतौर पर महत्वपूर्ण जानकारी नहीं होगी। लंबी अवधि में, बग को ठीक करने की आवश्यकता है, इसलिए विभाजित इतिहास में वास्तव में सभी कमिट होंगे, जो स्पर्श करते हैंdir कि उम्मीद के । मैं इस बात की उम्मीद करूंगा कि इस छिपी निर्भरता के लिए माता-पिता द्वारा किए गए गहन विश्लेषण को शामिल करने के लिए यह निर्णय सही होगा।

संदर्भ के लिए, यहां मूल कोड का हिस्सा है, जो व्यवहार के लिए जिम्मेदार है।

copy_or_skip()
  ...
  for parent in $newparents; do
      ptree=$(toptree_for_commit $parent) || exit $?
      [ -z "$ptree" ] && continue
      if [ "$ptree" = "$tree" ]; then
          # an identical parent could be used in place of this rev.
          identical="$parent"
      else
          nonidentical="$parent"
      fi
  ...
  if [ -n "$identical" ]; then
      echo $identical
  else
      copy_commit $rev $tree "$p" || exit $?
  fi

क्या बग 2020-05-09 (Sat) के रूप में तय किया गया है? @ क्लीम्किन
अर्धमूर्तीकरण

बग तय हो गया है। देखें: कंट्रीब / सबट्री: फिक्स "सबट्री स्प्लिट" स्किप-मर्ज बग। github.com/git/git/commit/…
अर्धकुंवारी

0

एरिक वुड्रूफ़ के जवाब ने मेरी मदद नहीं की, लेकिन निम्नलिखित ने किया:

मैं आमतौर पर 'ssquash' विकल्प के साथ 'git सबट्री पुल' बनाता हूं। ऐसा लगता है कि इसने सामंजस्य बिठाना मुश्किल कर दिया है, इसलिए मुझे इस बार स्क्वैश किए बिना एक सबट्री पुल करने की ज़रूरत थी, कुछ संघर्षों को हल करें और फिर धक्का दें।

मुझे जोड़ना चाहिए कि स्क्वैश पुल ने किसी भी संघर्ष को प्रकट नहीं किया, मुझे बताया कि सब कुछ ठीक था।


0

एक और [सरल] समाधान यदि आप कर सकते हैं, तो एक और कमिट करके रिमोट के प्रमुख को आगे बढ़ाना है। जब आप इस उन्नत सिर को स्थानीय सबट्री में खींच लेंगे तब आप इसे फिर से धक्का दे पाएंगे।


1
यह ठीक इसी तरह है कि मैंने स्थानीय उपप्रकार के साथ सिंक से दूरस्थ रिपॉजिटरी के साथ एक ही समस्या को हल किया।
ऐसिड बेंडोराइटिस

0

आप स्थानीय परिवर्तनों को दूरस्थ सबट्री रेपो में धकेल सकते हैं

git push subtree_remote_address.git `git subtree split --prefix=subtree_folder`:refs/heads/branch --force

0

क्रिस जॉर्डन के समाधान पर आधारित विंडोज़ उपयोगकर्ताओं के लिए एक त्वरित शक्तियां

$id = git subtree split --prefix pythonapp master
Write-Host "Id is: $id"
Invoke-Expression "git push heroku $id`:master --force"

0

तो यह वही है जो मैंने लिखा था जो @entheh ने कहा था।

for /f "delims=" %%b in ('git subtree split --prefix [name-of-your-directory-on-the-file-system-you-setup] -b [name-of-your-subtree-branch]') do @set token=%%b
git push [alias-for-your-subtree] %token%:[name-of-your-subtree-branch] --force

pause

0

यह मुद्दा भी था। यहाँ मैंने क्या किया, शीर्ष उत्तरों के आधार पर:

दिया हुआ:

#! git subtree push --prefix=public/shared project-shared master
git push using:  project-shared master
To git@github.com:***
! [rejected]        72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:***'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

इसे दर्ज करें:

git push <origin> 72a6157733c4e0bf22f72b443e4ad3be0bc555ce:<branch> --force

टोकन नोट जो 'git सबट्री पुश' द्वारा आउटपुट होता है, 'git push' में उपयोग किया जाता है।

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