2010-10-28 28 views
50

मेरे पास git के तहत एक प्रोजेक्ट है। एक दिन मैंने परियोजना के तहत सभी प्रोजेक्ट फ़ाइलों को वर्तमान निर्देशिका से foo/bar/ पर ले जाया। मैंने इसे git mv का उपयोग किया। फिर मैंने कुछ और फाइलें जोड़े और पहले से ही मौजूदा फाइलों में कुछ बदलाव किए।मैं इतिहास को फिर से लिख सकता हूं ताकि सभी फ़ाइलों को छोड़कर, जो मैं पहले से ही स्थानांतरित कर चुका हूं, उपनिर्देशिका में हैं?

परिणामस्वरूप, अब जब मैं foo/bar/file.c के इतिहास को देखता हूं, तो मैं केवल फाइलों को स्थानांतरित करने के बाद किए गए परिवर्तनों को देख सकता हूं।

मैंने इसे विभिन्न तरीकों से ठीक करने की कोशिश की (filter-branch उपनिर्देशिका फ़िल्टर, आदि के साथ), लेकिन कुछ भी मदद नहीं की, इसलिए मैं यहां बहुत ढेर हूं। मैं किसी भी मदद की सराहना करूंगा जो आप मुझे दे सकते हैं। धन्यवाद!

उत्तर

85

फाइलों के साथ इतिहास के पुनर्लेखन के लिए ले जाया गया:

आप के रूप में यद्यपि सभी फाइलों को हमेशा निर्देशिका foo/bar में रहे हैं, तो आप एक छोटे से सर्जरी करने की जरूरत है इस परियोजना के इतिहास देखने के लिए चाहते हैं। प्रतिबद्ध के पुनर्लेखन के लिए इतना है कि कहीं भी foo/bar मौजूद नहीं है "पेड़ फिल्टर" के साथ git filter-branch का प्रयोग करें, यह बनाए जाने और उसके सभी फाइलों को यह करने के लिए ले जाया जाता है:

git filter-branch --prune-empty --tree-filter ' 
if [ ! -e foo/bar ]; then 
    mkdir -p foo/bar 
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar 
fi' 

अब इतिहास रेकॉर्ड नहीं होगा के रूप में अगर सभी फाइलों थे हमेशाfoo/bar में स्थित है।

एक चले गए फ़ाइल का इतिहास देखना चाहते:

आप सिर्फ इतना है कि ले जाया गया है या अतीत में कुछ बिंदु पर नाम बदलकर एक फ़ाइल के इतिहास को देखने के लिए चाहते हैं, तो बस --follow विकल्प का उपयोग करने के लिए git log:

git log --follow foo/bar/file.c 
+1

@Alexander: आप बैश शेबांग लाइन के साथ एक वास्तविक स्क्रिप्ट में एक-लाइनर (एकल उद्धरण में सब कुछ) डालने का प्रयास करना चाह सकते हैं। मुझे लगता है कि 'फ़िल्टर-शाखा' शायद इसे 'sh' में चलाने की कोशिश कर रहा है, न कि 'bash'। – Cascabel

+0

मैंने कुछ प्रगति की। ऐसा लगता है कि अगर कथन में डबल ब्रैकेट इस त्रुटि का कारण बन रहे थे। सिंगल ब्रैकेट बेहतर काम करते हैं, फिर भी यह काम नहीं करता है। समस्या यह है कि मैंने सबकुछ foo/bar/में स्थानांतरित करने से पहले/प्रोजेक्ट में कुछ सामग्री के साथ foo नाम की निर्देशिका थी। तो अब यह शिकायत करता है "'foo' को अपने आप की उपनिर्देशिका, 'foo/bar/foo' 'में स्थानांतरित नहीं किया जा सकता है। –

+0

@Alexander: आपको तदनुसार स्क्रिप्ट को समायोजित करने की आवश्यकता होगी। कुछ ऐसा है: 'अगर [[! -e foo/bar]]; तो mkdir -p foo/bar; गिट एलएस-पेड़ - नाम केवल $ GIT_COMMIT | grep -v^foo $ | xargs- मैं फ़ाइलें एमवी फाइल foo/बार; fi' स्थानांतरित होने वाली फ़ाइलों की सूची से 'foo' को फ़िल्टर करने के लिए grep का उपयोग करता है। ध्यान दें कि मैं यह भी मान रहा हूं कि 'बार' उपनिर्देशिका तब तक अस्तित्व में नहीं थी जब तक कि आप इसके तहत सबकुछ नहीं ले जाते। यदि ऐसा नहीं है, तो आपको इसके लिए स्क्रिप्ट में भी खाते की आवश्यकता होगी। –

6

चीजों को लपेटने के लिए यहां मैंने जो किया है उसका संक्षिप्त सारांश है। आदेश है कि मेरे लिए काम किया था:

if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi 

गूंज आदेश है कि मैं अंत में जोड़ा सुनिश्चित किया है कि जब भी mv विफल रहता है पूरे आदेश चलते रहेंगे। यह foo/bar/foo की सामग्री को स्थानांतरित नहीं करता है, लेकिन मैं इसके साथ रह सकता हूं।

मदद के लिए Dan Moulding (!!!) और जेफ्रोमी के लिए बहुत बहुत धन्यवाद।