Dallanmayan (sarkan?) Git işlemlerini listeleme ve silme


152

Belirli bir dalın altında olmayan çok sayıda commit içeren bir Git deposum var, git showonları yapabilirim , ancak onları içeren dalları listelemeye çalıştığımda, hiçbir şeyi geri bildirmiyor.

Bunun sarkan taahhütler / ağaç sorunu olduğunu düşündüm (-D dalının bir sonucu olarak), bu yüzden depoyu budanmıştım, ancak bundan sonra hala aynı davranışı görüyorum:

$ git fetch origin

$ git fsck --unreachable
$ git fsck

Çıktı yok, sarkan hiçbir şey yok (değil mi?). Ama taahhüt var

$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...

ve herhangi bir şubeden ulaşılamamaktadır.

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

çıktı vermez.

Bu taahhüdün durumu tam olarak nedir? Tüm commit'leri benzer bir durumda nasıl listeleyebilirim? Böyle taahhütleri nasıl silebilirim?


olası bir kopyası Hatalı birleştirme
Josh Lee

Yanıtlar:


77

Çıktı yok, sarkan hiçbir şey yok (değil mi?)

Reflog'unuzdan atıfta bulunulan kayıtların ulaşılabilir kabul edildiğini unutmayın.

Bu taahhüdün durumu tam olarak nedir? Benzer durumdaki tüm işlemleri nasıl listeleyebilirim

Geçiş --no-reflogsikna etmek git fsckbunları size göstermek için.

Böyle taahhütleri nasıl silebilirim?

Reflog girdilerinizin süresi dolduğunda, bu nesneler de tarafından temizlenecektir git gc.

Son Kullanma tarafından düzenlenir gc.pruneexpire, gc.reflogexpireve gc.reflogexpireunreachableayarlara. Cf. git help config.

Varsayılanların hepsi oldukça makul.


2
Yani basitçe, sarkan taahhütler için yeniden akışların bir süre sonra otomatik olarak kaldırılacağını mı söylüyorsunuz?
MoralCode

2
Temel olarak: evet - sorunun biraz karışık olması dışında. Tüm reflog girişlerinin bir süre sonra otomatik olarak kaldırıldığını söylüyorum , ancak bunu konfigürasyon ayarlarından değiştirebilirsiniz. Bir tek denir taahhüt çünkü sarkan sahip olduğu zaman hiçbir şey reflog girdileri de dahil olmak üzere - - buna işaret ederek, “hareketin sarkan için reflogs” bir şey değildir. Bunlar " ulaşılamayan taahhütler için yeniden kayıtlar " olacaktır.
Aristotle Pagaltzis

"Ulaşılamayan taahhütler için yeniden bloglar" olacaklar. " Ama "reflog'unuzdan atıfta bulunulan kayıtlar ulaşılabilir kabul edilir" dediniz. Öyleyse "ulaşılamayan taahhütler için yeniden bloglar" nasıl bir şey olabilir? Kafam çok karışık.
LarsH

1
Evet, tutarlı değildim. Normalde insanlar reflog hakkında düşünmezler ve "ulaşılamaz" dedikleri zaman, "bir refden" anlamına gelir. git help glossaryOnu bu şekilde tanımlasa bile … “ulaşılabilir” için tanımı bu şekilde daraltılmamış, dolayısıyla çelişkilidir. Komik - yani söylediklerim aslında şu konudaki kafa karışıklığıyla tutarlı gitglossary... Kafa karıştıran kavramlar değil, sadece terminoloji. Mesele şu ki, "sallanan" taahhütler başka hiçbir şeyin işaret etmediği şeylerdir. "Başka türlü ulaşılamayan taahhütler için yeniden bloglar" desem yardımcı olur mu…?
Aristotle Pagaltzis

Bunların hepsi çok kafa karıştırıcı. Basitleştirelim. Şubeye mastergittiğinde yaparsın git commitve bir taahhüt alırsın 000001. Sonra yaparsın git commit --amend, bu da sana taahhüt verir 000002. Artık işaret eden etiket veya dal 000001yok ve günlüğünüzde --reflogseçenek olmadan göremezsiniz , ancak isterseniz yine de ona ulaşabilirsiniz git checkout 000001. Şimdi soru mı olduğu 000001bir sarkan taahhüt veya ulaşılamaz hem taahhüt veya bunların ikisinin de ya?
chharvey

272

Tüm sarkan taahhütleri ve refloglardan ulaşılabilenleri kaldırmak için şunu yapın:

git reflog expire --expire-unreachable=now --all
git gc --prune=now

Ama istediğinin bu olduğundan emin ol. Man sayfalarını okumanızı tavsiye ederim ama işin özü:

git gcerişilemez nesneleri (işlemeler, ağaçlar, bloblar (dosyalar)) kaldırır. Bir dalın geçmişinin bir parçası değilse, bir nesneye ulaşılamaz. Aslında biraz daha karmaşık:

git gc başka şeyler yapar, ancak bunlar burada alakalı değildir ve tehlikeli değildir.

İki haftadan daha genç --prune=nowerişilemeyen nesneler kaldırılmaz, bu nedenle " şimdiye kadar oluşturulmuş erişilemeyen nesneleri kaldır" anlamına gelir.

Nesnelere ayrıca reflog aracılığıyla da ulaşılabilir. Şubeler bir projenin geçmişini kaydederken, yeniden bloglar bu dalların geçmişini kaydeder. Değiştirirseniz, sıfırlarsanız vb. Taahhütler şube geçmişinden kaldırılır, ancak git hata yaptığınızı fark etmeniz durumunda bunları yanınızda tutar. Yeniden günlükler, bir dalda (veya HEAD'de) hangi yıkıcı (ve diğer) işlemlerin gerçekleştirildiğini bulmanın uygun bir yoludur ve yıkıcı bir işlemi geri almayı kolaylaştırır.

Bu yüzden, bir şubeden ulaşılamayan her şeyi gerçekten kaldırmak için yeniden blogları da kaldırmamız gerekiyor. Bunu, yeniden --allblog'ları sona erdirerek yapıyoruz. Yine git tekrar bunu yapmak için değil söylemek zorunda reflogs biraz kullanıcıları korumak için tutar: --expire-unreachable=now.

Yıkıcı işlemlerden kurtulmak için esas olarak reflog'u kullandığım için genellikle --expire=nowbunun yerine kullanıyorum, bu da yeniden blogları tamamen zap ediyor.


1
Size açık olmayan hangi komutları kullanacağınızı söylüyorum - gc yeterli olmamalı mı? Daha önce git-reflog kullanmadıysanız bilemezsiniz. Artık hangi komutları kullanmanız gerektiğini bildiğinize göre, söz konusu seçeneklere man sayfalarında bakmalısınız. Tabii ki bunun yerine oradaki bilgiyi kopyalayabilirim ...
tarsius

1
Aslında tam olarak ne yaptığını söylüyorum: "tüm sarkan taahhütleri ve yeniden bloglardan ulaşılabilenleri kaldırın". Reflogların ne olduğunu bilmiyorsanız: kılavuzu tekrar okuyun.
tarsius

7
Verilen cevap doğru olsa da, @ erikb85, size söylenenler hakkında herhangi bir eğitim olmadığını belirtmekte haklıdır. RTFM ile takip etmek daha da az yardımcıdır. Evet, hepimiz tüm belgeleri okumalıyız. Bazı durumlarda, belki de aramayı yapan kişi, neler olup bittiğini anlayacak kadar dokümantasyona girmiyordur. Bu nedenle, komutların ne yaptığına dair biraz eğitim, bu yanıtı daha sonra bulan herkes için faydalı olacaktır.
Lee Saferite

@LeeSaferite :-) artık tüm mutlusundur
Tarsius

12
git reflog expire --expire-unreachable=now --alltüm zulalarınızı bırakır!
Vsevolod Golovanov

23

Yine de bu konudaki tüm tavsiyeleri takip ettikten sonra aynı sorunu yaşadım:

git reflog expire --expire-unreachable=now --all
git gc --prune=now
git fsck --unreachable --no-reflogs   # no output
git branch -a --contains <commit>     # no output
git show <commit>                     # still shows up

Reflog değilse ve şube değilse, ... etiket olmalıdır !

git tag                             # showed several old tags created before the cleanup

Etiketleri git tag -d <tagname>temizlemeyle kaldırdım ve yeniden yaptım ve eski taahhütler gitmişti.


Etiketler hakkında zaten bir cevap var ( stackoverflow.com/a/37335660/450127 ) ve bu yeni bir şey eklemiyor gibi görünüyor. Bu, önceki cevap lehine kaldırılmamalı mı?
Ian Dunn

Nitekim, bir şekilde bu yanıtı gözden kaçırdım. 4 kişi cevabımı yararlı bulsa da, belki o kadar da yararsız değil mi? Ayrıca tüm olasılıkları tek bir özlü yanıt olarak gruplandırdım.
jakub.g

1
Çoğaltılsa bile, bu sayfa Google Sonucunda görünebilir ve aynı sorunu yaşayan kişilere anında yardımcı olur, insanları doğru cevaba sahip olabilecek bağlantılara defalarca yönlendirmekten daha iyidir .
Alexandre T.

Benim durumumda tüm çözümler kısmi idi. Eksik kısım tam olarak etiketlerdi.
viyps

14
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

Muhtemelen sadece olması gerekiyor

git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042

Uzaktan kumandalardan şubeler hakkında da rapor vermek


teşekkürler, şimdi hala bu taahhüdü tutan uzaktan kumandalarımı / kökenimi / sonraki buldum. nasıl kaldırılır? git push -d origin nextyardımcı olmuyor.
iRaS


teşekkürler - git fetch --prunehile yaptı. ancak tüm yanıtlarda, bu işleme referans veren etiketlere yönelik bir kontrolü kaçırıyorum. Hala kesinleştirme içeren etiketleri nasıl kontrol edeceğimi bilmiyorum (hepsini kaldırdım).
iRaS

Ancak ... bu, yalnızca uzak şubelerden erişilebilen (ve yerel şubelerin bulunmadığı) taahhütlerin erişilebilir olduğu ve bu nedenle git fsck --unreachable, hangi taahhütlerin erişilebilir olduğunu bulmak için ağ üzerinden uzaktan kumanda ile iletişim kurduğu anlamına mı geliyor?
LarsH

1
Kendi sorumu cevapladım ... evet, yalnızca uzak şubelerden erişilebilen (ve yerel şubelerden olmayan) taahhütler erişilebilir kabul edilir; ancak git fsck --unreachablehangi uzak şubelerin hangi taahhütleri içerdiğini bulmak için ağ üzerinden uzaktan kumanda ile iletişim kurması gerekmez. Uzak şube bilgisi yerel olarak, örneğin .git/refs/remotes/origin(veya içinde packed-refs) altında saklanır .
LarsH

8

Benzer bir sorun yaşadım. Koştum git branch --contains <commit>ve sorudaki gibi hiçbir çıktı vermedi.

Ama koştuktan sonra bile

git reflog expire --expire-unreachable=now --all
git gc --prune=now

benim taahhüdüm kullanılarak hala erişilebilirdi git show <commit>. Bunun nedeni, ayrılmış / sarkık "dalındaki" işlemlerden birinin etiketlenmiş olmasıdır. Etiketi kaldırdım, yukarıdaki komutları tekrar çalıştırdım ve altındaydım. git show <commit>geri döndü fatal: bad object <commit>- tam olarak ihtiyacım olan şey. Umarım bu benim kadar sıkışmış başka birine yardımcı olur.


etiketi nasıl çıkardın?
bapors

@bapors Tüm etiketleri listeleyin, söz konusu yürütmeye başvuran birini bulun ve ardından silin. stackoverflow.com/questions/5480258/…
Andrew Larsson

7

Yanlışlıkla aynı duruma çarptım ve zulalarımın ulaşılamaz işleme referans içerdiğini ve bu nedenle ulaşılamaz olduğu varsayılan işleme zulalardan ulaşılabilir olduğunu gördüm.

Bunları gerçekten ulaşılmaz kılmak için yaptım.

git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now

2

git gc --prune=<date>varsayılan olarak iki hafta öncesinden daha eski nesneleri budamaktır. Daha yakın bir tarih ayarlayabilirsiniz. Ancak, gevşek nesneler oluşturan git komutları genellikle git gc --auto'yu çalıştırır (bu, sayıları yapılandırma değişkeni gc.auto'nun değerini aşarsa gevşek nesneleri temizler).

Bu taahhütleri silmek istediğinizden emin misiniz? gc.auto'nun varsayılan ayarı, gevşek nesnelerin mantıksız miktarda bellek kullanmamasını sağlar ve gevşek nesneleri bir süre saklamak genellikle iyi bir fikirdir. Bu şekilde, yarın silinen şubenizin ihtiyaç duyduğunuz bir taahhüdü içerdiğini fark ederseniz, onu kurtarabilirsiniz.

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.