Git / GitHub के इतिहास से फ़ोल्डर और उसकी सामग्री निकालें


318

मैं अपने GitHub खाते पर एक भंडार पर काम कर रहा था और यह एक ऐसी समस्या है जिस पर मैं लड़खड़ा गया।

  • Node.js कुछ npm संकुल अधिष्ठापित फ़ोल्डर के साथ प्रोजेक्ट करता है
  • पैकेज node_modulesफ़ोल्डर में थे
  • उस फ़ोल्डर को रिपॉजिटरी में जोड़ा और जीथब को कोड धक्का दिया (उस समय एनपीएम भाग के बारे में नहीं सोच रहा था)
  • एहसास हुआ कि आपको कोड का हिस्सा बनने के लिए वास्तव में उस फ़ोल्डर की आवश्यकता नहीं है
  • उस फ़ोल्डर को हटा दिया गया, उसे धकेल दिया गया

उस समय, कुल git रेपो का आकार लगभग 6MB था जहां वास्तविक कोड (उस फ़ोल्डर को छोड़कर) लगभग 300 KB था

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

मैंने इसके लिए संभावित समाधानों को देखा और इन 2 तरीकों को आजमाया

Gist ऐसा लगता है कि यह काम किया है जहां स्क्रिप्ट चलाने के बाद, यह पता चला कि यह उस फ़ोल्डर से छुटकारा पा गया और इसके बाद पता चला कि 50 अलग-अलग कमिट संशोधित किए गए थे। लेकिन इसने मुझे उस कोड को आगे बढ़ाने नहीं दिया। जब मैंने इसे धकेलने की कोशिश की, तो यह कहा गया Branch up to dateलेकिन दिखाया गया कि 50 कमिट को ए पर संशोधित किया गया था git status। अन्य 2 विधियों ने भी मदद नहीं की।

अब भले ही यह दिखाया गया है कि यह उस फ़ोल्डर के इतिहास से छुटकारा दिलाता है, जब मैंने अपने लोकलहोस्ट पर उस रेपो के आकार की जांच की, तब भी यह लगभग 6 एमबी था। (मैंने refs/originalफ़ोल्डर भी हटा दिया है लेकिन रेपो के आकार में परिवर्तन नहीं देखा है)।

मैं जो स्पष्ट करना चाह रहा हूं वह है, अगर न केवल कमिटेड हिस्ट्री से छुटकारा पाने का एक तरीका है (जो कि केवल एक चीज है जो मुझे लगता है कि हुआ है), बल्कि उन फाइलों को भी रख रहा है जो एक रोलबैक करना चाहती है।

कहते हैं कि इसके लिए एक समाधान प्रस्तुत किया गया है और इसे मेरे लोकलहोस्ट पर लागू किया गया है, लेकिन उस गिटहब रेपो के लिए पुन: पेश नहीं किया जा सकता है, क्या यह संभव है कि रेपो, रोलबैक को पहले कमिट करने के लिए ट्रिक करें और इसे पुश करें (या ऐसा नहीं होगा कि गिट होगा अभी भी उन सभी आवागमन का इतिहास है? - उर्फ। 6 एमबी)।

यहां मेरा अंतिम लक्ष्य मूल रूप से फ़ोल्डर सामग्री को गिट से छुटकारा पाने का सबसे अच्छा तरीका है ताकि उपयोगकर्ता को 6MB के लायक सामान डाउनलोड न करना पड़े और फिर भी संभवतः अन्य कमिट्स हों जो कभी भी मॉड्यूल फ़ोल्डर को नहीं छूते हैं (यह सुंदर है उन सभी को) git के इतिहास में।

मैं यह कैसे कर सकता हूँ?


3
यदि नीचे दिए गए किसी भी उत्तर ने आपकी समस्या हल कर दी है, तो शायद आपको अपने प्रश्न के उत्तर के रूप में स्वीकार करने पर विचार करना चाहिए। meta.stackexchange.com/questions/5234/…
starbeamrainbowlabs

सबसे अच्छा जवाब है: stackoverflow.com/a/32886427/5973334
कुज़ेको

जवाबों:


556

यदि आप कोड को कॉपी-पेस्ट करने के लिए यहां हैं:

यह एक उदाहरण है जो node_modulesइतिहास से हटा देता है

git filter-branch --tree-filter "rm -rf node_modules" --prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo node_modules/ >> .gitignore
git add .gitignore
git commit -m 'Removing node_modules from git history'
git gc
git push origin master --force

वास्तव में क्या करता है:

पहली पंक्ति --tree-filterकमांड चलाने वाले एक ही पेड़ ( ) के रूप में HEAD (आपकी वर्तमान शाखा) पर सभी संदर्भों से गुजरती है rm -rf node_modules। यह आदेश (फ़ोल्डर node_modules को हटा देता है -r, बिना -r, rmकोई शीघ्र उपयोगकर्ता को दिया (के साथ नष्ट फ़ोल्डरों नहीं होगा), -f)। जोड़ा --prune-emptyबेकार हटा देता है (कुछ भी नहीं बदल रहा है) पुनरावृत्ति करता है।

दूसरी पंक्ति उस पुरानी शाखा के संदर्भ को हटा देती है।

बाकी कमांड अपेक्षाकृत सरल हैं।


3
बस एक साइड नोट: मैं git count-objects -vजाँचता था कि क्या फाइलें वास्तव में हटा दी गई थीं, लेकिन रिपॉजिटरी का आकार तब तक बना रहता है जब तक कि मैं रिपॉजिटरी को फिर से क्लोन नहीं करता। मुझे लगता है कि सभी मूल फ़ाइलों की एक प्रतिलिपि मिलिट।
डेविड इकार्डी

4
एक गैर-प्राचीन गिट के साथ, यह शायद पढ़ना चाहिए --force-with-lease, नहीं --force
ग्रिवेस

4
इनमें से कोई भी कमांड विंडोज़ पर काम नहीं करती है। या कम से कम नहीं विंडोज 10 ओएस पोस्ट करें कि "कट और पेस्ट" पर काम करता है
डेविड

3
विंडोज 10 उपयोगकर्ताओं के लिए, यह अच्छी तरह से विंडोज के लिए बैश के तहत काम करता है (मैंने उबंटू का इस्तेमाल किया)
लेडी किसेलिका

3
मैंने इसे विंडोज़ शेल के साथ और गिट बैश के साथ आज़माया, और काम नहीं किया। पहला कमांड पास, दूसरा कमांड फेल!
मोहि एल्डीन

240

मुझे लगता है कि --tree-filterअन्य उत्तरों में उपयोग किए जाने वाले विकल्प बहुत धीमे हो सकते हैं, विशेष रूप से बहुत सारे रिपॉजिटरी पर बहुत सारे कमिट के साथ।

यहाँ वह विधि है जो मैं --index-filterविकल्प का उपयोग करते हुए गिट इतिहास से एक निर्देशिका को पूरी तरह से हटाने के लिए उपयोग करता हूं , जो बहुत तेज चलती है:

# Make a fresh clone of YOUR_REPO
git clone YOUR_REPO
cd YOUR_REPO

# Create tracking branches of all branches
for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

# Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits
# (repeat these two commands for as many directories that you want to remove)
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

# Ensure all old refs are fully removed
rm -Rf .git/logs .git/refs/original

# Perform a garbage collection to remove commits with no refs
git gc --prune=all --aggressive

# Force push all branches to overwrite their history
# (use with caution!)
git push origin --all --force
git push origin --tags --force

आप पहले और बाद में भंडार का आकार देख सकते हैं gc:

git count-objects -vH

3
क्या आप बता सकते हैं कि यह ज्यादा तेज क्यों है?
नोक्टेक्ट

7
@knocte: डॉक्स से ( git-scm.com/docs/git-filter-branch )। "-इंडेक्स-फिल्टर: ... ट्री फिल्टर के समान है, लेकिन पेड़ की जांच नहीं करता है, जो इसे बहुत तेज बनाता है"
ली नेथर्टन

23
यह स्वीकृत उत्तर क्यों नहीं है? यह पूरी तरह से है।
मैड फिजिसिस्ट

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

12
उपर्युक्त के --quietलिए पासिंग git rmकम से कम फैक्टर 4.
ctusch

46

उपरोक्त लोकप्रिय उत्तर के अलावा, मैं विंडोज-सिस्टम के लिए कुछ नोट्स जोड़ना चाहूंगा । आदेश

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD
  • पूरी तरह से किसी भी संशोधन के बिना काम करता है ! इसलिए, आपको इसके बजाय Remove-Item, delया कुछ और का उपयोग नहीं करना चाहिएrm -rf

  • यदि आपको किसी फ़ाइल या निर्देशिका के लिए पथ निर्दिष्ट करने की आवश्यकता है , जैसे स्लैश का उपयोग करें./path/to/node_modules


अगर निर्देशिका में ए शामिल है तो यह विंडोज पर काम नहीं करेगा। (डॉट) नाम से।
कॉर्नेलियु सेरेडियू

4
और मुझे इसका हल मिल गया। Rm कमांड के लिए डबल इनवर्टेड-कॉमा का उपयोग इस तरह करें: "rm -rf नोड.modules"।
कोर्नेलियु सेरेडियुक

23

मुझे मिली सबसे अच्छी और सटीक विधि bfg.jar फ़ाइल डाउनलोड करना था: https://rtyley.github.io/bfg-repo-cleaner/

फिर कमांड चलाएं:

git clone --bare https://project/repository project-repository
cd project-repository
java -jar bfg.jar --delete-folders DIRECTORY_NAME  # i.e. 'node_modules' in other examples
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push --mirror https://project/new-repository

यदि आप फ़ाइलों को हटाना चाहते हैं तो इसके बजाय डिलीट-फाइल विकल्प का उपयोग करें:

java -jar bfg.jar --delete-files *.pyc

1
बहुत आसान :) अगर आप यह सुनिश्चित करना चाहते हैं कि केवल एक विशिष्ट फ़ोल्डर हटा दिया जाए, तो इससे मदद मिलेगी: stackoverflow.com/questions/21142986/…
emjay

9

ऐसा प्रतीत होता है कि इसके लिए अप-टू-डेट उत्तर का उपयोग सीधे नहीं करना filter-branchहै (कम से कम गिट खुद ही अब इसकी सिफारिश नहीं करता है), और उस काम को एक बाहरी उपकरण से हटा दें। विशेष रूप से, गिट-फिल्टर-रेपो वर्तमान में अनुशंसित है। उस टूल के लेखक का उपयोग करने पर तर्क प्रदान करता हैfilter-branch हैं सीधे उपयोग करने से समस्याएं पैदा हो सकती हैं।

dirइतिहास से हटाने के लिए ऊपर दी गई अधिकांश मल्टी-लाइन स्क्रिप्ट को फिर से लिखा जा सकता है:

git filter-repo --path dir --invert-paths

उपकरण जाहिरा तौर पर अधिक शक्तिशाली है। आप लेखक, ईमेल, refname और अधिक ( यहां पूरा मैनपेज ) द्वारा फ़िल्टर लागू कर सकते हैं । इसके अलावा, यह तेज है । स्थापना आसान है - यह विभिन्न स्वरूपों में वितरित किया जाता है


अच्छा उपकरण! उबंटू 20.04 पर अच्छी तरह से काम करता है, आप केवल pip3 install git-filter-repoतब से कर सकते हैं जब यह केवल स्टैडलिब है और कोई निर्भरता स्थापित नहीं करता है। उबंटू 18 पर यह डिस्ट्रो के गिट संस्करण के साथ असंगत है Error: need a version of git whose diff-tree command has the --combined-all-paths option, लेकिन docker run -ti ubuntu:20.04
कुबंज़िक

7

कॉपी और पेस्ट करने की विधि को पूरा करें, केवल टिप्पणियों में कमांड जोड़कर (कॉपी-पेस्ट समाधान के लिए), उनका परीक्षण करने के बाद:

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD
echo node_modules/ >> .gitignore
git add .gitignore
git commit -m 'Removing node_modules from git history'
git gc
git push origin master --force

इसके बाद, आप .OGignore से "node_modules /" लाइन हटा सकते हैं


क्यों आप तो हटा node_modulesसे .gitignore? ताकि वे गलती से फिर से प्रतिबद्ध हो सकें ??
एडम्सकी

1
यह gitignore से हटाया नहीं जाता है, इसे gitignore में जोड़ा जाता है। प्रतिबद्ध संदेश में "git history" कहा गया है, न कि "gitignore" :)
डैनी टुप्पेनि

लेकिन टिप्पणी का कहना है कि आप तो निकाल सकते हैं node_modulesसे .gitignore
ज़ावर

7

विंडोज उपयोगकर्ता के लिए, कृपया इसके अलावा उपयोग "करने के लिए कृपया ध्यान दें कि यदि कोई अन्य बैकअप पहले से है तो कमांड को 'जोड़ने के -fलिए जोड़ा जाए।

git filter-branch -f --tree-filter "rm -rf FOLDERNAME" --prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo FOLDERNAME/ >> .gitignore
git add .gitignore
git commit -m "Removing FOLDERNAME from git history"
git gc
git push origin master --force

3

मैंने विंडोज़ पर git का उपयोग करके पुराने C # प्रोजेक्ट से बिन और ओबीजी फ़ोल्डर्स को हटा दिया। इसके साथ सावधान रहें

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

यह git इनस्टॉल फ़ोल्डर में usr / bin फोल्डर को हटाकर git इंस्टॉलेशन की अखंडता को नष्ट कर देता है।

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