कई छोटे लोगों में बड़े गिट रिपॉजिटरी को विभाजित करें


86

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

तो, क्या कोई रेपो को तोड़ने में मदद कर सकता है जो इस तरह दिख सकता है:

MyHugeRepo/
   .git/
   DIR_A/
   DIR_B/
   DIR_1/
   DIR_2/

दो रिपॉजिटरी जो इस तरह दिखते हैं:

MyABRepo/
   .git
   DIR_A/
   DIR_B/

My12Repo/
   .git
   DIR_1/
   DIR_2/

मैंने इस पिछले प्रश्न में निर्देशों का पालन करने की कोशिश की है, लेकिन यह वास्तव में फिट नहीं होता है जब कई निर्देशिकाओं को एक अलग रेपो ( अलग-अलग गिट रिपॉजिटरी में उपनिर्देशिका ) में रखने की कोशिश की जाती है।


11
जब आप किसी उत्तर से खुश होते हैं, तो कृपया इसे स्वीकृत के रूप में चिह्नित करें।
बेन फॉवलर

1
बाहर (बजाय एकाधिक निर्देशिका को दूर करने के लिए देख के, कुछ परियोजनाओं पर कठिन हो सकता है) एक नई रेपो में एकाधिक (नेस्टेड) निर्देशिका विभाजित करने के लिए देख किसी के लिए, इस सवाल का जवाब मेरे लिए मददगार था: stackoverflow.com/a/19957874/164439
thaddeusmt

जवाबों:


80

यह MyABRepo सेटअप करेगा; आप निश्चित रूप से इसी तरह My12Repo कर सकते हैं।

git clone MyHugeRepo/ MyABRepo.tmp/
cd MyABRepo.tmp
git filter-branch --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 

.It / refs / मूल / refs / सिर / मास्टर के लिए एक संदर्भ। आप इसे हटा सकते हैं:

cd ..
git clone MyABRepo.tmp MyABRepo

अगर सब ठीक हो गया तो आप MyABRepo.tmp को हटा सकते हैं।


यदि किसी कारण से आपको .it-rewrite से संबंधित कोई त्रुटि मिलती है, तो आप यह प्रयास कर सकते हैं:

git clone MyHugeRepo/ MyABRepo.tmp/
cd MyABRepo.tmp
git filter-branch -d /tmp/git-rewrite.tmp --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 
cd ..
git clone MyABRepo.tmp MyABRepo

इसके बजाय अस्थायी निर्देशिका के रूप में /tmp/git-rewrite.tmp बनाएंगे और उपयोग करेंगे .git-rewrite। स्वाभाविक रूप से, आप इसके बजाय अपनी इच्छानुसार किसी भी मार्ग को स्थानापन्न कर सकते हैं /tmp/git-rewrite.tmp, जब तक कि आपके पास लिखित अनुमति है, और निर्देशिका पहले से मौजूद नहीं है।


'git फ़िल्टर-शाखा' manpage में ऊपर उल्लिखित अंतिम चरण के बजाय पुन: लिखित भंडार का एक नया क्लोन बनाने की सिफारिश की गई है।
जकूब नारबस्की

मैंने यह कोशिश की और एक त्रुटि मिली जब यह अंत में .it-rewrite फ़ोल्डर को हटाने की कोशिश कर रहा था।
माइक मैक

-d <पथ-पर-दूसरे-भौतिक-डिस्क> ने मेरे लिए काम किया और स्ट्रीट-एमवी 'विफलताओं को --ट्री-फिल्टर के भीतर समाप्त कर दिया।
वर्टिगो

क्या आपके पास एक विचार है कि बहुत पहले कमिट कैसे प्राप्त करें, यदि यह एक बहिष्कृत पथ से संबंधित है (जैसे DIR_A, उदाहरण के लिए)।
बिटमास्क

1
मुझे इस बात का पूरा अहसास नहीं था filter-branch। जिन लोगों को जानकारी नहीं है, वे इतिहास को फिर से लिखते हैं, इसलिए यदि आपने ऐसा करने के बाद रेपो को आगे बढ़ाने की योजना बनाई है, तो प्रतिबद्ध हैश अब अलग होगा और यह काम नहीं करेगा।
thaddeusmt

10

आप इस्तेमाल कर सकते हैं git filter-branch --index-filterके साथ git rm --cachedअपने मूल भंडार के क्लोन / प्रतियां से अवांछित निर्देशिका नष्ट करने के लिए।

उदाहरण के लिए:

trim_repo() { : trim_repo src dst dir-to-trim-out...
  : uses printf %q: needs bash, zsh, or maybe ksh
  git clone "$1" "$2" &&
  (
    cd "$2" &&
    shift 2 &&

    : mirror original branches &&
    git checkout HEAD~0 2>/dev/null &&
    d=$(printf ' %q' "$@") &&
    git for-each-ref --shell --format='
      o=%(refname:short) b=${o#origin/} &&
      if test -n "$b" && test "$b" != HEAD; then 
        git branch --force --no-track "$b" "$o"
      fi
    ' refs/remotes/origin/ | sh -e &&
    git checkout - &&
    git remote rm origin &&

    : do the filtering &&
    git filter-branch \
      --index-filter 'git rm --ignore-unmatch --cached -r -- '"$d" \
      --tag-name-filter cat \
      --prune-empty \
      -- --all
  )
}
trim_repo MyHugeRepo MyABRepo DIR_1 DIR_2
trim_repo MyHugeRepo My12Repo DIR_A DIR_B

आपको प्रत्येक रिपॉजिटरी की गैर-पंजीकृत शाखाओं या टैगों को मैन्युअल रूप से हटाने की आवश्यकता होगी (जैसे यदि आपके पास एक सुविधा-एक्स-फॉर-एबी शाखा थी, तो आप शायद इसे "12" रिपॉजिटरी से हटाना चाहते हैं)।


1
:बाश में एक टिप्पणी चरित्र नहीं है। आपको #इसके बजाय उपयोग करना चाहिए ।
डेनिथ

4
@ डायनेथ, :एक पारंपरिक अंतर्निहित कमांड ( पोसिक्स में भी निर्दिष्ट ) है। यह बैश में शामिल है , लेकिन यह एक टिप्पणी नहीं है। मैंने विशेष रूप से इसे प्राथमिकता में इस्तेमाल किया #क्योंकि सभी गोले #सभी संदर्भों में एक टिप्पणी परिचयकर्ता के रूप में नहीं लेते हैं (उदाहरण के लिए INTERACTIVE_COMMENTS विकल्प सक्षम किए बिना इंटरैक्टिव zsh )। का उपयोग करके :पूरे पाठ को किसी भी इंटरैक्टिव शेल में चिपकाने के साथ-साथ एक स्क्रिप्ट फ़ाइल में सहेजने के लिए उपयुक्त बनाता है।
क्रिस जॉन्सन

1
प्रतिभाशाली! केवल समाधान मैंने पाया है कि सभी शाखाओं को बरकरार रखता है
फेलिक्स

अजीब, मेरे लिए इसके साथ बंद हो जाता है git remote rm origin, हमेशा 1. वापस जाने के लिए लगता है जो इसलिए मैं प्रतिस्थापित &&द्वारा ;इस लाइन के लिए।
कियान

अच्छा, $ @ जब जरूरत से ज्यादा दो dirs के लिए काम करता है। जब मैं फोन करता हूं git remote add origin $TARGET; git push origin master
वाल्टर ए

6

Git_split प्रोजेक्ट एक साधारण स्क्रिप्ट है जो वास्तव में वही है जो आप खोज रहे हैं। https://github.com/vangorra/git_split

अपने स्वयं के स्थान पर git निर्देशिकाओं को अपने स्वयं के रिपॉजिटरी में बदल दें। कोई सबट्री फनी बिजनेस नहीं। यह स्क्रिप्ट आपके git रिपॉजिटरी में एक मौजूदा डायरेक्टरी लेगी और उस डायरेक्टरी को अपने स्वयं के स्वतंत्र रिपॉजिटरी में बदल देगी। साथ ही, यह आपके द्वारा प्रदान की गई निर्देशिका के लिए संपूर्ण परिवर्तन इतिहास की नकल करेगा।

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to push to.


1

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

cp -R MyHugeRepo MyABRepo
cp -R MyHugeRepo My12Repo

cd MyABRepo/
rm -Rf DIR_1/ DIR_2/
git add -A
git commit -a

इसके लिए मुझे जरूरत थी।

संपादित करें: बेशक, ए और बी निर्देशिका के खिलाफ My12Repo में एक ही बात की गई थी। इसने मुझे दो रिपॉजिट दिए, समान इतिहास के साथ मैंने अनचाहे डायरेक्टरीज को डिलीट कर दिया।


1
यह प्रतिबद्ध इतिहास को संरक्षित नहीं करता है।
डेनिथ

ऐसा कैसे? मेरे पास अभी भी सभी इतिहास हैं, यहां तक ​​कि हटाई गई फ़ाइलों के लिए भी।
माइक मैक

1
चूँकि आपकी आवश्यकता यह नहीं थी कि रेपो ए को रेपो बी का कभी भी अस्तित्व में नहीं होना चाहिए, मुझे लगता है कि यह (केवल कम प्रभावित बी) के रिकॉर्ड को छोड़ना एक उपयुक्त समाधान है। एक छोटे से इतिहास को डुप्लिकेट करने से बेहतर है।
स्टीव क्ले
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.