git - गिट भंडार में प्रतिबद्ध इतिहास से बड़ी फ़ाइल को कैसे हटाएं/हटाएं?




version-control git-rebase (10)

(इस समस्या को मैंने जो सबसे अच्छा जवाब देखा है वह है: https://stackoverflow.com/a/42544963/714112 , यहां कॉपी की गई है क्योंकि यह थ्रेड Google खोज रैंकिंग में उच्च दिखाई देता है लेकिन वह दूसरा नहीं है)

🚀 एक चमकदार तेज़ खोल एक-लाइनर 🚀

यह शेल स्क्रिप्ट भंडार में सभी ब्लॉब ऑब्जेक्ट्स को प्रदर्शित करती है, जो सबसे छोटी से सबसे बड़ी तक क्रमबद्ध होती है।

मेरे नमूना रेपो के लिए, यह यहां पाए गए अन्य लोगों की तुलना में लगभग 100 गुना तेजी से चला।
मेरे भरोसेमंद एथलॉन II एक्स 4 सिस्टम पर, यह लिनक्स कर्नेल रिपोजिटरी को इसकी 5,622,155 ऑब्जेक्ट्स के साथ एक मिनट में ही संभालता है।

बेस स्क्रिप्ट

git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '/^blob/ {print substr($0,6)}' \
| sort --numeric-sort --key=2 \
| cut --complement --characters=13-40 \
| numfmt --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest

जब आप कोड से ऊपर चलाते हैं, तो आपको इस तरह के अच्छे मानव-पठनीय आउटपुट मिलेंगे:

...
0d99bb931299  530KiB path/to/some-image.jpg
2ba44098e28f   12MiB path/to/hires-image.png
bd1741ddce0d   63MiB path/to/some-video-1080p.mp4

🚀 फास्ट फाइल रिमूवल 🚀

मान लीजिए कि आप HEAD से पहुंचने योग्य प्रत्येक प्रतिबद्धता से फ़ाइलों को a और b को हटाना चाहते हैं, तो आप इस कमांड का उपयोग कर सकते हैं:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch a b' HEAD

कभी-कभी मैंने एक डीवीडी प्रोजेक्ट को एक वेबसाइट प्रोजेक्ट में गिरा दिया, फिर लापरवाही से git commit -a -m ... , और, ज़ैप, रिपो को 2.2 गीगा द्वारा फूला गया था। अगली बार मैंने कुछ संपादन किए, वीडियो फ़ाइल हटा दी, और सबकुछ किया, लेकिन संपीड़ित फ़ाइल इतिहास में, भंडार में अभी भी है।

मुझे पता है कि मैं उन चीजों से शाखाएं शुरू कर सकता हूं जो एक काम करता है और एक शाखा को दूसरे पर पुनर्जीवित करता है। लेकिन मुझे 2 कामों को एक साथ जोड़ने के लिए क्या करना चाहिए ताकि बड़ी फाइल इतिहास में दिखाई न दे और कचरा संग्रहण प्रक्रिया में साफ हो?


आप branch filter कमांड का उपयोग कर ऐसा कर सकते हैं:

git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD


एसओ में वस्तुतः हर जवाब की कोशिश करने के बाद, मुझे अंत में यह मणि मिला जो मेरे भंडार में बड़ी फ़ाइलों को हटा दिया और हटा दिया और मुझे फिर से सिंक करने की अनुमति दी: http://www.zyxware.com/articles/4027/how-to-delete-files-permanently-from-your-local-and-remote-git-repositories

अपने स्थानीय कामकाजी फ़ोल्डर में सीडी और निम्न आदेश चलाएं:

git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch FOLDERNAME" -- --all

FOLDERNAME को उस फ़ाइल या फ़ोल्डर से प्रतिस्थापित करें जिसे आप दिए गए गिट रिपॉजिटरी से निकालना चाहते हैं।

एक बार यह हो जाने के बाद स्थानीय भंडार को साफ करने के लिए निम्न आदेश चलाएं:

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

अब रिमोट रिपोजिटरी में सभी बदलावों को दबाएं:

git push --all --force

यह रिमोट रिपोजिटरी को साफ करेगा।


जब आप इस समस्या में भाग लेते हैं, तो git rm पर्याप्त नहीं होगा, क्योंकि गिट याद करता है कि फ़ाइल हमारे इतिहास में एक बार मौजूद थी, और इस प्रकार इसका संदर्भ रखेगा।

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

मैंने git forget-blob को एक साथ रखा, एक छोटी सी लिपि जो इन सभी संदर्भों को हटाने का प्रयास करती है, और फिर शाखा में हर प्रतिबद्धता को फिर से लिखने के लिए गिट फ़िल्टर-शाखा का उपयोग करती है।

एक बार जब आपका ब्लॉब पूरी तरह से अव्यवस्थित हो जाता है, तो git gc इससे छुटकारा पा लेगा

उपयोग बहुत आसान git forget-blob file-to-forget । आप यहां अधिक जानकारी प्राप्त कर सकते हैं

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

मैंने इसे स्टैक ओवरफ़्लो और कुछ ब्लॉग प्रविष्टियों के उत्तरों के साथ धन्यवाद दिया। उन्हें क्रेडिट!


मैं इसमें बिटबकेट खाते के साथ भाग गया, जहां मैंने गलती से मेरी साइट के विशाल * .jpa बैकअप संग्रहीत किए थे।

git filter-branch --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch MY-BIG-DIRECTORY-OR-FILE' --tag-name-filter cat -- --all

अपने इतिहास ( टैग सहित ) को पूरी तरह से लिखने के लिए प्रश्न में फ़ोल्डर के साथ MY-BIG-DIRECTORY को दोहराएं।

स्रोत: http://naleid.com/blog/2012/01/17/finding-and-purging-big-files-from-git-history


मैंने मूल रूप से यह उत्तर दिया था: https://.com/a/11032521/1286423

(इतिहास के लिए, मैं इसे कॉपी-पेस्ट कर दूंगा)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch YOURFILENAME" HEAD
$ rm -rf .git/refs/original/ 
$ git reflog expire --all 
$ git gc --aggressive --prune
$ git push origin master --force

यह काम नहीं किया, क्योंकि मैं चीजों का नाम बदलना और स्थानांतरित करना पसंद करता हूं। तो कुछ बड़ी फाइल फ़ोल्डरों में थीं जिनका नाम बदल दिया गया है, और मुझे लगता है कि जीसी उन फ़ाइलों के संदर्भ में tree ऑब्जेक्ट्स में संदर्भ के कारण उन फ़ाइलों के संदर्भ को हटा नहीं सका। वास्तव में इसे मारने का मेरा अंतिम समाधान यह था:

# First, apply what's in the answer linked in the front
# and before doing the gc --prune --aggressive, do:

# Go back at the origin of the repository
git checkout -b newinit <sha1 of first commit>
# Create a parallel initial commit
git commit --amend
# go back on the master branch that has big file
# still referenced in history, even though 
# we thought we removed them.
git checkout master
# rebase on the newinit created earlier. By reapply patches,
# it will really forget about the references to hidden big files.
git rebase newinit

# Do the previous part (checkout + rebase) for each branch
# still connected to the original initial commit, 
# so we remove all the references.

# Remove the .git/logs folder, also containing references
# to commits that could make git gc not remove them.
rm -rf .git/logs/

# Then you can do a garbage collection,
# and the hidden files really will get gc'ed
git gc --prune --aggressive

मेरा रेपो (.git) 32 एमबी से 388 केबी तक बदल गया, यहां तक ​​कि फ़िल्टर-शाखा भी साफ नहीं हो सका।


यदि आपको पता है कि पूरे पेड़ के माध्यम से जाने के बजाए आपकी प्रतिबद्धता हाल ही में थी: git filter-branch --tree-filter 'rm LARGE_FILE.zip' HEAD~10..HEAD


ये आदेश मेरे मामले में काम करते थे:

git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch oops.iso' --prune-empty --tag-name-filter cat -- --all
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

यह उपरोक्त संस्करणों से थोड़ा अलग है।

उन लोगों के लिए जिन्हें इसे जिथब / बिटबकेट में धक्का देना है (मैंने केवल बिटबकेट के साथ इसका परीक्षण किया):

# WARNING!!!
# this will rewrite completely your bitbucket refs
# will delete all branches that you didn't have in your local

git push --all --prune --force

# Once you pushed, all your teammates need to clone repository again
# git pull will not work

बीआईटीजी रिपो-क्लीनर का उपयोग करें, git-filter-branch लिए एक सरल, तेज़ विकल्प, विशेष रूप से गिट इतिहास से अवांछित फ़ाइलों को हटाने के लिए डिज़ाइन किया गया है।

उपयोग निर्देशों का ध्यानपूर्वक पालन करें , मुख्य भाग यह है:

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git

आकार में 100 एमबी से अधिक की कोई भी फाइल (जो आपकी नवीनतम प्रतिबद्धता में नहीं हैं) को आपके गिट रिपॉजिटरी के इतिहास से निकाल दिया जाएगा। फिर आप मृत डेटा को साफ करने के लिए git gc का उपयोग कर सकते हैं:

$ git gc --prune=now --aggressive

बीएफजी आम तौर पर git-filter-branch चलाने से कम से कम 10-50x तेज होता है, और आम तौर पर उपयोग करना आसान होता है।

पूर्ण प्रकटीकरण: मैं बीएफजी रिपो-क्लीनर का लेखक हूं।


git filter-branch --tree-filter 'rm -f path/to/file' HEAD ने मेरे लिए बहुत अच्छा काम किया, हालांकि मैंने here वर्णित वही समस्या में भाग लिया, जिसे मैंने इस सुझाव का पालन ​​करके हल किया।

प्रो-गिट बुक में पुनर्लेखन इतिहास पर एक संपूर्ण अध्याय है - प्रत्येक कमिट अनुभाग से filter-branch / फ़ाइल को निकालने पर एक नज़र डालें।






git-rewrite-history