Git'te silindikten sonra bir dalı kurtarabilir miyim?


1066

Eğer git branch -d XYZkoşarsam, şubeyi kurtarmanın bir yolu var mı? Şube sil komutunu çalıştırmamışım gibi geri dönmenin bir yolu var mı?


4
Kabul edilen cevap hakkında gerçekten harika bir not, şube kökünden silinmiş olsa bile işe yaramasıdır! Yanlışlıkla silindikten sonra artık yerel olarak sahip olmadığım birkaç dalı kurtardım.
theblang

Yanıtlar:


1955

Evet, git reflogsilinen şubenizin ucundaki taahhüt için SHA1'i yapabilmeli ve bulabilmelisiniz git checkout [sha]. Ve bu taahhütte git checkout -b [branchname]bulunduktan sonra , sadece şubeyi oradan yeniden oluşturabilirsiniz.


Bu yoğun / tek katmanlı sürüm için @Cascabel'a teşekkür ederiz.

Tek adımda yapabilirsiniz:

git checkout -b <branch> <sha>

477
Tek bir adımda bunu yapabilirsiniz: git checkout -b <branch> <sha>.
Cascabel

200
Hızlı ipucu - Şubeyi yeni sildiyseniz terminalinizde bunun gibi bir şey görürsünüz - "Şube <your-branch> (<sha>)" silindi. Ve sonra süper kolay - sadece bunu kullanın <sha>. Örneğin, yukarıda belirtildiği gibi -git checkout -b <branch> <sha>
Snowcrash

6
Evet sadece terminalinizde yukarı kaydırın (siz yapmadıysanız CMD+K)
neaumusic

42
Varsayılan olarak kısaltılmış olanın git reflog --no-abbrevtamamını görmek için kullanın <sha>.
jkulak

5
Silinen şubenin gölgesini bulmakta zorluk çeken benim gibi herkes için: Yapabildim git checkout remotes/origin/deleted_branch.
Jeff Irwin

161

Çoğu zaman ulaşılamayan taahhütler reflogdadır. Bu nedenle, denenecek ilk şey,git reflog (reflog'u görüntüleyen) komutunu kullanarak reflog'a bakmaktır HEAD.

Taahhüt hala mevcut olan belirli bir dalın parçasıysa, daha kolay bir şey komutu kullanmaktır git reflog name-of-my-branch. Ayrıca uzaktan kumanda ile de çalışır, örneğin zorla iterseniz (ek tavsiye: her zamangit push --force-with-lease hataları daha iyi önlemeyi tercih edin ve daha kurtarılabilir).


Taahhütleriniz reflogunuzda değilse (belki de reflogda yazmayan bir üçüncü taraf aracı tarafından silindiği için), şubemi böyle bir komut kullanarak bulunan taahhüdün sha'sına sıfırlayarak bir dalı başarıyla kurtardım ( tüm sarkan taahhütleri içeren bir dosya oluşturur):

git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

Birden fazla kez kullanmanız gerekiyorsa (veya bir yere kaydetmek istiyorsanız), bu komutla bir takma ad da oluşturabilirsiniz ...

git config --global alias.rescue '!git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt'

ve ile kullanın git rescue

Bulunan taahhütleri araştırmak için, her bir komutu, bunlara bakmak için bazı komutlar kullanarak görüntüleyebilirsiniz.

İşleme meta verilerini görüntülemek için (yazar, oluşturma tarihi ve işleme mesajı):

git cat-file -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Farkları görmek için:

git log -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Taahhüdünüzü bulduktan sonra şu taahhütte bir şube oluşturun:

git branch commit_rescued 48540dfa438ad8e442b18e57a5a255c0ecad0560

Windows altında olan ve GUI'leri sevenler için GitExtensions ile taahhütleri (ve birleşik aşamalı dosyaları) kolayca Repository=> Git maintenance=> özelliğini kullanarak kurtarabilirsiniz .Recover lost objects...


Silinen aşamalı dosyaları kolayca kurtarmak için benzer bir komut: https://stackoverflow.com/a/58853981/717372


2
Büyük yardım. Yerel repoda olmayan kayıp bir işim vardı. Oradaki ilk komut, sunucuda bulmama yardımcı oldu. +1
Sean Adkinson

1
git kurtarma takma adı bir nimettir !!! Katkıda bulunduğunuz için çok teşekkür ederim!
72A12F4E

2
Hayatımı kurtardın.
Jed Lynch

Patrick Koorevaar'ın yanıtı bana yardımcı oldu, çünkü son silinen dallanmış taahhütlerimi bilmiyorum <sha>.
Monir Khan

@ Monir-Khan Ve? Neyi sonuçlandırmalıyım? Patrick yanıtı, komutumun sadece bir kopyası / yapıştırmasıdır (bir hata ile: taahhütlere göre filtrelemeyi unuttu) ...
Philippe

45

Bir GUI kullanmak isterseniz, tüm işlemi gitk ile yapabilirsiniz.

gitk --reflog

Bu, şubenin taahhüt geçmişini şubenin silinmemiş gibi görmenizi sağlayacaktır. Şimdi şubeye en son taahhüdü sağ tıklayın ve menü seçeneğini seçin Create new branch.


28

En çok oy alan çözüm aslında talep edilenden daha fazlasını yapıyor:

git checkout <sha>
git checkout -b <branch>

veya

git checkout -b <branch> <sha>

taahhüt etmeyi unutmuş olabileceğiniz son değişikliklerle birlikte sizi yeni şubeye taşıyın. Niyetiniz olmayabilir, özellikle de şubeyi kaybettikten sonra "panik modunda".

Daha temiz (ve daha basit) bir çözüm tek astar gibi görünüyor ( <sha>ile birlikte bulduktan sonra git reflog):

git branch <branch> <sha>

Şimdi ne mevcut dalınız ne de taahhütlü değişiklikler etkilenmiyor. Bunun yerine, sonuna kadar yalnızca yeni bir dal oluşturulacaktır <sha>.

Bahşiş değilse, yine de işe yarayacak ve daha kısa bir dal <sha>alacaksınız, doğru olana kadar yeni ve yeni dal adı ile tekrar deneyebilirsiniz .

Son olarak, başarıyla geri yüklenen dalı adını veya başka bir şeye yeniden adlandırabilirsiniz:

git branch -m <restored branch> <final branch>

Söylemeye gerek yok, başarının anahtarı doğru taahhüdü bulmaktı <sha>, bu yüzden taahhütlerinizi akıllıca adlandırın :)


14

Tfe yanıtına ekleme : Git kaynakları alanında (git.git deposunda) git-resurrect.sh betiği vardır contrib/, bu da size yardımcı olabilir.

git-resurrect <name>denilen bir şube ipucunun izlerini bulmaya <name>çalışır ve diriltmeye çalışır. Şu anda, reflog ödeme iletileri için ve -rayrıca birleştirme iletileri için aranmaktadır . İle -mve -ttüm hakemlerimizle tarihçesi için taranır Merge <name> into other/ Merge <other> into <name>(sırasıyla) oldukça yavaş ama diğer insanların konu dalları diriltmek olanak veren konuları işleyen.


1
PATH'ime / usr / lib / git-core / eklemek zorunda kalmama rağmen şimdi benim için çalıştı. Ama umduğum mucizeyi gerçekleştirmedi :(
AmanicA

10

Silinen şubemi bulmak ve almak için aşağıdaki komutları kullandım. İlk adımlar gcb'nin açıklamasından alınmıştır.

$ git fsck --full --no-reflogs --unreachable --lost-found > lost
$ cat lost | cut -d\  -f3 > commits
$ cat commits | xargs -n 1 git log -n 1 --pretty=oneline

Şimdi komut açıklamalarına dayanarak git kesin kimliğini (GIT-SHA) arayın ve aşağıdaki komutta kullanın. Önceden bulunan GIT-SHA ile NEW-BRANCH adlı yeni bir şubeye göz atın:

$ git checkout -b NEW-BRANCH GIT-SHA

Çok teşekkür ederim. Adı aramak için biraz zaman aldı, ama buna değer zaman. Eğer taahhüt mesaj dizesini aramak için bir yol varsa, çok daha iyi olurdu.
Monir Khan

9

Eğer bir reflogunuz yoksa, örneğin. reflog özelliği etkin olmayan çıplak bir depoda çalıştığınız ve kurtarmak istediğiniz taahhüt son zamanlarda oluşturulduğundan, başka bir seçenek de yakın zamanda oluşturulan taahhüt nesnelerini bulmak ve bunlara bakmaktır.

.git/objectsÇalıştırılan dizinin içinden :

find . -ctime -12h -type f | sed 's/[./]//g' | git cat-file --batch-check | grep commit

Bu, son 12 saat içinde oluşturulan tüm nesneleri (işlemeler, dosyalar, etiketler vb.) Bulur ve bunları yalnızca işlemeleri gösterecek şekilde filtreler. Bunları kontrol etmek hızlı bir işlemdir.

Ben sözü git-ressurect.sh senaryoyu çalışacaktı Jakub cevabı ilk olsa.


1
Güzel bir alternatif fikir! Komutunuz bir hata veriyor. Sorun "12h" kısmı (aslında "h"). "H" yi kaldırdığımda her şey yolunda gitti. Gönderen man find: "-ctime n - Dosyanın durumu en son n * 24 saat önce değiştirildi." Bu nedenle, son 12 saatlik beklenen davranışa sahip olmak için 12'yi 0,5'e değiştirmeliyiz.
pagliuca

1
Burada OS X 10.8 kullanıyorum, bu yüzden yukarıdaki 'find' bayrakları, gönderdiği sürüme dayanıyor.
Robert Knight

1
Evet, sorunun sürümlerle ilgili olduğundan emin olun! Bu yüzden cevabınızı ilk etapta iptal ettim! İnsanların parametrelerin farklı olabileceğini fark etmesi için yorum yaptım.
pagliuca

9

İçin GitHub'dan Git olmayan kullanıcıların yüklü:

GitHub web sitesinden geri yüklemek isterseniz , repo ile ilgili olayların bir listesini almak için API'larını kullanabilirsiniz :

İlk

  • şu SHA'ları (sağlama karmaları) bulun:

    curl -i https://api.github.com/repos/PublicUser/PublicRepo/events

    ... veya özel depolar için:

    curl -su YourUserName https://api.github.com/repos/YourUserName/YourProject/events

    (GitHub şifresi istenecektir)

    • (Repo iki faktörlü kimlik doğrulaması gerektiriyorsa, aşağıdaki bu cevaba ilişkin yorumlara bakın.)

Sonraki

  • GitHub'a gidin ve sonsuza kadar silinecek yeni bir geçici şube oluşturun ( Chrome tercih edilir).

   • Dallara gidin ve bunu silin.

   •   Aynı sayfada, yeniden yüklemeden DevTools, Ağ panelini açın. Şimdi hazırlanın ...

   • Geri yükle'yi tıklayın. Yeni bir "hat" göreceksiniz. Üzerine sağ tıklayın ve "cURL olarak kopyala" yı seçin ve bu metni bazı düzenleyicilere kaydedin.

   Kod kopyalanamaz hattı, bu bir ucuna • Ekleme: -H "Cookie=".

Şimdi şöyle bir şey almalısınız:

    curl 'https://github.com/UserName/ProjectName/branches?branch=BranchSHA&name=BranchName' -H 'Cookie:' -H 'Origin: https://github.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US' -H 'User-Agent: User-Agent' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: https://github.com/UserName/ProjectName/branches' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=token' --compressed

Son adım

  • "BranchSHA" yerine SHA karma ve BranchName yerine istenen ad (BTW, şube web yeniden adlandırmak için büyük bir hack) ile değiştirin. Çok yavaş değilseniz, bu isteği yine de yapmanız gerekir. Örneğin, bir terminale kopyalayıp yapıştırmanız yeterlidir.

PS

Bunun "en basit çözüm" veya "doğru" çözüm olmadığını anlıyorum, ancak birisinin yararlı bulması durumunda sunulmaktadır.


1
Yukarıdakiler, güvenmeyen git reflogve bu nedenle örneğin uzak bir dalı sildiğinizde ve bilgisayardan erişimi kaybettiğinde yararlı bir şey elde edilmediğinde yararlı olan az sayıda kişiden biridir reflog. Ne zaman Not Github OAuth veya iki faktörlü kimlik doğrulamasını kullanarakcurl komut formunun olur: curl -u username:token https://api.github.com/useryacurl -H "Authorization: token TOKEN" https://api.github.com/repos/USER_OR_ORG_NAME/REPO_NAME/events
TT--

@ TT-- vay, yardım ettiğine sevindim! ve auth
token'a katkınız

8

Silinecek şubeye başka bir şube tarafından erişilip erişilemeyeceğini anladığımdan, kullanarak güvenli bir şekilde silebilirsiniz.

git branch -d [branch]

ve işin kaybolmaz. Bir dalın anlık görüntü değil, bir işaretçi olduğunu unutmayın. Böylece bir dalı sildiğinizde bir işaretçiyi silmiş olursunuz.

Başka bir şubeye ulaşamayan bir şubeyi silerseniz, işinizi bile kaybetmezsiniz. Tabii ki taahhüt karmasını kontrol etmek kadar kolay olmayacak, ama yine de yapabilirsiniz. Bu nedenle Git, kullanılarak erişilemeyen bir dalı silemez -d. Bunun yerine kullanmak zorundasın

git branch -D [branch]

Bu Scott Chacon Git hakkında video izlemek gerekir bir parçasıdır. Dallar ve bunları nasıl sileceği hakkında konuşurken 58. dakikayı kontrol edin.

GitHub'dan Scott Chacon ile Git'e Giriş


7
Bu soruya cevap vermeye nasıl yardımcı oluyor?
Dmitri Zaitsev

6
Askerlere, şubelerin içerik barındırmadığını ancak aslında işaretçi olduğunu söylemek. Şubeleri silmekten korkmanıza gerek yok .. Silinenle aynı taahhüde işaret eden yenilerini oluşturabilirsiniz .... Vay canına! Bu soruyu sorduğumda hala hatırlıyorum. 2012'ye iyi zamanlar!
fabiopagoti

1
AT LAST üç ekran kaydırmak zorunda sorunu cevap bir cevap bulmak zorunda: bir şube silmek sadece bir işaretçi siliniyor. Burada veri kaybı durumu yok, kurtarılacak tek şey nereye işaret ettiği. Doğrudan giden cevaplar reflogaşırıya kaçar.
RomainValeri

5

Tüm bunları yerel olarak gerçekleştirdiğinizden emin olun ve Bitbucket Bulut'a gitmeden önce repounuzun istediğiniz durumda olduğunu doğrulayın. Mevcut repoyu klonlamak ve önce bu çözümleri test etmek de iyi bir fikir olabilir.

  1. Şube yeni sildiyseniz terminalinizde böyle bir şey görürsünüz:
    Deleted branch <your-branch> (was <sha>)

Şubeyi geri yüklemek için şunu kullanın:

    git checkout -b <branch> <sha>

Kafanızın üst kısmındaki 'sha' bilmiyorsanız:

  1. Aşağıdakileri kullanarak silinen şubenizin ucundaki taahhüt için 'sha' yı bulun:
    git reflog
  1. Şubeyi geri yüklemek için şunu kullanın:
    git checkout -b <branch> <sha>

Taahhütleriniz reflogunuzda değilse:

  1. Şöyle bir komut kullanarak şubenizi şubeye geri yükleyerek bir şubeyi kurtarmayı deneyebilirsiniz:
    git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

Daha sonra, aşağıdakilerden birini kullanarak her bir taahhüdü görüntüleyebilirsiniz:

    git log -p <commit>
    git cat-file -p <commit>

4

Silinmiş bir dalı kurtarmak için, önce reflog geçmişini gözden geçirin,

git reflog -n 60

Burada n, son n işlemeyi ifade eder. Sonra uygun kafayı bulun ve o kafa ile bir dal oluşturun.

git branch testbranch HEAD@{30}

4

İstemediğim birkaç taahhüdü temizlemeye çalışmak için uzaktan bir şubeyi yeniden temellendirdim ve istediğim doğru olanları şifreleyecektim. Tabii SHA'ları yanlış yazdım ...

İşte onları nasıl buldum (çoğunlukla cevaplardaki şeylerden daha kolay bir arayüz / etkileşim):

İlk olarak, günlüğünüzde gevşek taahhütlerin bir listesini oluşturun. Bunu en kısa zamanda yapın ve çöp toplayıcı tarafından atılabileceğinden çalışmayı bırakın.

git fsck --full --no-reflogs --unreachable --lost-found > lost

Bu, lostbakmak zorunda olduğunuz tüm taahhütleri içeren bir dosya oluşturur . Hayatımızı kolaylaştırmak için, sadece SHA'yı ondan keselim:

cat lost | cut -d\  -f3 > commits

Şimdi commitsbakmanız gereken tüm taahhütleri içeren bir dosyanız var.

Bash kullandığınızı varsayarsak, son adım:

for c in `cat commits`; do  git show $c; read; done

Bu, her biri için fark ve taahhüt bilgilerini gösterecektir. Ve basmanızı bekleyin Enter. Şimdi istediklerinizin hepsini yazın ve sonra kiraz alın. Bunları tamamladıktan sonra sadece Ctrl-C yapın.



1

Önce git'e gidin ve projenize taşıyın:

cd android studio project
cd Myproject
then type :
git reflog

Hepiniz değişikliklerin bir listesi var ve referans numarası ref sonra almak
android studio veya git betcha ödeme . Başka bir çözüm ref numarasını almak ve git git aşağı android studio tıklayın sonra çıkış etiketi tıklayın veya referans numarası geçmiş revizyon sonra lol şube var.


1

Tfe'nin cevabına ek olarak, taahhüt edilen çöp toplanmadıkça, belirtilen bu işlemle kurtarabilirsiniz. Git dalı, yalnızca taahhüt ağacındaki belirli bir taahhüdün göstergesidir. Ancak işaretçiyi silerseniz ve bu daldaki taahhütler varolan başka bir dalla birleştirilmezse, git sarkan bir işlem olarak davranır ve düzenli aralıklarla otomatik olarak çalışabilecek çöp toplama işlemi sırasında bunları kaldırır.

Şubeniz mevcut bir şubeyle birleştirilmemişse ve çöp toplanmışsa, şubenin mevcut bir şubeden çatallandığı noktaya kadar tüm taahhütleri kaybedersiniz.


1

İlgili bir sorun: "Silinen şubelerin ne olduğunu öğrenme" araması yaptıktan sonra bu sayfaya geldim.

Birçok eski şubeyi silerken, yeni şubelerden birini yanlışlıkla sildiğimi hissettim, ancak kurtarmak için adını bilmiyordum.

Son zamanlarda hangi şubelerin silindiğini öğrenmek için aşağıdakileri yapın:

Git URL'nize giderseniz, bu şuna benzer:

https://your-website-name/orgs/your-org-name/dashboard

Ardından, yakın geçmişte silinenlerin, kimin tarafından silindiğinin akışını görebilirsiniz.


Elbette. Yukarıdaki cevap GitHub içindir. GitHub'ı yerel olarak kurduk. Soru sorduğunuz için teşekkürler.
Manohar Reddy Poreddy

1

Bunu şubeyi sildiğim bilgisayarda yaptım:

git reflog

tepki:

74b2383 (develope) HEAD@{1}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: checkout: moving from develope to master
74b2383 (develope) HEAD@{3}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{4}: reset: moving to HEAD
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{5}: clone: from http://LOCALGITSERVER/myBigProject/Android.git

ve ben bu komut ile şube almak:

git checkout -b newBranchName 74b2383


0

Sadece kullanarak bana git reflogdönmedi sha. Sadece commit id(8 karakter uzunluğunda ve bir sha çok daha uzundur)

Ben de kullandım git reflog --no-abbrev

Ve sonra yukarıda belirtilenle aynı şeyi yapın: git checkout -b <branch> <sha>


her zaman kısaltılmış 8 karakter sha kullanabilirsiniz, tam sha kullanmak zorunda değilsiniz
Michael Dreher

0

VSCode kullanıyorsanız ... ve şubenizi silmeden önce bir noktada sunucunuzla senkronize ettiyseniz ...

Git şubesi silme işleminin sunucudaki kopyayı değil yalnızca yerel kopyayı sildiğini unutmayın. İlk olarak, Git panelinde (sol araç çubuğundaki git simgesi) dallara bakın ve dalınızın hala "origin / your_branch_name" altında olup olmadığına bakın. Öyleyse, bunu seçin ve kodunuzu geri almalısınız (hemen başka bir yere kopyala / yapıştır / kaydetmenizi öneririz).

Bir "origin / your_branch_name" görmediyseniz GitLens uzantısını yükleyin. Bu, sunucu depolarında görsel olarak gezinmenizi ve sunucuyla eşitlediğiniz kopyayı bulmanızı sağlar. Birden çok deponuz varsa, deponun GitLens'te görünmesini sağlamak için istenen depodan en az bir dosyanın açılmış olması gerekebileceğini unutmayın. Sonra:

  1. GitLens panelini açma

  2. Depoyu genişlet

  3. Bir kategori listesi görmelisiniz: Şubeler / Katkıda Bulunanlar / Uzaktan Kumandalar / Stashes / vb.

YourLostTreasure öğenizi "Şubeler" altında veya "Uzaktan Kumandalar>> Kökeni" altında bulabilirsiniz. Umarım, istenen ada sahip bir şube görürsünüz - genişletirseniz, o branşta değiştirdiğiniz dosyaları görmelisiniz. Dosya adlarını açmak için çift tıklayın ve hemen bu kodu yedekleyin.

Kayıp dalınızı hemen görmüyorsanız, etrafta dolaşın ve umut verici bir şey bulursanız, hemen açın ve kodu alın. TheGoldenBranch'ı bulana kadar biraz uğraşmak zorunda kaldım ve o zaman bile kodun sonuncusu ya da iki kaydedişi eksikti (muhtemelen bir-Şube-Birleştirme-ama-yanlışlıkla-tıklatma-denemeden önce sunucuya senkronize edemediğim için) Şube-Sil). Aramalarım gereksiz yere uzatıldı çünkü şubeyi ilk bulduğumda ismin doğru olduğundan emin değildim ve bakmaya devam ettim ve ilk dalı tekrar bulmak biraz zaman aldı. (Böylece, Carpe Carpum ve sonra aramaya devam et.)

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.