git - आईड - समग्र पोर्टल




गिट सबट्री-उप-अद्यतित लेकिन धक्का नहीं दे सकता है (7)

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

मैंने एक समस्या में भाग लिया है जहां गिट रिपोर्ट करता है कि मेरा उप-योग अद्यतित है, लेकिन धक्का देना अस्वीकार कर दिया जाता है। उदाहरण के लिए:

#! 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 [email protected]:***
! [rejected]        72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:***'
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.

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


"गिटहब पेज" टाइप ऐप के लिए, जहां आप एक gh-pages शाखा में "dist" subtree तैनात करते हैं, तो समाधान कुछ ऐसा दिख सकता है

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

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


आप रिमोट सबट्री रेपो में पुश स्थानीय परिवर्तन को मजबूर कर सकते हैं

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

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

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

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


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

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

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

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

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

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

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

git push project-shared project-shared:master

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


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

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

% 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 को प्रतिबद्ध किया C , जो B पूर्ववत करता है, इसलिए BC अनुक्रम 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

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

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

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

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

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

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

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





git-subtree