कई गिट रिपोजिटरी को मिलाकर


207

मान लीजिए कि मुझे एक सेटअप मिला है जो कुछ इस तरह दिखता है

phd/code/
phd/figures/
phd/thesis/

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

cd phd/code
git commit 
cd ../figures
git commit

यह (अब) सिर्फ प्रदर्शन करने के लिए अच्छा होगा

cd phd
git commit

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

cd phd
git init
git add [[everything that's already in my other repositories]]

लेकिन यह एक लाइनर की तरह प्रतीत नहीं होता है। क्या इसमें कुछ भी है gitजो मेरी मदद कर सकता है?


इस महान दृष्टिकोण पर भी विचार करें: stackoverflow.com/questions/1425892/…
जोहान Sjöberg

इस पर भी विचार करें: saintgimp.org/2013/01/22/…
ptim

Join-git-repos.py स्क्रिप्ट मास्टर शाखाओं के साथ प्रत्येक अगर आप अलग खजाने है एक अच्छा काम करता है, कि आप संयोजित करना चाहते हैं।
मार्क

जवाबों:


149

यहाँ एक समाधान मैंने यहाँ दिया है :

  1. पहले अपनी पीएचडी निर्देशिका का पूरा बैकअप लें: मैं नहीं चाहता कि आपकी कड़ी मेहनत के वर्षों को खोने के लिए जिम्मेदार ठहराया जाए! ;-)

    $ cp -r phd phd-backup
    
  2. की सामग्री को ले जाने phd/codeके लिए phd/code/code, और इतिहास को ठीक ताकि ऐसा लगता है कि यह हमेशा किया गया है (इस का उपयोग करता है Git के फिल्टर शाखा आदेश):

    $ cd phd/code
    $ git filter-branch --index-filter \
        'git ls-files -s | sed "s#\t#&code/#" |
         GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
         git update-index --index-info &&
         mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
    
  3. की सामग्री के लिए एक ही phd/figuresहै और phd/thesis(बस की जगह codeके साथ figuresऔर thesis)।

    अब आपकी निर्देशिका संरचना इस तरह दिखनी चाहिए:

    phd
      |_code
      |    |_.git
      |    |_code
      |         |_(your code...)
      |_figures
      |    |_.git
      |    |_figures
      |         |_(your figures...)
      |_thesis
           |_.git
           |_thesis
                |_(your thesis...)
    
  4. फिर रूट डायरेक्टरी में git रिपॉजिटरी बनाएं, इसमें सब कुछ खींचें और पुरानी रिपॉजिटरी निकालें।

    $ cd phd
    $ git init
    
    $ git pull code
    $ rm -rf code/code
    $ rm -rf code/.git
    
    $ git pull figures --allow-unrelated-histories
    $ rm -rf figures/figures
    $ rm -rf figures/.git
    
    $ git pull thesis --allow-unrelated-histories
    $ rm -rf thesis/thesis
    $ rm -rf thesis/.git
    

    अंत में, अब आपके पास वह होना चाहिए जो आप चाहते थे:

    phd
      |_.git
      |_code
      |    |_(your code...)
      |_figures
      |    |_(your figures...)
      |_thesis
           |_(your thesis...)
    

इस प्रक्रिया का एक अच्छा पक्ष यह है कि यह गैर-संस्करणित फ़ाइलों और निर्देशिकाओं को जगह में छोड़ देगा ।

उम्मीद है की यह मदद करेगा।


हालांकि चेतावनी का केवल एक शब्द: यदि आपकी codeनिर्देशिका में पहले से ही एक codeउपनिर्देशिका या फ़ाइल है, तो चीजें बहुत गलत हो सकती हैं (समान रूप से figuresऔर thesisनिश्चित रूप से)। यदि ऐसा है, तो इस पूरी प्रक्रिया को करने से पहले उस निर्देशिका या फ़ाइल का नाम बदलें:

$ cd phd/code
$ git mv code code-repository-migration
$ git commit -m "preparing the code directory for migration"

और जब प्रक्रिया पूरी हो जाती है, तो इस अंतिम चरण को जोड़ें:

$ cd phd
$ git mv code/code-repository-migration code/code
$ git commit -m "final step for code directory migration"

बेशक, अगर codeउपनिर्देशिका या फ़ाइल संस्करणित नहीं है , तो mvइसके बजाय का उपयोग करें git mv, और git commitएस के बारे में भूल जाओ ।


13
इस स्निपेट के लिए धन्यवाद - यह बिल्कुल वही हुआ जिसकी मुझे आवश्यकता थी (एक बार जब मैंने मैक ओएस एक्स के लिए हिसाब लगाया था "" t "का प्रसंस्करण नहीं किया गया था (मुझे इसके बजाय ^ V ^ I का उपयोग करना पड़ा था)।
क्रेग ट्रेडर

6
मैं इसे पहले काम करने के लिए नहीं मिला और अंततः एक अन्य पुराने संदेश बोर्ड पर समस्या का समाधान पाया। अंतिम पंक्ति में, मुझे फ़ाइल नामों के उद्धरणों को इस तरह रखना था: mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEADऔर फिर इसने बहुत काम किया!
जोरिन

3
फंकी फिल्टर-ब्रांच कमांड git की फिल्टर-ब्रांच मैन पेज से है। आपको यह कहना चाहिए कि जैसे: ए) इसे सही ढंग से जिम्मेदार ठहराया जाना चाहिए बी) मैं इस तरह के आदेश को सिर्फ इसलिए नहीं चलाऊंगा क्योंकि किसी ने, यहां तक ​​कि उच्च प्रतिष्ठा के साथ, इसे स्टैकऑवरफ्लो पर पोस्ट किया था। यह जानकर कि मैं मनुष्य के पृष्ठों से हूँ।
tymtam

5
ध्यान रहे! MacOS X sed के GNU एक्सटेंशन का उपयोग नहीं करता है, इसलिए यह अनुक्रम \ t को नहीं जानता है। परिणाम एक गड़बड़ इतिहास है! मेरा समाधान एक स्क्रिप्ट फ़ाइल में कोड को लिखना था, इसमें एक वास्तविक <TAB> चरित्र लिखना था। टर्मिनल से, एक टैब ctrl + v दबाकर प्रवेश किया जा सकता है और फिर एक <TAB> लिखा जा सकता है। मैंने क्रेग के समाधान की कोशिश नहीं की है
गिल वेगलियाच

4
देखो (2)! यह भी ध्यान दें कि यदि कुछ फाइलों या निर्देशिकाओं में हाइफ़न ('-') हैं तो sed कमांड विफल हो जाएगी। उस स्थिति में आप इसे 's ~ \ t ~ & code / ~' जैसी किसी चीज़ से प्रतिस्थापित कर सकते हैं। यहाँ, उसी तर्क को लागू करते हुए, नामों में '~' के लिए देखें
गिल वेगलियाच

75

git-stitch-repogit-fast-export --all --date-orderकमांड-लाइन पर दिए गए git रिपॉजिटरी के आउटपुट को प्रोसेस करेगा , और इसके लिए उपयुक्त एक स्ट्रीम git-fast-importबनाएगा जो एक नया कमेटी बनाएगा जिसमें एक नए कमिट ट्री में सभी कमेंट्स होंगे जो सभी सोर्स रिपॉजिटरी के इतिहास का सम्मान करते हैं।


33
उह, यह एक थर्ड-पार्टी टूल है, गिट का हिस्सा नहीं है ... :-)
अरस्तू पगलतज़िस

1
दरअसल, अब आप मुझे बताएं :) ओह ठीक है, मुझे लगता है कि मुझे एक दिन CPAN पैकेज कैसे स्थापित करना सीखना था ...
रॉबर्टसन

1
उस आदेश को इंगित करने के लिए धन्यवाद। बस इसका उपयोग SVN से Git में कुछ रिपोज को स्थानांतरित करने में मदद करने के लिए कर रहा है।
13

1
शाखाएँ / मर्ज होने पर चेतावनी काम नहीं कर सकती है! से Git-मिसरा-रेपो । पेज: "Git-मिसरा-रेपो खजाने कि एक रेखीय इतिहास (कोई मर्ज के) के साथ पूरी तरह से काम करता है .. सिलाई एल्गोरिथ्म संस्करण 0.06 बनाना चाहिए में जोड़ा करने के लिए सुधार खजाने होने के साथ काम करने के लिए उपयुक्त है शाखाएँ और विलय। "
ब्रायन पी।

6
यह एक बाहरी स्क्रिप्ट है, इसका उत्तर बहुत छोटा है और वास्तव में मददगार नहीं है, इस स्क्रिप्ट में मर्ज कमिट की समस्या है, बहुत से लोग पर्ल या सीपीएएन को नहीं संभालेंगे और इसका उत्तर में अच्छी तरह से समझाया नहीं गया है। तो ... -1, सॉरी।
हरलान डोबरेव

20

शायद, बस (पिछले उत्तर के समान, लेकिन सरल आदेशों का उपयोग करके) अलग-अलग पुराने रिपॉजिटरी में से प्रत्येक में एक कमिट करता है जो कंटेंट को एक उप-नाम वाले उपडिर में स्थानांतरित करता है, जैसे:

$ cd phd/code
$ mkdir code
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean:
$ git mv * code/
$ git commit -m "preparing the code directory for migration"

और फिर तीन अलग-अलग रिपोज़ को एक नए में मर्ज करके, जैसे कि स्मथ कर:

$ cd ../..
$ mkdir phd.all
$ cd phd.all
$ git init
$ git pull ../phd/code
...

फिर आप अपने इतिहास को बचाएंगे, लेकिन एकल रेपो के साथ आगे बढ़ेंगे।


यह ठीक है, लेकिन यदि आप एक रेपो को दूसरे में विलय कर रहे हैं (यानी पीएचडी पहले से मौजूद रेपो से खाली नहीं था) तो अगर कोड निर्देशिका में सबफ़ोल्डर्स के समान नाम वाले फ़ोल्डर थे, तो आप समस्याओं को 'गिट' के रूप में मारेंगे। / phd / code 'ऑर्निगल रास्तों के साथ सभी आवागमन को खींचता है और केवल अंत में यह mv कमिट लागू करता है।
tymtam

1
@ टायमेक: लेकिन यह अभी भी उस स्थिति में काम करेगा, बिना किसी समस्या के। अच्छी बात यह होगी कि इतिहास में पथ "सही" नहीं होंगे (नए पथ के अनुरूप)।
इम्ज़ - इवान ज़खरीशेव

19

आप सबट्री मर्ज की रणनीति आजमा सकते हैं । यह आपको रेपो बी को रेपो ए में विलय करने देगा। इससे अधिक फायदा git-filter-branchयह है कि इसके लिए आपको रेपो ए (एसएचए 1 रकम को तोड़ना) के अपने इतिहास को फिर से लिखने की आवश्यकता नहीं है।


लिंक काम नहीं करता है और यह इतिहास को संरक्षित नहीं करेगा, क्या ऐसा होगा?
tymtam

3
@Tymek (सुरक्षा भंग के बाद kernel.org के कुछ हिस्से अभी भी नीचे हैं)। यह आने वाले रेपो बी के SHA1 को तोड़ता है लेकिन A बरकरार रहता है।
लीफ ग्रुएनवोल्ड्ट

2
यहाँ उस डॉक का एक दर्पण है जिसके लिए अब ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/howto/…
Leif Gruenwoldt

1
@LeifGruenwoldt 1 लिंक अब काम कर रहा है। और दर्पण लिंक चला गया है, आपको इसे हटा देना चाहिए मुझे लगता है।
वादिम कोटोव

9

गिट-फिल्टर-शाखा समाधान अच्छी तरह से काम करता है, लेकिन ध्यान दें कि यदि आपका git रेपो SVN आयात से आता है तो यह एक संदेश के साथ विफल हो सकता है जैसे:

Rewrite 422a38a0e9d2c61098b98e6c56213ac83b7bacc2 (1/42)mv: cannot stat `/home/.../wikis/nodows/.git-rewrite/t/../index.new': No such file or directory

इस मामले में आपको फ़िल्टर-शाखा से प्रारंभिक संशोधन को बाहर करने की आवश्यकता है - यानी HEADअंत में बदलकर [SHA of 2nd revision]..HEAD- देखें:

http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html


2
धन्यवाद! मैं अपना सिर खुजला रहा हूँ कि यह काम क्यों नहीं कर रहा था! रेपो वास्तव में एसवीएन से आया था।
आर्थर माल्सटन

1
वही त्रुटि जब मैं ऐसा करता हूं। मेरी आशाओं को पूरा किया। साथ ही, लिंक अब टूट गया है।
रयान

क्या आप इसका मतलब बता सकते हैं कि "सिर को बदलकर ..." का मतलब क्या है, मेरा रेपो एक एसवीएन आयात से आता है और मैं बिल्कुल इस समस्या का सामना कर रहा हूं, इससे बहुत मदद मिलेगी!

5

@MiniQuark समाधान ने मुझे बहुत मदद की, लेकिन दुर्भाग्य से यह खाता टैग में नहीं है जो स्रोत रिपॉजिटरी में हैं (कम से कम मेरे मामले में)। नीचे @MiniQuark उत्तर के लिए मेरा सुधार है।

  1. पहले निर्देशिका बनाएँ जिसमें रेपो और मर्ज किए गए रेपो शामिल होंगे, प्रत्येक मर्ज किए गए के लिए निर्देशिका बनाएँ।

    $ mkdir new_phd
    $ mkdir new_phd / कोड
    $ mkdir new_phd / आंकड़े
    $ mkdir new_phd / थीसिस

  2. प्रत्येक रिपॉजिटरी का एक पुल बनाएं और सभी टैग प्राप्त करें। (केवल codeउप-निर्देशिका के लिए निर्देश प्रस्तुत करना )

    $ cd new_phd / code
    $ git init
    $ git पुल ../../original_phd/code मास्टर
    $ git लाने के लिए ../../original_phd/code refs / tags / *: refin / tags / *

  3. (यह MiniQuark जवाब में बिंदु से 2 सुधार है) की सामग्री ले जाएँ new_phd/codeकरने के लिए new_phd/code/codeऔर जोड़ने के code_प्रत्येक से पहले prefeix टैग

    $ git फ़िल्टर-शाखा --index-filter 'git ls-files -s | sed "s- \ t \" * - & code / - "| GIT_INDEX_FILE = $ GIT_INDEX_FILE.new गिट अपडेट-इंडेक्स --index-info && mv $ GIT_INDEX_FILE_new $ GIT_INDEX_FILE '--tag-name-filter' sed" s " -। * - कोड _ & - "'हेड

  4. ऐसा करने के बाद फ़िल्टर-शाखा करने से पहले दो बार के रूप में कई टैग होंगे। पुराने टैग रेपो में बने रहते हैं और code_उपसर्ग वाले नए टैग जोड़े जाते हैं।

    $ git टैग
    mytag1
    code_mytag1

    मैन्युअल रूप से पुराने टैग निकालें:

    $ ls .git / refs / टैग / * | grep -v "/ code_" | xargs rm

    अन्य उपनिर्देशिकाओं के लिए दोहराएँ बिंदु 2,3,4

  5. अब हमारे पास @MiniQuark anwser बिंदु 3 में निर्देशिकाओं की संरचना है।

  6. MiniQuark anwser के बिंदु 4 के अनुसार करें, लेकिन एक पुल बनाने के बाद और .gitdir हटाने से पहले , टैग पाएं :

    $ git fetch कैटलॉग refs / टैग / *: refs / टैग / *

    जारी रखें..

यह सिर्फ एक और उपाय है। आशा है कि यह किसी की मदद करता है, इससे मुझे मदद मिली :)


5

अरस्तू पगल्टज़िस के उत्तर से गिट- स्टिक -रेपो केवल सरल, रैखिक इतिहास वाले रिपॉजिटरी के लिए काम करता है।

MiniQuark का उत्तर सभी रिपॉजिटरी के लिए काम करता है, लेकिन यह टैग और शाखाओं को संभाल नहीं पाता है।

मैंने एक प्रोग्राम बनाया जो उसी तरह से काम करता है जैसे कि मिनीक्वार वर्णन करता है, लेकिन यह एक मर्ज कमिट (एन माता-पिता के साथ) का उपयोग करता है और इन मर्ज कमिट को इंगित करने के लिए सभी टैग और शाखाओं को भी पुन: बनाता है।

उदाहरण के लिए git-merge-repos रिपॉजिटरी देखें कि इसका उपयोग कैसे किया जाए।



3

दरअसल, गिट-स्टिक-रेपो अब शाखाओं और टैगों का समर्थन करता है, जिसमें एनोटेट टैग भी शामिल हैं (मुझे लगता है कि एक बग था जो मैंने रिपोर्ट किया था, और यह ठीक हो गया)। मुझे जो उपयोगी लगा वह टैग के साथ है। चूंकि टैग कमिट से जुड़े होते हैं, और कुछ समाधान (जैसे एरिक ली का दृष्टिकोण) टैग से निपटने में विफल रहता है। आप एक आयातित टैग से एक शाखा बनाने की कोशिश करते हैं, और यह किसी भी मर्ज / चालों को पूर्ववत कर देगा और आपको वापस भेज देगा जैसे समेकित रिपॉजिटरी उस रिपॉजिटरी के समान होगा जो टैग से आया था। साथ ही, यदि आप एक से अधिक रिपॉजिटरी में एक ही टैग का उपयोग करते हैं तो समस्याएँ हैं जिन्हें आपने 'मर्ज / समेकित' किया है। उदाहरण के लिए, यदि आपके पास रेपो का A B है, तो दोनों का टैग rel_1.0 है। आप रेपो ए और रेपो बी को रेपो एबी में विलय करते हैं। चूंकि rel_1.0 टैग दो अलग-अलग कमिटों पर हैं (ए के लिए एक और बी के लिए एक), AB में कौन सा टैग दिखाई देगा या तो आयातित रेपो ए से या आयातित रेपो बी से टैग, लेकिन दोनों नहीं।

git- स्टिच-रेपो rel_1.0-A और rel_1.0-B टैग बनाकर उस समस्या को हल करने में मदद करता है। आप rel_1.0 टैग की जांच करने में सक्षम नहीं हो सकते हैं और दोनों की उम्मीद कर सकते हैं, लेकिन कम से कम आप दोनों को देख सकते हैं, और सैद्धांतिक रूप से, आप उन्हें एक सामान्य स्थानीय शाखा में मर्ज कर सकते हैं फिर उस मर्ज किए गए शाखा पर एक rel_1.0 टैग बना सकते हैं (केवल आपको मानकर विलय और स्रोत कोड नहीं बदल)। शाखाओं के साथ काम करना बेहतर है, क्योंकि आप प्रत्येक रेपो से शाखाओं की तरह स्थानीय शाखाओं में विलय कर सकते हैं। (dev-a और dev-b को एक स्थानीय देव शाखा में मिला दिया जा सकता है, जिसे बाद में उत्पत्ति के लिए धकेला जा सकता है)।


2

जो क्रम आपने सुझाया

git init
git add *
git commit -a -m "import everything"

काम करेंगे, लेकिन आप अपना प्रतिबद्ध इतिहास खो देंगे।


इतिहास खोना इतना बुरा नहीं है, लेकिन चूंकि रिपॉजिटरी मेरे खुद के काम के लिए है (यानी, यह निजी है) वहां बहुत सारी चीजें हैं जो मैं संस्करणबद्ध नहीं करना चाहता हूं या जो अभी तक संस्करण नहीं है।
विल रॉबर्टसन

1

मेनप्रोजेक्ट के भीतर एक दूसरेप्रोजेक्ट को मर्ज करना:

ए) दूसरेप्रोजेक्ट में

git fast-export --all --date-order > /tmp/secondProjectExport

बी) मेनप्रोजेक्ट में:

git checkout -b secondProject
git fast-import --force < /tmp/secondProjectExport

इस शाखा में वे सभी भारी परिवर्तन करते हैं जो आपको करने और उन्हें करने की आवश्यकता है।

सी) फिर मास्टर और दो शाखाओं के बीच एक शास्त्रीय मर्ज:

git checkout master
git merge secondProject

यह दोनों फ़ाइलों और फ़ोल्डरों को एक परियोजना में दोनों गिट परियोजनाओं के मूल में विलय कर देगा। मुझे संदेह है कि _anyone_would ऐसा होना चाहता है।
क्लिंटन

0

मैं अपना समाधान यहां भी फेंक दूंगा। यह मूल रूप से एक काफी सरल बैश स्क्रिप्ट रैपर है git filter-branch। अन्य समाधानों की तरह यह केवल मास्टर शाखाओं को माइग्रेट करता है और टैग को माइग्रेट नहीं करता है। लेकिन पूर्ण मास्टर कम हिस्टरीज़ माइग्रेट हैं और यह एक संक्षिप्त बैश स्क्रिप्ट है इसलिए उपयोगकर्ताओं के लिए समीक्षा या ट्वीक करना अपेक्षाकृत आसान होना चाहिए।

https://github.com/Oakleon/git-join-repos


0

यह बैश स्क्रिप्ट sed टैब कैरेक्टर इश्यू (उदाहरण के लिए MacOS पर) और गुम फाइलों के मुद्दे पर काम करती है।

export SUBREPO="subrepo"; # <= your subrepository name here
export TABULATOR=`printf '\t'`;
FILTER='git ls-files -s | sed "s#${TABULATOR}#&${SUBREPO}/#" |
  GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
  git update-index --index-info &&
  if [ -f "$GIT_INDEX_FILE.new" ]; then mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE; else echo "git filter skipped missing file: $GIT_INXEX_FILE.new"; fi'

git filter-branch --index-filter "$FILTER" HEAD

यह मिनिकार्क , मरियस-ब्यूटुक और रियान के पदों का एक संयोजन है । उन्हें खुश करने के लिए!

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