Git: Geçmiş kaydetmeden dosya nasıl kaldırılır?


113

56f06019 kimliğiyle taahhüdüm var (örneğin). Bu işlemde yanlışlıkla büyük dosya (50Mb) teslim ettim. Başka bir kayıtta aynı dosyayı ancak doğru boyutta (küçük) ekliyorum. Şimdi klonladığımda repom çok ağır :( Depomun boyutunu küçültmek için bu büyük dosyayı repo geçmişinden nasıl kaldırırım?


benim durumumda, bu büyük bir dosya değil, veritabanı kredilerini içeren bir yapılandırma dosyası. Git üzerinde çalışıyordum, o sırada .gitignore'un farkında değildim.
Rashi


Yanıtlar:


165

Pro Git kitabının 9. Bölümünde Nesneleri Kaldırma hakkında bir bölüm vardır .

Adımları kısaca burada özetleyeyim:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Daha önce açıklanan filter-branchyeniden ödeme seçeneği gibi , yeniden yazma işlemidir. Geçmişi yayınladıysanız --force, yeni referansları zorlamanız gerekir.

filter-branchYaklaşım çok daha fazla güçlüdür rebaseo yana, bir yaklaşım

  • tüm şubeler / referanslar üzerinde aynı anda çalışmanıza olanak sağlar,
  • herhangi bir etiketi anında yeniden adlandırır
  • dosyanın eklenmesinden bu yana birkaç birleştirme işlemi olsa bile temiz çalışır
  • dosya (a) dal (lar) ının geçmişinde birkaç kez (yeniden) eklendi / kaldırılsa bile temiz çalışır
  • yeni, ilgisiz taahhütler yaratmaz, bunun yerine onlarla ilişkili ağaçları değiştirirken kopyalar. Bu, imzalı taahhütler, taahhüt notları vb. Gibi şeylerin korunduğu anlamına gelir.

filter-branch yedekleri de tutar, böylece yeniden günlüklerin ve çöp toplama işlemlerinin süresi dolmadıkça deponun boyutu hemen azalmaz:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger

1
Bunun windows cmd.exe altında çalışmadığını belirtmek gerekir. Yine de cygwin altında çalışıyor gibi görünüyor.
Sahte İsim

2
Yukarıdaki git filtre dalını tek tırnak yerine çift tırnak kullanarak çalıştırdım (Windows Server 2012 cmd.exe üzerinde)
JCii

1
Benim için işe yarayan bu filtre dalı komut satırı oldu. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Sonra rm --recursive --force .git/refs/originalve rm --recursive --force .git/logs Sonra git prune --expire now ve git gc --aggressive Bu, benim için yukarıda listelenen tam adımlarınızdan daha iyi çalıştı. Git Pro kitabının bağlantısını çok değerli olduğu için dahil ettiğiniz için teşekkür ederiz.
dacke.geo

Filter-branch komutundan sonra, .git klasörünün boyutunu aşağı indirebilmemin tek yolu burada bulunan komutu izlemekti: stackoverflow.com/questions/1904860/… git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = şimdi gc "$ @"
Steve Ardis



0

Etkileşimli modda yeniden temellemeye ihtiyaç duyacaksınız , buradaki bir örneğe bakın: GitHub'da bir kaydı nasıl kaldırabilirim? ve eski taahhütlerin nasıl kaldırılacağı .

Kaydetmeniz HEAD eksi 10 kaydetme düzeyindeyse:

$ git rebase -i HEAD~10

Geçmişinizin basımından sonra, "yeni" geçmişe itmeniz gerekir, zorlamak için eklemeniz gerekir +( itme seçeneklerinde refspec'e bakın ):

$ git push origin +master

Eğer başkaları sizin deponuzu zaten klonladıysa, onları bilgilendireceksiniz, çünkü sadece geçmişi değiştirdiniz.


3
Yani yok değil geçmişinden büyük bir dosya çıkarın. Ayrıca, zorlamanın kanonik yolu git push --forceveya git push -f(insanların dalın itme hedefini bilmesini gerektirmeyen)
sehe

Soruya göre, yeni dosya eski dosyayla tamamen aynı, yani aynı yol. Bu yüzden git rmyolda doğrudan kullanamazsınız .
Loïc d'Anterroches

2
@sehe, büyük dosya ile commit'i ortadan kaldıran bir rebase yaparsanız, tamamen yok olur.
vonbrand

@vonbrand yalnızca yeniden eklediğiniz şubeden. 'Kimden' şubesinin silineceğini varsaymıyorum. Ama evet, bir revizyon ağacı dalını silerseniz bu yardımcı olacaktır: _
sehe

@sehe, elbette, rahatsız edici taahhüdü içeren tüm dalları takip etmelisiniz. Depoda biraz gürleşmeden önceyse, yapacak çok fazla yeniden organizasyonunuz olacaktır. Ancak rebase bunun için bir araçtır.
vonbrand

0

Windows https://stackoverflow.com/a/8741530/8461756 üzerinde aşağıdaki cevabı kullanmayı denedim

Tek tırnak pencerelerde çalışmaz, çift tırnağa ihtiyacınız vardır.

Aşağıdaki benim için çalıştı.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Büyük dosyayı kaldırdıktan sonra, değişikliklerimi github master'a aktarabildim.


0

Silmek için basit bir Komut kullanabilirsiniz

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.