सवाल पृथक गिट भंडार में उपनिर्देशिका को अलग करें (स्थानांतरित करें)


मेरे पास एक Git भंडार जिसमें कई उपनिर्देशिकाएं शामिल हैं। अब मुझे पता चला है कि उपनिर्देशिका में से एक दूसरे से असंबंधित है और इसे एक अलग भंडार से अलग किया जाना चाहिए।

उपनिर्देशिका के भीतर फ़ाइलों का इतिहास रखते हुए मैं यह कैसे कर सकता हूं?

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

बस इसे स्पष्ट करने के लिए, मेरे पास निम्न संरचना है:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

लेकिन मुझे इसके बजाय यह पसंद आएगा:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/

1595
2017-12-11 13:57


मूल


यह अब तुच्छ है git filter-branch नीचे मेरा जवाब देखें। - jeremyjjbrown
@jeremyjjbrown सही है। अब ऐसा करना मुश्किल नहीं है लेकिन Google पर सही उत्तर ढूंढना मुश्किल है क्योंकि सभी पुराने उत्तर परिणामों पर हावी हैं। - Agnel Kurian


जवाब:


अद्यतन करें: यह प्रक्रिया इतनी आम है कि गिट टीम ने इसे एक नए उपकरण के साथ बहुत आसान बना दिया है, git subtree। यहाँ देखें: पृथक गिट भंडार में उपनिर्देशिका को अलग करें (स्थानांतरित करें)


आप अपने भंडार को क्लोन करना चाहते हैं और फिर उपयोग करना चाहते हैं git filter-branch सबकुछ चिह्नित करने के लिए, लेकिन उपनिर्देशिका जो आप अपने नए रेपो में कचरा-संग्रहित करना चाहते हैं।

  1. अपने स्थानीय भंडार को क्लोन करने के लिए:

    git clone /XYZ /ABC
    

    (नोट: भंडार हार्ड लिंक का उपयोग करके क्लोन किया जाएगा, लेकिन यह कोई समस्या नहीं है क्योंकि हार्ड-लिंक्ड फ़ाइलों को स्वयं में संशोधित नहीं किया जाएगा - नए बनाए जाएंगे।)

  2. अब, हम उन रोचक शाखाओं को संरक्षित करते हैं जिन्हें हम फिर से लिखना चाहते हैं, और उसके बाद वहां धक्का देने से बचने के लिए उत्पत्ति को हटा दें और यह सुनिश्चित करने के लिए कि पुराने कामों को मूल द्वारा संदर्भित नहीं किया जाएगा:

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    या सभी दूरस्थ शाखाओं के लिए:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. अब आप उन टैग को भी हटाना चाहेंगे जिनके पास उपप्रोजेक्ट से कोई संबंध नहीं है; आप इसे बाद में भी कर सकते हैं, लेकिन आपको फिर से अपने रेपो को फिर से शुरू करने की आवश्यकता हो सकती है। मैंने ऐसा नहीं किया और एक मिला WARNING: Ref 'refs/tags/v0.1' is unchanged सभी टैग के लिए (क्योंकि वे सब सबप्रोजेक्ट से असंबंधित थे); इसके अतिरिक्त, ऐसे टैग को हटाने के बाद और जगह पुनः प्राप्त की जाएगी। जाहिरा तौर पर git filter-branch अन्य टैग को फिर से लिखने में सक्षम होना चाहिए, लेकिन मैं इसे सत्यापित नहीं कर सका। यदि आप सभी टैग को हटाना चाहते हैं, तो उपयोग करें git tag -l | xargs git tag -d

  4. फिर फ़िल्टर-शाखा का उपयोग करें और अन्य फ़ाइलों को बाहर करने के लिए रीसेट करें, ताकि उन्हें काटा जा सके। चलो भी जोड़ें --tag-name-filter cat --prune-empty खाली प्रतिबद्धताओं को हटाने और टैग को फिर से लिखने के लिए (ध्यान दें कि इसे अपने हस्ताक्षर को पट्टी करना होगा):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    या वैकल्पिक रूप से, केवल हेड शाखा को फिर से लिखना और टैग और अन्य शाखाओं को अनदेखा करना:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. फिर बैकअप रीफ्लॉग हटाएं ताकि अंतरिक्ष को वास्तव में पुनः दावा किया जा सके (हालांकि अब ऑपरेशन विनाशकारी है)

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
    

    और अब आपके पास एबीसी उप-निर्देशिका का स्थानीय गिट भंडार है जो इसके सभी इतिहास संरक्षित है।

नोट: अधिकांश उपयोगों के लिए, git filter-branch वास्तव में जोड़ा पैरामीटर होना चाहिए -- --all। हाँ यह वास्तव में है --अंतरिक्ष--  all। यह आदेश के लिए अंतिम पैरामीटर होने की जरूरत है। जैसा कि मातली ने पाया, यह प्रोजेक्ट शाखाओं और टैग को नए रेपो में शामिल करता है।

संपादित करें: नीचे टिप्पणियों के विभिन्न सुझावों को सुनिश्चित करने के लिए शामिल किया गया था, उदाहरण के लिए, कि भंडार वास्तव में संकुचित है (जो हमेशा पहले मामला नहीं था)।


1155
2017-07-25 17:10



बहुत अच्छा जवाब। धन्यवाद! और वास्तव में जो कुछ मैं चाहता था उसे पाने के लिए, मैंने फ़िल्टर-शाखा कमांड में "- --all" जोड़ा। - matli
तुमको क्यों चाहिए --no-hardlinks? एक हार्डलिंक को हटाने से दूसरी फ़ाइल प्रभावित नहीं होगी। गिट ऑब्जेक्ट्स भी अपरिवर्तनीय हैं। केवल तभी यदि आप मालिक / फ़ाइल अनुमतियों को बदलना चाहते हैं --no-hardlinks। - vdboor
एक अतिरिक्त कदम जो मैं अनुशंसा करता हूं वह "गिट रिमोट आरएम मूल" होगा। अगर मैं गलत नहीं हूं, तो यह मूल भंडार पर वापस जाने से रोक देगा। - Tom
जोड़ने के लिए एक और आदेश filter-branch है --prune-empty, अब खाली खाली करने के लिए। - Seth Johnson
पॉल की तरह, मैं अपने नए रेपो में प्रोजेक्ट टैग नहीं चाहता था, इसलिए मैंने इसका उपयोग नहीं किया -- --all। मैं भी भाग गया git remote rm origin, तथा git tag -l | xargs git tag -d से पहले git filter-branch आदेश। यह मेरा संकुचित है .git 60 एम से ~ 300 के लिए निर्देशिका। ध्यान दें कि आकार घटाने के लिए मुझे इन दोनों आदेशों को चलाने की आवश्यकता है। - saltycrane


आसान तरीका ™

यह पता चला है कि यह एक आम और उपयोगी प्रथा है कि गिट के अधिकारियों ने इसे वास्तव में आसान बना दिया है, लेकिन आपके पास गिट (> = 1.7.11 मई 2012) का एक नया संस्करण होना चाहिए। देखें अनुबंध नवीनतम गिट कैसे स्थापित करें के लिए। इसके अलावा, एक है वास्तविक दुनिया का उदाहरण में पूर्वाभ्यास नीचे।

  1. पुराने रेपो तैयार करें

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    ध्यान दें:  <name-of-folder> प्रमुख या पिछला अक्षर नहीं होना चाहिए। उदाहरण के लिए, नाम का फ़ोल्डर subproject के रूप में पारित किया जाना चाहिए subproject, नहीं ./subproject/

    विंडोज उपयोगकर्ताओं के लिए नोट: जब आपकी फ़ोल्डर गहराई> 1 है, <name-of-folder> * निक्स शैली फ़ोल्डर विभाजक होना चाहिए (/)। उदाहरण के लिए, नाम का फ़ोल्डर path1\path2\subproject के रूप में पारित किया जाना चाहिए path1/path2/subproject

  2. नया रेपो बनाएं

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. नए रेपो को जिथूब या कहीं भी लिंक करें

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. साफ - सफाई, अगर चाहा

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    ध्यान दें: यह भंडार में सभी ऐतिहासिक संदर्भ छोड़ देता है। देखें अनुबंध नीचे अगर आप वास्तव में पासवर्ड करने के बारे में चिंतित हैं या आपको अपने फ़ाइल आकार को कम करने की आवश्यकता है .git फ़ोल्डर।

...

पूर्वाभ्यास

ये हैं उपरोक्त के समान कदम, लेकिन उपयोग करने के बजाय मेरे भंडार के लिए मेरे सटीक कदमों का पालन करना <meta-named-things>

नोड में जावास्क्रिप्ट ब्राउज़र मॉड्यूल को लागू करने के लिए मेरे पास एक प्रोजेक्ट है:

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

मैं एक फ़ोल्डर को विभाजित करना चाहता हूं, btoa, एक अलग गिट भंडार में

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

अब मेरे पास एक नई शाखा है, btoa-only, जो केवल के लिए प्रतिबद्ध है btoa और मैं एक नया भंडार बनाना चाहता हूं।

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

इसके बाद मैं गिथब या बिटबकेट पर एक नया रेपो बना सकता हूं, या जो कुछ भी जोड़ता है वह जोड़ता है origin (बीटीडब्ल्यू, "उत्पत्ति" केवल एक सम्मेलन है, कमांड का हिस्सा नहीं - आप इसे "रिमोट-सर्वर" या जो भी चाहें उसे कॉल कर सकते हैं)

git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master

शुभ दिन!

ध्यान दें: यदि आपने एक रेपो बनाया है README.md, .gitignore तथा LICENSE, आपको पहले खींचने की आवश्यकता होगी:

git pull origin -u master
git push origin -u master

अंत में, मैं बड़े रिपो से फ़ोल्डर को हटाना चाहता हूं

git rm -rf btoa

...

अनुबंध

ओएस एक्स पर नवीनतम गिट

गिट का नवीनतम संस्करण प्राप्त करने के लिए:

brew install git

ओएस एक्स के लिए ब्रू प्राप्त करने के लिए:

http://brew.sh

उबंटू पर नवीनतम गिट

sudo apt-get update
sudo apt-get install git
git --version

अगर यह काम नहीं करता है (आपके पास उबंटू का एक पुराना संस्करण है), कोशिश करें

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

अगर वह अभी भी काम नहीं करता है, तो कोशिश करें

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

टिप्पणियों से rui.araujo के लिए धन्यवाद।

अपने इतिहास को साफ़ करना

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

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

इसके बाद आप जांच सकते हैं कि आपकी फ़ाइल या फ़ोल्डर अब गिट इतिहास में दिखाई नहीं दे रहा है

git log -- <name-of-folder> # should show nothing

हालांकि, आप github को हटाए "धक्का" नहीं कर सकते हैं और जैसे। यदि आप कोशिश करते हैं तो आपको एक त्रुटि मिलेगी और आपको करना होगा git pull इससे पहले कि आप कर सकते हैं git push - और फिर आप अपने इतिहास में सबकुछ रखने के लिए वापस आ गए हैं।

तो यदि आप "उत्पत्ति" से इतिहास को हटाना चाहते हैं - जिसका मतलब है कि इसे गितब, बिटबकेट आदि से हटाना है - आपको रिपो को हटाना होगा और रेपो की एक प्रतिलिपि प्रतिलिपि बनाना होगा। लेकिन रुकें - अभी और है! - यदि आप वास्तव में किसी पासवर्ड से छुटकारा पाने के बारे में चिंतित हैं या ऐसा कुछ आपको बैकअप को छीनने की आवश्यकता होगी (नीचे देखें)।

निर्माण .git छोटे

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

तो अगर आप वास्तव में करना चाहते हैं कचरा खाली करो सेवा मेरे क्लोन आकार को कम करें एक रेपो के तुरंत आपको यह सब अजीब सामान करना है:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

उस ने कहा, मैं इन चरणों को निष्पादित करने की अनुशंसा नहीं करता जबतक कि आपको पता न हो कि आपको आवश्यकता है - बस अगर आपने गलत उपनिर्देशिका को छीन लिया है, तो पता है? जब आप रेपो को दबाते हैं तो बैकअप फ़ाइलों को क्लोन नहीं किया जाना चाहिए, वे सिर्फ आपकी स्थानीय प्रतिलिपि में होंगे।

श्रेय


1124
2018-06-05 13:15



git subtree अभी भी 'contrib' फ़ोल्डर का हिस्सा है और सभी distros पर डिफ़ॉल्ट रूप से स्थापित नहीं है। github.com/git/git/blob/master/contrib/subtree - onionjake
@krlmlr sudo chmod + x /usr/share/doc/git/contrib/subtree/git-subtree.sh sudo ln -s /usr/share/doc/git/contrib/subtree/git-subtree.sh / usr / lib / गिट-कोर / गिट-सबट्री उबंटू 13.04 पर सक्रिय करने के लिए - rui.araujo
यदि आपने सार्वजनिक भंडार में पासवर्ड डाला है, तो आपको पासवर्ड बदलना चाहिए, इसे सार्वजनिक रिपो से हटाने की कोशिश न करें और उम्मीद है कि किसी ने इसे देखा नहीं है। - Miles Rout
ऐसा लगता है कि सामग्री के साथ एक नया रेपो बनाते हैं ABC/, लेकिन नए रेपो में फ़ोल्डर नहीं है ABC/ सवाल के रूप में, खुद ही। आप यह कैसे करेंगे? - woojoo666
यह समाधान इतिहास को संरक्षित नहीं करता है। - Cœur


पॉल का जवाब / एबीसी युक्त एक नया भंडार बनाता है, लेकिन / XYZ के भीतर / एबीसी को नहीं हटाता है। निम्न आदेश / XBC के भीतर से / एबीसी हटा देगा:

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

बेशक, इसे पहले 'क्लोन - नो-हार्डलिंक्स' रिपोजिटरी में जांचें, और रीसेट, जीसी और प्रिंस कमांड पॉल सूचियों के साथ इसका पालन करें।


131
2017-10-19 21:10



वह बनाना git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" --prune-empty HEAD और यह होगा बहुत और तेज। इंडेक्स-फ़िल्टर इंडेक्स पर काम करता है जबकि पेड़-फ़िल्टर को चेकआउट और चरण करना होता है हर प्रतिबद्धता के लिए सब कुछ। - fmarc
कुछ मामलों में भंडार XYZ के इतिहास को गड़बड़ कर रहा है ... केवल एक साधारण "आरएम-आरएफ एबीसी; जीआईटी आरएम -आर एबीसी; गिट प्रतिबद्ध - एबीसी ने अपने स्वयं के रेपो में '' ज्यादातर लोगों के लिए बेहतर काम किया है। - Evgeny
यदि आप इसे एक से अधिक बार करते हैं, तो शायद आप इस कमांड पर -f (बल) का उपयोग करना चाहते हैं, उदाहरण के लिए, अलग होने के बाद दो निर्देशिकाओं को निकालने के लिए। अन्यथा आपको "नया बैकअप नहीं बनाया जा सकता"। - Brian Carlton
यदि आप कर रहे हैं --index-filter विधि, आप इसे भी बनाना चाहते हैं git rm -q -r -f, ताकि प्रत्येक आमंत्रण प्रत्येक फ़ाइल के लिए एक पंक्ति मुद्रित नहीं करेगा। - Eric Naeseth
मैं पॉल के जवाब को संपादित करने का सुझाव दूंगा, केवल इसलिए कि पॉल बहुत गहन है। - Erik Aronesty


मैंने पाया है कि नए भंडार से पुराने इतिहास को सही तरीके से हटाने के लिए, आपको इसके बाद थोड़ा और काम करना होगा filter-branch कदम।

  1. क्लोन और फ़िल्टर करें:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. पुराने इतिहास के हर संदर्भ को हटा दें। "उत्पत्ति" आपके क्लोन का ट्रैक रख रही थी, और "मूल" वह जगह है जहां फ़िल्टर-शाखा पुरानी चीजें बचाती है:

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. अब भी, आपका इतिहास एक पैकफाइल में फंस सकता है जो fsck स्पर्श नहीं करेगा। इसे टुकड़ों में फाड़ें, एक नया पैकफाइल बनाएं और अप्रयुक्त वस्तुओं को हटा दें:

    git repack -ad
    

वहाँ है इसका एक स्पष्टीकरण में फिल्टर शाखा के लिए मैनुअल


94
2018-06-09 15:41



मुझे लगता है जैसे somethink git gc --aggressive --prune=now अभी भी गुम है, है ना? - Albert
@ अल्बर्ट रेकैक कमांड उस पर ख्याल रखता है, और कोई ढीली वस्तु नहीं होगी। - Josh Lee
सिर्फ repack मेरे लिए काम नहीं किया, गिट जीसी करने की जरूरत है - jsvnm
हाँ, git gc --aggressive --prune=now नए रेपो को कम कर दिया - Tomek Wyderka
सरल और सुरुचिपूर्ण। धन्यवाद! - Marco Pelegrini


संपादित करें: बैश स्क्रिप्ट जोड़ा गया।

यहां दिए गए उत्तरों ने मेरे लिए आंशिक रूप से काम किया; कैश में बहुत सी बड़ी फाइलें बनीं। अंततः क्या काम किया (Freenode पर #git में घंटों के बाद):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

पिछले समाधानों के साथ, भंडार आकार लगभग 100 एमबी था। यह इसे 1.7 एमबी तक लाया। शायद यह किसी की मदद करता है :)


निम्नलिखित बैश स्क्रिप्ट कार्य को स्वचालित करती है:

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

38
2017-08-20 14:11





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

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

21
2018-03-22 20:55



इसने एकदम जादू की तरह काम किया। उपर्युक्त उदाहरण में YOUR_SUBDIR वह उपनिर्देशिका है जिसे आप रखना चाहते हैं, बाकी सब कुछ हटा दिया जाएगा - J.T. Taylor
आप टिप्पणी के आधार पर अद्यतन। - jeremyjjbrown
यह सवाल का जवाब नहीं देता है। दस्तावेज़ों से यह कहता है The result will contain that directory (and only that) as its project root. और वास्तव में यह आपको मिलेगा, यानी मूल परियोजना संरचना संरक्षित नहीं है। - NicBright
@NicBright क्या आप गलत तरीके से दिखाने के लिए प्रश्न में XYZ और ABC के साथ अपनी समस्या का वर्णन कर सकते हैं? - Adam
@jeremyjjbrown क्लोन रेपो का पुन: उपयोग करना संभव है और एक नया रेपो का उपयोग नहीं करना है, यानी मेरा प्रश्न यहां stackoverflow.com/questions/49269602/... - Qiulang


अद्यतन करें: गिट-सबट्री मॉड्यूल इतना उपयोगी था कि गिट टीम ने इसे कोर में खींच लिया और इसे बनाया git subtree। यहाँ देखें: पृथक गिट भंडार में उपनिर्देशिका को अलग करें (स्थानांतरित करें)

इसके लिए गिट-सबट्री उपयोगी हो सकता है

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (बहिष्कृत)

http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/


19
2017-08-06 15:26



गिट-सबट्री अब गिट का हिस्सा है, हालांकि यह contrib पेड़ में है, इसलिए डिफ़ॉल्ट रूप से हमेशा स्थापित नहीं है। मुझे पता है कि यह होमब्रू गिट फॉर्मूला द्वारा स्थापित है, लेकिन इसके मैन पेज के बिना। apenwarr इस प्रकार अपने संस्करण अप्रचलित कहते हैं। - echristopherson


यहां एक छोटा सा संशोधन है CoolAJ86की "द इज़ी वे ™" उत्तर विभाजित करने के लिए एकाधिक उप फ़ोल्डर्स (हम कहते हैं sub1तथा sub2) एक नए गिट भंडार में।

आसान तरीका ™ (एकाधिक उप फ़ोल्डर्स)

  1. पुराने रेपो तैयार करें

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    ध्यान दें:  <name-of-folder> प्रमुख या पिछला अक्षर नहीं होना चाहिए। उदाहरण के लिए, नाम का फ़ोल्डर subproject के रूप में पारित किया जाना चाहिए subproject, नहीं ./subproject/

    विंडोज उपयोगकर्ताओं के लिए नोट: जब आपकी फ़ोल्डर गहराई> 1 है, <name-of-folder> * निक्स शैली फ़ोल्डर विभाजक होना चाहिए (/)। उदाहरण के लिए, नाम का फ़ोल्डर path1\path2\subproject के रूप में पारित किया जाना चाहिए path1/path2/subproject। इसके अलावा उपयोग नहीं करते हैं mvआदेश लेकिन move

    अंतिम नोट: मूल उत्तर के साथ अद्वितीय और बड़ा अंतर स्क्रिप्ट की दूसरी पंक्ति है "git filter-branch..."

  2. नया रेपो बनाएं

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. नए रेपो को जिथूब या कहीं भी लिंक करें

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. साफ - सफाई, अगर चाहा

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    ध्यान दें: यह भंडार में सभी ऐतिहासिक संदर्भ छोड़ देता है। देखें अनुबंध मूल उत्तर में यदि आप वास्तव में पासवर्ड करने के बारे में चिंतित हैं या आपको अपने फ़ाइल आकार को कम करने की आवश्यकता है .git फ़ोल्डर।


13
2018-04-17 05:12



यह मामूली संशोधन के साथ मेरे लिए काम किया। क्योंकि मेरा sub1 तथा sub2 फ़ोल्डर्स प्रारंभिक संस्करण के साथ मौजूद नहीं थे, मुझे अपना संशोधित करना पड़ा --tree-filter निम्नानुसार लिपि: "mkdir <name-of-folder>; if [ -d sub1 ]; then mv <sub1> <name-of-folder>/; fi"। दूसरे के लिए filter-branch आदेश मैंने <sub1> <sub2> के साथ बदल दिया, <name-of-folder> के छोड़े गए निर्माण, और शामिल हैं -f बाद filter-branch मौजूदा बैकअप की चेतावनी को ओवरराइड करने के लिए। - pglezen
यह काम नहीं करता है अगर गिट में इतिहास के दौरान उपनिवेशों में से कोई भी बदल गया है। यह कैसे हल किया जा सकता है? - nietras
@nietras rogerdpack के जवाब देखें। इन अन्य उत्तरों में सभी जानकारी पढ़ने और अवशोषित करने के बाद मुझे ढूंढने में थोड़ी देर लग गई। - Adam


मूल प्रश्न XYZ / एबीसी / (* फाइलें) एबीसी / एबीसी / (* फाइलें) बनना चाहता है। अपने कोड के लिए स्वीकृत उत्तर को लागू करने के बाद, मैंने देखा कि यह वास्तव में एक्सबीजेड / एबीसी / (* फाइलें) को एबीसी / (* फाइलों) में बदल देता है। फ़िल्टर-शाखा मैन पेज भी कहता है,

परिणाम में वह निर्देशिका होगी (और केवल वह) इसकी परियोजना रूट के रूप में। "

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

I lost contiuity after filter-branch

प्रश्न का मेरा जवाब तब भंडार की 2 प्रतियां बनाना है और प्रत्येक फ़ोल्डर में मैन्युअल रूप से उस फ़ोल्डर को हटा देना है जिसे आप रखना चाहते हैं। मैन पेज मुझे इसके साथ बैक करता है:

[...] [इस आदेश] का उपयोग करने से बचें यदि आपकी समस्या को ठीक करने के लिए एक साधारण एकल प्रतिबद्धता पर्याप्त होगी


11
2017-07-25 10:01



मुझे उस ग्राफ की शैली पसंद है। क्या मैं पूछ सकता हूं कि आप किस उपकरण का उपयोग कर रहे हैं? - Slipp D. Thompson
मैक के लिए टॉवर। मुझे वास्तव में यह पसंद है। मैक के लिए अपने आप में स्विच करने लायक है। - MM.
हाँ, हालांकि मेरे मामले में, मेरे subfoldered targetdir गया था नाम बदला किसी बिंदु पर और git filter-branch बस इसे एक दिन कहा जाता है, नाम से पहले किए गए सभी कामों को हटा देता है! चौंकाने वाला, इस बात पर विचार करते हुए कि गिट कितनी अच्छी तरह से चीजों को ट्रैक करने और व्यक्तिगत सामग्री के हिस्सों के प्रवासन पर नजर रखता है! - Jay Allen
ओह, अगर कोई भी खुद को एक ही नाव में पाता है, तो यहां मैंने जो आदेश दिया था, वह यहां है। उसे मत भूलना git rm कई तर्क लेता है, इसलिए प्रत्येक फ़ाइल / फ़ोल्डर के लिए इसे चलाने का कोई कारण नहीं है: BYEBYE="dir/subdir2 dir2 file1 dir/file2"; git filter-branch -f --index-filter "git rm -q -r -f --cached --ignore-unmatch $BYEBYE" --prune-empty -- --all - Jay Allen


जोड़ने के लिए पॉल का जवाब, मैंने पाया कि अंत में अंतरिक्ष को पुनर्प्राप्त करने के लिए, मुझे हेड को एक स्वच्छ भंडार में धक्का देना है और यह .git / ऑब्जेक्ट / पैक निर्देशिका के आकार को कम करता है।

अर्थात।

$ mkdir ... एबीसी.git
$ सीडी ... एबीसी.git
$ गिट इनिट - बेयर

जीसी प्रुन के बाद, यह भी करें:

$ गिट पुश ... एबीसी.git हेड

फिर आप कर सकते हैं

$ गिट क्लोन ... एबीसी.git

और एबीसी / .git का आकार कम हो गया है

दरअसल, भंडार को साफ करने के लिए धक्का के साथ कुछ समय लेने वाले कदम (जैसे गिट जीसी) की आवश्यकता नहीं है, यानी .:

$ गिट क्लोन - नो-हार्डलिंक्स / एक्सवाईजेड / एबीसी
$ गिट फिल्टर-शाखा - सब्सडायरेक्टरी-फ़िल्टर एबीसी हेड
$ गिट रीसेट - हार्ड
$ गिट पुश ... एबीसी.git हेड

7
2017-11-12 13:22





उचित तरीका अब निम्नलिखित है:

git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

गिटहब अब भी है छोटा लेख ऐसे मामलों के बारे में।

लेकिन पहले अपनी निर्देशिका को अलग करने के लिए अपने मूल रेपो को क्लोन करना सुनिश्चित करें (क्योंकि यह सभी फाइलों और अन्य निर्देशिकाओं को हटा देगा और आपको उनके साथ काम करने की आवश्यकता होगी)।

तो आपका एल्गोरिदम होना चाहिए:

  1. अपने रिमोट रेपो को दूसरी निर्देशिका में क्लोन करें
  2. का उपयोग करते हुए git filter-branch कुछ उपनिर्देशिका के तहत केवल फाइल छोड़ दी, नए रिमोट पर धक्का
  3. अपने मूल रिमोट रेपो से इस उपनिर्देशिका को हटाने के लिए प्रतिबद्ध बनाएं

5
2017-09-19 18:46