Git रिपॉजिटरी में प्रतिबद्ध इतिहास से एक बड़ी फ़ाइल को हटाने / हटाने के लिए कैसे?


708

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

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


9
यह लेख आपको मदद करना चाहिए। github.com/removing-sensitive-data
MBO


1
ध्यान दें कि यदि आपकी बड़ी फ़ाइल किसी उपखंड में है, तो आपको पूर्ण सापेक्ष पथ निर्दिष्ट करना होगा।
जोहान

1
संबंधित मदद। Github.com/en/articles/…
frederj

बीएफजी के नीचे दिए गए कई जवाब जितना आसान है git filter-branch, लेकिन मैंने इसके विपरीत पाया।
2540625

जवाबों:


605

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

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

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

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

$ git gc --prune=now --aggressive

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

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


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

1
@RobertoTyley धन्यवाद। मैंने इसे 3 अलग-अलग बार आज़माया है और सभी एक ही संदेश के साथ हुए हैं। इसलिए मैं यह भी सोच रहा हूं कि आप गैर-फास्ट-फॉरवर्ड अपडेट को अस्वीकार करने के लिए दूरस्थ सर्वर के बारे में सही हैं। मैं बस एक नए रेपो में अपडेट किए गए रेपो को आगे बढ़ाने पर विचार करूंगा। धन्यवाद!
टोनी

7
@ रॉबर्टबोली परफेक्ट, आप मेरा समय बचाते हैं, बहुत बहुत धन्यवाद। वैसे, शायद git push --forceआपके चरणों के बाद करना चाहिए , अन्यथा रिमोट रेपो अभी भी नहीं बदला है।
ली 2

3
जोड़ने के लिए +1 git push --force। इसके अलावा ध्यान देने योग्य: बल पुश को रिमोट द्वारा अनुमति नहीं दी जा सकती है (gitlab.com डिफ़ॉल्ट रूप से, शाखा को "असुरक्षित" करने के लिए नहीं था)।
MatrixManAtYrService 15

25
मुझे लगता है कि ट्रम्प शब्दजाल टूल आउटपुट थोड़ा बहुत है।
क्रिस

564

यदि आप अन्य डेवलपर्स के लिए इतिहास प्रकाशित कर चुके हैं, तो आप जो करना चाहते हैं, वह बहुत ही विघटनकारी है। अपने इतिहास की मरम्मत के बाद आवश्यक चरणों के लिए प्रलेखन में "अपस्ट्रीम रिबेस से पुनर्प्राप्त करना"git rebase देखें ।

आपके पास कम से कम दो विकल्प हैं: git filter-branchऔर एक इंटरैक्टिव रिबेस, दोनों को नीचे समझाया गया है।

का उपयोग करते हुए git filter-branch

मुझे एक तोड़फोड़ आयात से भारी बाइनरी टेस्ट डेटा के साथ एक समान समस्या थी और एक गिट रिपॉजिटरी से डेटा हटाने के बारे में लिखा था ।

अपने इतिहास को कहो:

$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A     login.html
* cb14efd Remove DVD-rip
| D     oops.iso
* ce36c98 Careless
| A     oops.iso
| A     other.html
* 5af4522 Admin page
| A     admin.html
* e738b63 Index
  A     index.html

ध्यान दें कि git lolaएक गैर-मानक लेकिन अत्यधिक उपयोगी उपनाम है। --name-statusस्विच के साथ , हम प्रत्येक संशोधन से जुड़े पेड़ संशोधनों को देख सकते हैं।

"लापरवाह" प्रतिबद्ध में (जिसका SHA1 ऑब्जेक्ट नाम CE36c98 है) फ़ाइल oops.isoडीवीडी-चीर दुर्घटना से जोड़ा गया है और अगले प्रतिबद्ध में हटा दिया गया है, cb14efd। पूर्वोक्त ब्लॉग पोस्ट में वर्णित तकनीक का उपयोग करना, निष्पादित करने का आदेश है:

git filter-branch --prune-empty -d /dev/shm/scratch \
  --index-filter "git rm --cached -f --ignore-unmatch oops.iso" \
  --tag-name-filter cat -- --all

विकल्प:

  • --prune-emptyहटाता है कि फिल्टर ऑपरेशन के परिणामस्वरूप खाली हो जाता है ( यानी , पेड़ को न बदलें)। ठेठ मामले में, यह विकल्प एक क्लीनर इतिहास पैदा करता है।
  • -dएक अस्थायी निर्देशिका का नाम जो फ़िल्टर्ड इतिहास के निर्माण के लिए उपयोग करने के लिए मौजूद नहीं है। यदि आप एक आधुनिक लिनक्स वितरण पर चल रहे हैं, तो एक पेड़ को/dev/shm निर्दिष्ट करने से तेजी से निष्पादन होगा
  • --index-filterमुख्य घटना है और इतिहास में प्रत्येक चरण पर सूचकांक के खिलाफ चलती है। आप oops.isoजहां भी मिल रहे हैं उसे हटाना चाहते हैं , लेकिन यह सभी कमिट में मौजूद नहीं है। git rm --cached -f --ignore-unmatch oops.isoजब यह मौजूद होता है तो कमांड डीवीडी-रिप को हटा देता है और अन्यथा विफल नहीं होता है।
  • --tag-name-filterटैग नामों को फिर से लिखने का तरीका बताता है। का एक फ़िल्टर catपहचान ऑपरेशन है। आपके रिपॉजिटरी, ऊपर के नमूने की तरह, कोई टैग नहीं हो सकता है, लेकिन मैंने इस विकल्प को पूर्ण सामान्यता के लिए शामिल किया है।
  • -- विकल्पों के अंत को निर्दिष्ट करता है git filter-branch
  • --allनिम्नलिखित --सभी रेफ के लिए आशुलिपि है। आपके रिपॉजिटरी, ऊपर के नमूने की तरह, केवल एक रेफरी (मास्टर) हो सकता है, लेकिन मैंने इस विकल्प को पूर्ण सामान्यता के लिए शामिल किया है।

कुछ मंथन के बाद, अब इतिहास है:

$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A     login.html
* e45ac59 Careless
| A     other.html
|
| * f772d66 (refs/original/refs/heads/master) Login page
| | A   login.html
| * cb14efd Remove DVD-rip
| | D   oops.iso
| * ce36c98 Careless
|/  A   oops.iso
|   A   other.html
|
* 5af4522 Admin page
| A     admin.html
* e738b63 Index
  A     index.html

ध्यान दें कि नई "लापरवाह" प्रतिबद्धता केवल जोड़ता है other.htmlऔर "निकालें डीवीडी रिप" प्रतिबद्ध अब मास्टर शाखा पर नहीं है। लेबल की गई शाखा refs/original/refs/heads/masterमें आपके द्वारा गलत किए जाने की स्थिति में आपके मूल कमिट होते हैं। इसे हटाने के लिए, "रिपॉजिटरी को सिकोड़ने के लिए चेकलिस्ट" में दिए चरणों का पालन करें

$ git update-ref -d refs/original/refs/heads/master
$ git reflog expire --expire=now --all
$ git gc --prune=now

एक सरल विकल्प के लिए, अवांछित बिट्स को छोड़ने के लिए रिपॉजिटरी को क्लोन करें।

$ cd ~/src
$ mv repo repo.old
$ git clone file:///home/user/src/repo.old repo

file:///...केवल क्लोन बनाने के बजाय क्लोन URL का उपयोग करना वस्तुओं को कॉपी करता है।

अब आपका इतिहास है:

$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A     login.html
* e45ac59 Careless
| A     other.html
* 5af4522 Admin page
| A     admin.html
* e738b63 Index
  A     index.html

पहले दो कमिट्स ("इंडेक्स" और "एडमिन पेज") के लिए SHA1 ऑब्जेक्ट के नाम एक ही रहे, क्योंकि फिल्टर ऑपरेशन ने उन कमिट्स को संशोधित नहीं किया था। "लापरवाह" खो गया oops.isoऔर "लॉगिन पृष्ठ" को एक नया माता-पिता मिल गया, इसलिए उनके SHA1 ने बदलाव किया।

परस्पर विद्रोह

के इतिहास के साथ:

$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A     login.html
* cb14efd Remove DVD-rip
| D     oops.iso
* ce36c98 Careless
| A     oops.iso
| A     other.html
* 5af4522 Admin page
| A     admin.html
* e738b63 Index
  A     index.html

आप oops.iso"लापरवाह" से हटाना चाहते हैं जैसे कि आपने इसे कभी नहीं जोड़ा, और फिर "डीवीडी-चीर निकालें" आपके लिए बेकार है। इस प्रकार, हमारी योजना एक इंटरैक्टिव रीबेस में है "एडमिन पेज" को "लापरवाह" संपादित करने और "निकालें-चीर" को हटाने के लिए है।

रनिंग $ git rebase -i 5af4522निम्नलिखित सामग्रियों के साथ एक संपादक शुरू करता है।

pick ce36c98 Careless
pick cb14efd Remove DVD-rip
pick f772d66 Login page

# Rebase 5af4522..f772d66 onto 5af4522
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

हमारी योजना को निष्पादित करते हुए, हम इसे संशोधित करते हैं

edit ce36c98 Careless
pick f772d66 Login page

# Rebase 5af4522..f772d66 onto 5af4522
# ...

यही है, हम "डीवीडी-रिप हटाएं" के साथ लाइन हटाते हैं और ऑपरेशन को "लापरवाह" के editबजाय बदल देते हैं pick

निम्नलिखित संदेश के साथ कमांड प्रॉम्प्ट पर सेव-क्विट करना हमें छोड़ देता है।

Stopped at ce36c98... Careless
You can amend the commit now, with

        git commit --amend

Once you are satisfied with your changes, run

        git rebase --continue

जैसा कि संदेश हमें बताता है, हम "लापरवाह" कमिट पर हैं जिसे हम संपादित करना चाहते हैं, इसलिए हम दो कमांड चलाते हैं।

$ git rm --cached oops.iso
$ git commit --amend -C HEAD
$ git rebase --continue

पहले सूचकांक से आपत्तिजनक फ़ाइल को हटाता है। दूसरा संशोधित इंडेक्स होने के लिए "लापरवाह" को संशोधित या संशोधित करता है और -C HEADपुराने प्रतिबद्ध संदेश का पुन: उपयोग करने के लिए गिट को निर्देश देता है। अंत में, git rebase --continueबाकी रिबास ऑपरेशन के साथ आगे बढ़ता है।

यह एक इतिहास देता है:

$ git lola --name-status
* 93174be (HEAD, master) Login page
| A     login.html
* a570198 Careless
| A     other.html
* 5af4522 Admin page
| A     admin.html
* e738b63 Index
  A     index.html

जो आप चाहते हैं


4
मैं git फ़िल्टर-शाखा का उपयोग करते समय धक्का क्यों नहीं दे सकता, 'git@bitbucket.org: उत्पाद / myproject.git' पर कुछ रीफ़ पुश करने में विफल रहा है। फिर से धक्का देने से पहले परिवर्तन।
अगुंग प्रिसिएटो

11
अपने कमांड में -f(या --force) विकल्प जोड़ें git push: “आमतौर पर, कमांड एक रिमोट रेफरी को अद्यतन करने से इंकार कर देता है जो इसे अधिलेखित करने के लिए उपयोग किए जाने वाले स्थानीय रेफरी का पूर्वज नहीं है। यह ध्वज चेक को निष्क्रिय करता है। यह रिमोट रिपॉजिटरी को कम करने का कारण बन सकता है; देखभाल के साथ इसका उपयोग करें। ”
ग्रेग बेकन

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

1
मैं ऊपर की प्रक्रियाओं में से किसी एक के बाद, दूरस्थ रिपॉजिटरी (GitHub पर) बड़ी फ़ाइल को नहीं हटाता। केवल स्थानीय करता है। मैंने जोर का धक्का और नाडा लगाया। मैं क्या खो रहा हूँ?
अज़ातरा

1
यह भी dirs पर काम करता है। ... "git rm --cached -rf --ignore-unmatch path/to/dir"...
rynop

198

इस सरल लेकिन शक्तिशाली आदेश का उपयोग क्यों न करें?

git filter-branch --tree-filter 'rm -f DVD-rip' HEAD

--tree-filterविकल्प परियोजना के प्रत्येक चेकआउट के बाद निर्दिष्ट कमांड चलाता है और उसके बाद परिणाम recommits। इस स्थिति में, आप प्रत्येक स्नैपशॉट से डीवीडी-रिप नामक एक फ़ाइल को निकालते हैं, चाहे वह मौजूद हो या न हो।

यदि आप जानते हैं कि किस फ़ाइल ने बहुत बड़ी फ़ाइल शुरू की है (35dsa2 कहें), तो आप HEAD को 35dsa2..HEAD से बदल सकते हैं ताकि बहुत अधिक इतिहास न लिखा जा सके, इस प्रकार यदि आपने अभी तक धक्का नहीं दिया है, तो डायवर्ट करने से बचें। @ अल्फा_989 के सौजन्य से यह टिप्पणी यहां छोड़ना बहुत जरूरी है।

इस लिंक को देखें ।


3
यह एक अच्छा उपाय है! मैंने एक gist बनाया है जिसमें फ़ाइलों को सूचीबद्ध करने के लिए एक python स्क्रिप्ट है और git cmd जो उस फ़ाइल को हटा देगा जिसे आप साफ किया हुआ gist.github.com/ariv3ra/16fd94e46345e62cfbbf
punkdata

5
Bfg से बहुत बेहतर है। मैं bfg के साथ एक गिट से फ़ाइल को साफ करने में असमर्थ था, लेकिन इस कमांड ने मदद की
podarok

4
यह भी खूब रही। दूसरों के लिए बस एक नोट जो कि आपको प्रति शाखा में करना होगा अगर बड़ी फाइल कई शाखाओं में है।
जेम्स

2
विंडोज पर मुझे मिला fatal: bad revision 'rm', जिसे मैंने "इसके बजाय उपयोग करके तय किया '। ओवरऑल कमांड:git filter-branch --force --index-filter "git rm --cached -r --ignore-unmatch oops.iso" --prune-empty --tag-name-filter cat -- --all
marcotama

2
यदि आप जानते हैं commitजहाँ आप में (जैसे कि फ़ाइल डाल 35dsa2), आप बदल सकते हैं HEADके साथ 35dsa2..HEAD। इस तरह से यह सभी कमिट्स की जांच करने और उन्हें फिर से लिखने की कोशिश करने tree-filterकी तुलना में बहुत धीमी है index-filter। यदि आप HEAD का उपयोग करते हैं, तो वह ऐसा करने का प्रयास करेगा।
अल्फा_989

86

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

🚀 एक धधकते हुए तेज खोल एक लाइनर ly

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

मेरे सैंपल रेपो के लिए, यह यहां पाए गए अन्य लोगों की तुलना में लगभग 100 गुना अधिक तेजी से चला।
मेरे भरोसेमंद Athlon II X4 सिस्टम पर, यह सिर्फ एक मिनट में अपने 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

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

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

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

3
यदि आपके रेपो में कोई टैग है, तो आप संभवत: --tag-name-filter catनए संबंधितgit filter-branch --index-filter 'git rm --cached --ignore-unmatch a b' --tag-name-filter cat HEAD
कॉम्पटिट

3
मैक निर्देश और कुछ अन्य जानकारी मूल लिंक पोस्ट में दिखाई देती हैं
nruth

3
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <filename>' HEADवर्कऑर्डर राइट ऑफ द बैट
एलिजोनमार्क

मेरा पसंदीदा जवाब। मैक ओएस (गोन कमांड का उपयोग करके) पर उपयोग करने के लिए एक मामूली ट्वीक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 \ | gnumfmt --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest
फ्लोरियन ओसवाल्ड

रि-लिस्ट के साथ कूल स्क्रिप्ट लेकिन यह मेरे लिए एक उपनाम के रूप में काम नहीं करता था, किसी भी विचार को कैसे करना है?
रॉबिन मैनोली

47

एसओ में लगभग हर उत्तर की कोशिश करने के बाद, मैंने आखिरकार इस मणि को पाया, जो मेरी रिपॉजिटरी में बड़ी फ़ाइलों को जल्दी से हटा दिया और हटा दिया और मुझे फिर से सिंक करने की अनुमति दी: http://www.zyxware.com/articles/4027/how-to-delete -files स्थायी रूप-से-अपने स्थानीय और रिमोट Git-खजाने

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

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

यह सुदूर भंडार को साफ करेगा।


मेरे लिए एक जादू की तरह काम किया।
रेमन वास्कोनसेलोस

3
यह मेरे लिए भी काम किया। एक विशिष्ट फ़ोल्डर से छुटकारा मिल जाता है (मेरे मामले में, एक जिसमें रिपॉजिटरी पर बहुत बड़ी या गीथब रेपो फाइल होती है), लेकिन मौजूद होने पर स्थानीय फाइल सिस्टम पर रखता है।
स्किज़ो

मेरे लिए काम किया! कोई इतिहास नहीं बचा है जो संभावित रूप से भ्रमित है (यदि कोई व्यक्ति जहां अभी क्लोन करना है), तो सुनिश्चित करें कि आपके पास किसी भी टूटे लिंक, निर्भरता, आदि को अपडेट करने की योजना है
ruoho ruotsi

38

इन आदेशों ने मेरे मामले में काम किया:

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

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

उन लोगों के लिए जिन्हें इसे github / bitbucket पर धकेलने की आवश्यकता है (मैंने केवल इसे bitbucket के साथ परीक्षण किया है):

# 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

4
यह ऊपर से अलग कैसे है, यह बेहतर क्यों है?
एंडी हेडन

1
किसी कारण से mkljun संस्करण मेरे मामले में गिट स्पेस को कम नहीं करता है, मैंने पहले ही उपयोग करके फ़ाइलों को सूचकांक से हटा दिया था git rm --cached files। ग्रेग बेकन का प्रस्ताव अधिक पूर्ण है, और इस खदान के लिए काफी समान है, लेकिन वह उन मामलों के लिए --फोर्स इंडेक्स से चूक गया जब आप कई बार के लिए फ़िल्टर-शाखा का उपयोग कर रहे हैं, और उन्होंने इतनी जानकारी लिखी, कि मेरा संस्करण फिर से शुरू होने जैसा है। इसका।
कोस्टानोस

1
यह वास्तव में मदद की लेकिन मैं का उपयोग करने के लिए आवश्यक -fविकल्प सिर्फ -rfयहाँ git rm --cached -rf --ignore-unmatch oops.isoके बजाय git rm --cached -r --ignore-unmatch oops.isoनीचे प्रति @ lfender6445 के रूप में
drstevok

10

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

$ 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

11
इन आदेशों को तब तक न चलाएं जब तक आप अपने लिए अपार पीड़ा नहीं पैदा करना चाहते। इसने मेरे मूल स्रोत कोड फ़ाइलों का एक बहुत नष्ट कर दिया। मुझे लगता है कि यह GIT में मेरे प्रतिबद्ध इतिहास से कुछ बड़ी फ़ाइलों को शुद्ध करेगा (मूल प्रश्न के अनुसार), हालांकि, मुझे लगता है कि यह कमांड आपके मूल स्रोत कोड ट्री (बड़े अंतर!) से स्थायी रूप से फ़ाइलों को शुद्ध करने के लिए डिज़ाइन की गई है। मेरा सिस्टम: Windows, VS2012, Git Source Control प्रदाता।
कंटीनैगो

2
मैंने इस आदेश का उपयोग किया: git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch oops.iso' --prune-empty --tag-name-filter cat -- --allअपने कोड से पहले के बजाय
कोस्टानोस

9

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

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


8

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


7

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

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

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

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


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

5

यह आपके इतिहास से इसे हटा देगा

git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch bigfile.txt' --prune-empty --tag-name-filter cat -- --all

यह मेरे लिए काम किया धन्यवाद !!
सोनाजा

यह मेरे मामले में काम करता है। मैं इसे आपकी मास्टर शाखा पर चलाता हूं।
एस। डोमेंग

4

मैंने मूल रूप से इस जवाब पर क्या किया था: https://stackoverflow.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

यह काम नहीं किया, क्योंकि मैं चीजों को बहुत नाम बदलना और स्थानांतरित करना पसंद करता हूं। इसलिए कुछ बड़ी फ़ाइल उन फ़ोल्डरों में थीं जिनका नाम बदल दिया गया है, और मुझे लगता है कि gc उन फ़ाइलों के संदर्भ की वजह से उन फ़ाइलों के संदर्भ को हटा नहीं सकता 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) 32MB से 388KB तक बदल गया, यहां तक ​​कि फ़िल्टर-शाखा भी साफ़ नहीं हो सकी।


4

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

# Do it in a new testing branch
$ git checkout -b test

# Remove file-name from every commit on the new branch
# --index-filter, rewrite index without checking out
# --cached, remove it from index but not include working tree
# --ignore-unmatch, ignore if files to be removed are absent in a commit
# HEAD, execute the specified command for each commit reached from HEAD by parent link
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch file-name' HEAD

# The output is OK, reset it to the prior branch master
$ git checkout master
$ git reset --soft test

# Remove test branch
$ git branch -d test

# Push it with force
$ git push --force origin master

2

Git एक्सटेंशन का उपयोग करें , यह एक UI उपकरण है। इसमें "फाइल्स लार्ज फाइल्स" नाम का एक प्लगइन है, जो रिपोजिटरी में लेज फाइलों को ढूंढता है और उन्हें अनुमति से हटाने की अनुमति देता है।

इस उपकरण का उपयोग करने से पहले 'git फ़िल्टर-शाखा' का उपयोग न करें, क्योंकि यह 'फ़िल्टर-शाखा' द्वारा निकाली गई फ़ाइलों को खोजने में सक्षम नहीं होगा (Altough 'फ़िल्टर-शाखा' भंडार पैक फ़ाइलों से फ़ाइलों को पूरी तरह से नहीं हटाता है) ।


यह विधि बड़े रिपॉजिटरी के लिए बहुत धीमी है। बड़ी फ़ाइलों को सूचीबद्ध करने में एक घंटे से अधिक समय लगा। फिर जब मैं फ़ाइलों को हटाने के लिए जाता हूं, तो एक घंटे के बाद यह केवल 1/3 होता है, पहली फ़ाइल को संसाधित करने के माध्यम से जिसे मैं हटाना चाहता हूं।
kristianp

हां, इसकी गति धीमी है, लेकिन क्या यह काम करता है ... क्या आप कुछ जल्दी जानते हैं?
Nir

1
इस पृष्ठ पर एक अन्य उत्तर के रूप में, लेकिन BFG रेपो-क्लीनर का उपयोग नहीं किया है।
kristianp

2

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

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


2

इस सूत्र में बहुत अच्छे उत्तर हैं, लेकिन इस बीच उनमें से कई पुराने हैं। उपयोग करना git-filter-branchअब अनुशंसित नहीं है, क्योंकि इसका उपयोग करना मुश्किल है और बड़े भंडार पर धीमी गति से धीमी गति से।

git-filter-repo उपयोग करने के लिए बहुत तेज और सरल है।

git-filter-repoएक पायथन लिपि है, जो गीथूब पर उपलब्ध है: https://github.com/newren/git-filter-repo

आपको केवल एक फ़ाइल चाहिए: Python3 स्क्रिप्ट git-filter-repo। इसे उस पथ पर कॉपी करें जो PATH चर में शामिल है। विंडोज पर आपको स्क्रिप्ट की पहली लाइन (INSTALL.md देखें) बदलनी पड़ सकती है। आपको अपने सिस्टम पर स्थापित Python3 की आवश्यकता है, लेकिन यह कोई बड़ी बात नहीं है।

पहले आप दौड़ सकते हैं

git filter-repo --analyze

यह आपको यह निर्धारित करने में मदद करता है कि आगे क्या करना है।

आप अपनी डीवीडी-रिप फ़ाइल को हर जगह हटा सकते हैं:

 git filter-repo --invert-paths --path-match DVD-rip

फ़िल्टर-रेपो वास्तव में तेज़ है। फ़िल्टर-शाखा द्वारा मेरे कंप्यूटर पर लगभग 9 घंटे तक चलने वाला कार्य, फ़िल्टर-रेपो द्वारा 4 मिनट में पूरा किया गया। आप फ़िल्टर-रेपो के साथ कई और अच्छे काम कर सकते हैं। उस के लिए प्रलेखन देखें।

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


1

जब आप इस समस्या में भाग लेते हैं, 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/

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


आपको होमब्रे में यह मिलना चाहिए
कैमरून ई

0

अन्य git filter-branch(धीमी लेकिन शुद्ध गिट समाधान) और बीएफजी (आसान और बहुत अच्छा प्रदर्शन करने वाला) के अलावा, अच्छे प्रदर्शन के साथ फ़िल्टर करने के लिए एक और उपकरण भी है:

https://github.com/xoofx/git-rocket-filter

इसके विवरण से:

git-filter-branchनिम्नलिखित अनूठी विशेषताओं को प्रदान करते हुए git-रॉकेट-फिल्टर का उद्देश्य कमांड के समान है:

  • कमिट्स और पेड़ों का तेजी से पुनर्लेखन (x10 से x100 के आदेश से)।
  • अंतर्निर्मित श्वेत-सूचीकरण के लिए समर्थन में (फ़ाइल या निर्देशिकाओं को रखता है) और ब्लैकम-ऑप्शन के साथ काली-सूचीकरण।
  • ट्री-फ़िल्टरिंग के लिए पैटर्न की तरह .gitignore का उपयोग करें
  • फास्ट और आसान सी # स्क्रिप्टिंग दोनों को छानने और पेड़ को छानने के लिए
  • फाइल / डायरेक्टरी पैटर्न के अनुसार ट्री-फ़िल्टरिंग में स्क्रिप्टिंग के लिए समर्थन
  • मर्ज के कमिट सहित स्वचालित रूप से खाली / अपरिवर्तित प्रतिबद्धता को पूर्ववत करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.