गिट रिपॉजिटरी के इतिहास को ढहाना


85

हमारे पास एक गिट परियोजना है जिसका काफी बड़ा इतिहास है।

विशेष रूप से, परियोजना की शुरुआत में परियोजना में काफी द्विआधारी संसाधन फाइलें थीं, इन्हें अब हटा दिया गया है क्योंकि वे प्रभावी रूप से बाहरी संसाधन हैं।

हालाँकि, हमारे भंडार का आकार> 200MB है (कुल जाँच वर्तमान में ~ 20MB है) इन फाइलों के पहले होने के कारण।

हम जो करना चाहते हैं वह इतिहास "ढह" रहा है ताकि रिपॉजिटरी प्रतीत होता है कि बाद के संशोधन से बनाया गया था। उदाहरण के लिए

1-----2-----3-----4-----+---+---+
                   \       /
                    +-----+---+---+
  1. रिपोजिटरी बनाई
  2. बाइनरी फ़ाइलों का बड़ा सेट जोड़ा गया
  3. बाइनरी फ़ाइलों का बड़ा सेट हटा दिया गया
  4. रिपोजिटरी का नया इरादा 'शुरू'

इसलिए प्रभावी रूप से हम एक निश्चित बिंदु से पहले परियोजना के इतिहास को खोना चाहते हैं। इस बिंदु पर केवल एक शाखा है, इसलिए कई प्रारंभ बिंदुओं आदि से निपटने की कोशिश के साथ कोई जटिलता नहीं है। हालांकि हम इतिहास के सभी को खोना नहीं चाहते हैं और वर्तमान संस्करण के साथ एक नया भंडार शुरू करना चाहते हैं।

क्या यह संभव है, या हम हमेशा के लिए फूला हुआ भंडार पाने के लिए बर्बाद हैं?

जवाबों:


89

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

$ git log --stat       # list all commits and commit messages 

अपनी बाइनरी फ़ाइलों को जोड़ने और हटाने वाले कमिट के लिए यह खोजें और उनके SHA1s को नोट करें, 2bcdefऔर 3cdef3

फिर रेपो के इतिहास को संपादित करने के लिए, rebase -iअपने इंटरैक्टिव विकल्प के साथ कमांड का उपयोग करें , जहां आप अपने बायनेरिज़ को जोड़ते हैं, उसके माता-पिता के साथ शुरू करते हैं। यह आपके $ EDITOR को लॉन्च करेगा और आपको शुरू होने वाले कमिट की एक सूची दिखाई देगी 2bcdef:

$ git rebase -i 2bcdef^    # generate a pick list of all commits starting with 2bcdef
# Rebasing zzzzzz onto yyyyyyy 
# 
# Commands: 
#  pick = use commit 
#  edit = use commit, but stop for amending 
#  squash = use commit, but meld into previous commit 
# 
# If you remove a line here THAT COMMIT WILL BE LOST.
#
pick 2bcdef   Add binary files and other edits
pick xxxxxx   Another change
  .
  .
pick 3cdef3   Remove binary files; link to them as external resources
  .
  .

squash 3cdef3दूसरी पंक्ति के रूप में सम्मिलित करें और उस पंक्ति को हटा दें जो pick 3cdef3सूची से कहती है। अब आपके पास इंटरैक्टिव के लिए क्रियाओं की एक सूची है rebaseजो उन कमिटों को जोड़ती है जो आपके बायनेरिज़ को एक कमिट में जोड़ते हैं और हटाते हैं जिनका अंतर उन कमिट्स में बस किसी भी अन्य परिवर्तन है। तब यह क्रम में आने वाले सभी के बाद फिर से लागू होगा, जब आप इसे पूरा करने के लिए कहेंगे:

$ git rebase --continue

इसमें एक या दो मिनट का समय लगेगा।
अब आपके पास एक रेपो है जो अब बायनेरिज़ के आने या जाने का नहीं है। लेकिन वे अभी भी जगह लेंगे, क्योंकि डिफ़ॉल्ट रूप से, Git लगभग 30 दिनों के लिए परिवर्तन करता रहता है, इससे पहले कि वे कचरा एकत्र कर सकें, ताकि आप अपना मन बदल सकें। यदि आप उन्हें अभी निकालना चाहते हैं:

$ git reflog expire --expire=1.minute refs/heads/master
      #all deletions up to 1 minute  ago available to be garbage-collected
$ git fsck --unreachable      # lists all the blobs(files) that will be garbage-collected
$ git prune
$ git gc                      

अब आपने ब्लोट को हटा दिया है लेकिन अपने शेष इतिहास को रखा है।


7
आपको बस यह याद रखना है कि क्या अन्य पहले से ही उस भंडार से खींच चुके हैं, इतिहास को फिर से लिखना उनके खींचने को भ्रमित करेगा। गिट-रिबास मैनुअल बताता है कि उन अन्य रेपो को कैसे पुनर्प्राप्त किया जाए। kernel.org/pub/software/scm/git/docs/git-rebase.html
ओटो

यह उपयोगकर्ता की विशिष्ट समस्या के लिए एक शानदार उत्तर है, लेकिन वास्तविक प्रश्न के लिए नहीं! davitenio का उत्तर वास्तविक प्रश्न के लिए एक महान उत्तर है।
सैम वाटकिंस

27

आप git filter-branchअपनी शाखा की प्रतिबद्ध संख्या 4 को नया रूट बनाने के लिए ग्राफ्ट के साथ उपयोग कर सकते हैं । फ़ाइल .git/info/graftsको केवल एक पंक्ति के साथ बनाएं जिसमें कमिट नंबर 4 का SHA1 हो।

यदि आप अब करते हैं git logया gitkआप देखेंगे कि वे कमांड आपकी शाखा के रूट के रूप में प्रतिबद्ध नंबर 4 प्रदर्शित करेंगे। लेकिन वास्तव में आपके भंडार में कुछ भी नहीं बदला होगा। आप नष्ट कर सकते हैं .git/info/graftsऔर के उत्पादन git logया gitkपहले की तरह हो जाएगा। वास्तव में कमिट नंबर 4 बनाने के लिए आपको git filter-branchबिना कोई तर्क दिए नई रूट को चलाना होगा ।


यह रिबेस से बेहतर है क्योंकि इसमें मर्ज कमिट को संरक्षित करने के मुद्दे नहीं हैं, और टाइमस्टैम्प को बदलने का कारण नहीं है। आसान और तेजी से सभी रिबेज तरीकों से भी।
mmrobins 10

वास्तव में, क्या उन सभी कमियों को शारीरिक रूप से हटाने का एक तरीका है जो अब उस शाखा का हिस्सा नहीं हैं? git gc --prune=0उन्हें साफ करने के लिए प्रतीत नहीं होता है।
वेरोजेन

1
@verhogen git gc --prune=nowशारीरिक रूप से सभी कमिटों को साफ़ करता है जो अब संदर्भित नहीं हैं। यदि यह आपके लिए काम नहीं करता है, तो आपके पास कुछ रिमोट ट्रैकिंग शाखा हो सकती है जो अभी भी पुराने रूट का संदर्भ देती है। साथ सूची git branch -rदें, फिर दूरस्थ शाखा को उदाहरण के लिए हटा दें git branch -rd origin/masterऔर फिर git gc --prune=nowदोबारा चलाएं ।
कायहर

20

जेस्पर की पोस्ट की बदौलत मैंने देखा git-filter-branch- जो वास्तव में आप चाहते हैं। ऐसा लगता है कि आप अपने पहले के कमिट्स को भी बरकरार रख सकते हैं, सिवाय इसके कि जब आपकी बिग फाइल्स को हटाया गया था, तब वे संशोधित हो जाएंगे। से Git फिल्टर शाखा आदमी पेज :

मान लीजिए कि आप किसी फ़ाइल (गोपनीय जानकारी या कॉपीराइट उल्लंघन से) को हटाना चाहते हैं:

git फ़िल्टर-शाखा - tree-filter 'rm फ़ाइल नाम' HEAD

उस आदमी पृष्ठ को पढ़ना सुनिश्चित करें ... स्पष्ट रूप से आप यह सुनिश्चित करने के लिए अपने भंडार के एक अतिरिक्त क्लोन पर यह करना चाहते हैं कि यह उम्मीद के मुताबिक काम करता है।


2
जीथब के लिंक की जाँच करें ... गिट-फ़िल्टर-ब्रांच कमांड के साथ कुछ शक्तिशाली विकल्प हैं: help.github.com/articles/remove-sensitive-data
ricosrealm

5

है git-fast-exportआप के लिए क्या देख रहे हैं?

NAME
   git-fast-export - Git data exporter

SYNOPSIS
   git-fast-export [options] | git-fast-import

DESCRIPTION
   This program dumps the given revisions in a form suitable to be piped into git-fast-
   import(1).

   You can use it as a human readable bundle replacement (see git-bundle(1)), or as a kind
   of an interactive git-filter-branch(1).
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.