2012-06-06 15 views
6

के साथ बहुत सारे इतिहास के साथ मेरे पास नवीनतम संशोधन में लगभग 3500 प्रतिबद्धताओं और 30,000 विशिष्ट फ़ाइलों के साथ एक गिट भंडार है। यह कई लोगों से लगभग 3 वर्षों का काम प्रस्तुत करता है और हमें इसे सभी खुले स्रोत बनाने की अनुमति प्राप्त हुई है। मैं सिर्फ नवीनतम संस्करण की बजाय पूरे इतिहास को रिलीज़ करने के लिए कड़ी मेहनत कर रहा हूं। ऐसा करने के लिए मुझे "समय पर वापस जाना" और फ़ाइलों के शीर्ष पर लाइसेंस शीर्षलेख डालने में दिलचस्पी है जब वे बनाए जाते हैं। मेरे पास वास्तव में यह काम कर रहा है, लेकिन इसमें लगभग 3 दिन पूरी तरह से रैमडिस्क से बाहर चलते हैं, और अभी भी मैन्युअल हस्तक्षेप की आवश्यकता होती है। मुझे पता है कि यह बहुत तेज़ हो सकता है, लेकिन मेरा गिट-फू कार्य तक काफी नहीं है।कुशलतापूर्वक पुनर्लेखन (rebase -i) गिट

प्रश्न: मैं एक ही चीज़ को बहुत तेज़ी से कैसे पूरा कर सकता हूं?

क्या मैं वर्तमान में है (एक स्क्रिप्ट में स्वचालित है, लेकिन मेरे साथ सहन कृपया ...):

  1. पहचानें प्रतिबद्ध जहां एक नई फ़ाइल भंडार में जोड़ा गया था के सभी (वहाँ सिर्फ शर्मीले होते हैं इनमें से 500, Fwiw) का:

    git whatchanged --diff-filter=A --format=oneline 
    
  2. परिभाषित वातावरण चर GIT_EDITOR अपने ही स्क्रिप्ट फ़ाइल की पहली पंक्ति पर edit केवल एक ही समय के साथ pick की जगह होने के लिए (आप क्यों शीघ्र ही देखेंगे)। इस आपरेशन की मूल है:

    perl -pi -e 's/pick/edit/ if $. == 1' $1 
    
  3. प्रत्येक के लिए ऊपर git whatchanged के उत्पादन से प्रतिबद्ध, शुरू करने के लिए एक इंटरैक्टिव रिबेस आह्वान बस से पहले प्रतिबद्ध है कि फाइल कहा:

    git rebase -i decafbad001badc0da0000~1 
    

मेरा कस्टम GIT_EDITOR (वह पर्ल एक-लाइनर) pick से edit में बदलता है और हमें नई फ़ाइल में परिवर्तन करने के लिए एक खोल में गिरा दिया जाता है। एक और सरल header-inserter स्क्रिप्ट हेडर में एक ज्ञात अद्वितीय पैटर्न की तलाश करता है जिसे मैं सम्मिलित करने का प्रयास कर रहा हूं (केवल मेरे लिए ज्ञात फ़ाइल प्रकारों (*। [ChS] में))। यदि यह वहां नहीं है, तो यह फ़ाइल डालता है, और git add फ़ाइल है। इस निष्पक्ष तकनीक का कोई ज्ञान नहीं है कि वर्तमान प्रतिबद्धताओं के दौरान वास्तव में कौन सी फाइलें शामिल की गई थीं, लेकिन यह सही चीज करने और बेवकूफ होने (एक ही फाइल के खिलाफ कई बार चलाने के लिए सुरक्षित) समाप्त होती है, और यह नहीं है कि यह पूरी प्रक्रिया किसी भी तरह से बाधित है ।

इस बिंदु पर हम खुश हमने अपडेट कर दिया वर्तमान प्रतिबद्ध है, और आह्वान है कि कर रहे हैं:

git commit --amend 
    git rebase --continue 

rebase --continue महंगा हिस्सा है। चूंकि हम whatchanged के आउटपुट में प्रत्येक संशोधन के लिए एक बार git rebase -i का आह्वान करते हैं, यह बहुत अधिक रिबेजिंग है। लगभग हर समय जब इस स्क्रिप्ट को चलाता है तो "रिबेसिंग (2345/2733)" काउंटर वृद्धि को देखकर खर्च किया जाता है।

यह भी धीमा नहीं है। समय-समय पर संघर्ष होते हैं जिन्हें संबोधित किया जाना चाहिए। यह कम से कम इन मामलों में हो सकता है (लेकिन अधिक संभावना है): (1) जब एक "नई" फ़ाइल वास्तव में मौजूदा फाइल की एक प्रति होती है जिसमें इसकी पहली पंक्तियों में कुछ बदलाव किए जाते हैं (उदाहरण के लिए, #include कथन)। यह एक वास्तविक संघर्ष है लेकिन ज्यादातर मामलों में स्वचालित रूप से हल किया जा सकता है (हाँ, एक स्क्रिप्ट है जो उससे संबंधित है)। (2) जब एक फ़ाइल हटा दी जाती है। यह केवल पुष्टि करके कि यह git rm के साथ इसे हटाना चाहता है, यह छोटा रूप से हल करने योग्य है। (3) ऐसे कुछ स्थान हैं जहां ऐसा लगता है कि diff बस बुरी तरह व्यवहार करता है, उदाहरण के लिए, जहां परिवर्तन केवल खाली रेखा का जोड़ है।अन्य वैध विवादों के लिए मैन्युअल हस्तक्षेप की आवश्यकता होती है लेकिन पूरी तरह से वे सबसे बड़ी बाधा नहीं हैं। सबसे बड़ी बाधा बिल्कुल "बसने (xxxx/yyyy)" पर देखकर बस बैठी है।

अभी व्यक्तिगत विवादों को नए कामों से पुराने कामों में शुरू किया जाता है, यानी, git whatchanged के आउटपुट के शीर्ष से शुरू होता है। इसका मतलब है कि पहली बार पुनर्जन्म कल के कामों को प्रभावित करता है, और अंत में हम 3 साल पहले से रिबिटिंग करेंगे। "नए" से "पुराने" तक जाकर काउंटर-अंतर्ज्ञानी लगता है, लेकिन अब तक मुझे विश्वास नहीं है कि जब तक हम रीबेस का आह्वान करते हैं तो हम pick को edit में बदलते हैं। मुझे ऐसा करने से डर है क्योंकि संघर्ष आते हैं, और मैं संघर्ष में लहरों की एक ज्वारीय लहर से निपटना नहीं चाहता हूं, जो कि एक ही समय में सबकुछ चुकाने की कोशिश कर रहा है। शायद किसी से बचने के लिए कोई रास्ता जानता है? मैं एक के साथ आने में सक्षम नहीं हूँ।

मैंने गिट ऑब्जेक्ट्स 1 की आंतरिक कार्यप्रणाली को देखना शुरू कर दिया! ऐसा लगता है कि ऑब्जेक्ट ग्राफ़ को चलाने के लिए और अधिक कुशल तरीका होना चाहिए और केवल उन परिवर्तनों को बनाना चाहिए जिन्हें मैं बनाना चाहता हूं।

कृपया ध्यान दें कि इस भंडार जहां हम प्रभावी रूप से टैग या शाखाओं में से कोई फायदा नहीं बना एक SVN भंडार से आया है (मैं पहले से ही git filter-branch उन्हें दूर एड), तो हम एक सरल-रेखा इतिहास की सुविधा है। कोई गिट शाखा या विलय नहीं।

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

धन्यवाद!

अपडेट 2012-06-17: Blog post सभी गोरी विवरणों के साथ।

+0

यह मेरे लिए बहुत अस्पष्ट है, मैं एक बड़े पैमाने पर इतिहास फिर से लिखने के लिए आवश्यक कभी नहीं, लेकिन मैं पता है कि ऐसा करने के लिए सही उपकरण है ['गिट फ़िल्टर-शाखा'] (http://www.kernel.org/pub/software/scm/git/docs/v1.7.3/git-filter-branch.html) । मुझे खेद है कि मैं और अधिक सहायक नहीं हो सकता, मुझे उम्मीद है कि यह आपको ट्रैक पर ले जाएगा। – KurzedMetal

+0

@ कुर्ज़ेड मेटल: मैंने इस रिलीज के लिए अप्रासंगिक थे (फाइल सिस्टम) पथ को खत्म करने के लिए इस सभी रिबेजिंग को शुरू करने से पहले 'फ़िल्टर-शाखा' का उपयोग किया था। (एसवीएन भंडार जिस से इस गिट भंडार का निर्माण किया गया था, वह भी बड़ा और अधिक अपर्याप्त है।) हालांकि, आपके पास एक बिंदु हो सकता है कि 'फिल्टर-शाखा' के दौरान किए जाने वाले स्क्रिप्टिंग परिवर्तन इस सभी रिबेजिंग करने से अधिक कुशल हो सकते हैं। मैं जांच करूंगा। – jonny0x5

+0

'यह कई लोगों से लगभग 3 साल का काम प्रस्तुत करता है और हमें इसे सभी खुले स्रोत बनाने की अनुमति प्राप्त हुई है, मुझे पता है कि यह विषय है, लेकिन मैं उत्सुक हूं: पी, परियोजना का नाम/मुखपृष्ठ क्या है? – KurzedMetal

उत्तर

4

का उपयोग

git filter-branch -f --tree-filter '[[ -f README ]] && echo "---FOOTER---" >> README' HEAD 

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

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

jon (ओपी) ने महत्वपूर्ण सरलीकरण और गति के साथ लक्ष्य प्राप्त करने के लिए इस मूल पैटर्न का उपयोग किया।

git filter-branch -d /dev/shm/git --tree-filter \ 
'perl /path/to/find-add-license.pl' --prune-empty HEAD 

कुछ प्रदर्शन-महत्वपूर्ण अवलोकन।

  • रैमडिस्क निर्देशिका के लिए -d <directory> पैरामीटर इशारा का उपयोग करना (जैसे /dev/shm/foo) काफी गति में सुधार होगा।

  • अपनी अंतर्निहित भाषा सुविधाओं का उपयोग करते हुए, एक ही स्क्रिप्ट से सभी परिवर्तन करें, छोटी उपयोगिताओं (जैसे find) का उपयोग करते समय किए गए कांटे, प्रक्रिया को कई बार धीमा कर देंगे। इस से बचें:

    git filter-branch -d /dev/shm/git --tree-filter \ 
    'find . -name "*.[chS]" -exec perl /path/to/just-add-license.pl \{\} \;' \ 
    --prune-empty HEAD 
    

इस ओपी इस्तेमाल किया पर्ल स्क्रिप्ट का एक स्वच्छ संस्करण है:

#!/usr/bin/perl -w 
use File::Slurp; 
use File::Find; 

my @dirs = qw(aDir anotherDir nested/DIR); 
my $header = "Please put me at the top of each file."; 

foreach my $dir(@dirs) { 
    if (-d $dir) { 
    find(\&Wanted, $dir); 
    } 
} 

sub Wanted { 
    /\.c$|\.h$|\.S$/ or return; # *.[chS] 
    my $file = $_; 
    my $contents = read_file($file); 
    $contents =~ s/\r\n?/\n/g; # convert DOS or old-Mac line endings to Unix 
    unless($contents =~ /Please put me at the top of each file\./) { 
    write_file($file, {atomic => 1}, $header, $contents); 
    } 
} 
+0

धन्यवाद। ऐसा लगता है कि यह सही दिशा में आगे बढ़ रहा है। एक चीज जो मेरे लिए अस्पष्ट है, यह है कि यह फ़ाइल के बाद प्रत्येक प्रतिबद्धता के लिए '--- FOOTER --- 'पेश नहीं करता है। जहां 'ट्री-फिल्टर' के "स्मारक" में गिट आकृति केवल उस आदेश को चलाने के लिए होती है? उदाहरण के लिए, 'गिट फ़िल्टर-शाखा-एफ - ट्री-फ़िल्टर' इको "मैंने भाग लिया" >>/tmp/ran.log 'हेड' प्रिंट्स "मैं" एक बार उस अस्थायी फ़ाइल के प्रति प्रतिबद्ध होने के लिए "भाग गया"। – jonny0x5

+1

इस प्रकार 'फ़िल्टर-शाखा' काम करता है, यह आपके द्वारा निर्दिष्ट शाखा के सभी काम करता है। और आपको वास्तव में सभी कामों का मौका देना पड़ता है, आप इससे बच नहीं सकते हैं, 'गिट' स्टोर नहीं करता है, यह फाइल सामग्री को स्टोर करता है, इसलिए यदि आपके पास 'ए-बी-सी' इतिहास है, 'ए' को प्रतिबद्ध करने के लिए "पाद लेख" जोड़ें, लेकिन 'बी' नहीं, ऐसा लगता है कि आपने इसे 'बी' में हटा दिया है, यह फैलता नहीं है, इसलिए यदि आप अपने इतिहास के माध्यम से अपना "पाद लेख" रखना चाहते हैं, तो आपको इसे 'ए',' बी' और 'सी 'करने के लिए जोड़ें, जैसे' फ़िल्टर-शाखा 'करता है (प्रत्येक प्रतिबद्धता के लिए चल रहा है)। – KurzedMetal

+0

इस स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। मैं 'गिट फ़िल्टर-शाखा - ट्री-फिल्टर' का उपयोग करके अपना लक्ष्य पूरा करने में सक्षम था, और वांछित परिवर्तन करने के लिए एक छोटी शॉर्ट (20 लाइनों से कम) perl स्क्रिप्ट बनाई। मेरी समझ यह है कि स्टैक ओवरफ्लो सबसे अच्छा अभ्यास यह है कि मेरे विशिष्ट प्रश्न, अपवोट और हल के रूप में चिह्नित करने के तरीके को स्पष्ट करने के लिए अपने उत्तर को संपादित करना है। – jonny0x5

-1

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

यदि आपके पास पहले से ही एक सही समाधान है (यहां तक ​​कि एक जो तीन दिन लेता है), क्या यह अनुकूलित करने का प्रयास करना वाकई सार्थक है? I वास्तव में इस कोड को डीबग करने और निष्पक्ष समाधान लेने वाले तीन दिनों से कम समय में परिणाम जारी करने के लिए पर्याप्त रूप से पर्याप्त रूप से काम करने की कल्पना कर सकता है।

+0

3 दिनों में आप रेपो के इतिहास को फिर से लिखने की तुलना में बहुत अधिक चीजें कर सकते हैं, यह क्रे कंप्यूटर युग नहीं है। तो हाँ यह अनुकूलन योग्य है INMHO – CharlesB

+0

मेरा मतलब था कि परिणाम रिलीज के लिए तैयार होने से पहले ** विकास ** के तीन दिनों से अधिक समय लगेगा। –

+0

क्षमा करें, गलत चीजें, क्या आप अपनी पोस्ट संपादित कर सकते हैं ताकि मैं अपना डाउनवोट हटा सकूं? – CharlesB

संबंधित मुद्दे