Git: Silinen (uzak) dalı kurtar


96

İtme sırasında bir şekilde sildiğim iki Git dalını kurtarmam gerekiyor.

Bu iki dal farklı bir sistemde oluşturuldu ve sonra benim "paylaşılan" (github) havuzuma gönderildi.

Sistemimde, (görünüşe göre) bir getirme sırasında dalları aldım:

~/myfolder> git fetch
remote: Counting objects: 105, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 62 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (62/62), done.
From github.com:mygiturl
 * [new branch]      contact_page -> origin/contact_page
   731d1bb..e8b68cc  homepage   -> origin/homepage
 * [new branch]      new_pictures -> origin/new_pictures

Hemen ardından yerel değişikliklerimi merkezi depoya göndermek için baskı yaptım. Nedense bu şubeler hem yerel sistemimden hem de merkezi depodan silindi:

~/myfolder> git push
Counting objects: 71, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (49/49), 4.99 KiB, done.
Total 49 (delta 33), reused 0 (delta 0)
To git@github.com:mygiturl.git
 - [deleted]         contact_page
 + e8b68cc...731d1bb homepage -> homepage (forced update)
   bb7e9f2..e0d061c  master -> master
 - [deleted]         new_pictures
   e38ac2e..bb7e9f2  origin/HEAD -> origin/HEAD
   731d1bb..e8b68cc  origin/homepage -> origin/homepage
   e38ac2e..bb7e9f2  origin/master -> origin/master
 * [new branch]      origin/contact_page -> origin/contact_page
 * [new branch]      origin/new_pictures -> origin/new_pictures

Dalları doğdukları makineden çıkarmak çok kolay değil, bu yüzden mümkünse onları yerel makinemden almaya çalışıyorum.

Google'da araştırdığım git "geri al" bilgilerinin tümü, kayıp taahhütleri kurtarmakla ilgili. Bu dallar için UID'lerim olmadığından, bunun burada geçerli olduğunu sanmıyorum.

Bunları nasıl geri alabileceğimi bilmek isterim. Ayrıca ilk etapta nasıl silindiklerini ve gelecekte bundan nasıl kaçınabileceğimi de bilmek istiyorum.

DÜZENLEME: istek üzerine, işte repo yapılandırmam

user.name=Craig Walker
user.email=github@softcraft.ca
alias.unadd=reset HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=git@github.com:MyGitURL.git
remote.origin.mirror=true
branch.master.remote=origin
branch.master.merge=refs/heads/master
alias.undo=reset --hard
alias.test=push -f ci HEAD:master
alias.st=status
alias.ci=commit
alias.br=branch
alias.co=checkout
alias.ch=checkout
alias.df=diff
alias.lg=log -p
alias.who=shortlog -s --
remote.ci.url=ContinuousIntegrationGitURL
remote.ci.fetch=+refs/heads/*:refs/remotes/ci/*
branch.photo.remote=origin
branch.photo.merge=refs/heads/photos
remote.foo.url=FooGitURL
remote.foo.fetch=+refs/heads/*:refs/remotes/cynthia/*
branch.homepage.remote=origin
branch.homepage.merge=refs/heads/homepage

Görünüşe göre "alışılmadık" veya uyumsuz bir getirme ve gönderme yapılandırmanız var. git config -lYerel arşiv için ne gösteriliyor?
CB Bailey

Büyük olasılıkla; Ben gönderdim.
Craig Walker

2
Kişisel remote.origin.fetchrefspec ile kullanım için uygun değildir remote.origin.mirror = true. Yansıtmak mı yoksa GitHub deposunu normal bir uzaktan kumanda olarak kullanmak mı istiyorsunuz? Cevabım her iki şekilde de ihtiyacınız olan komutlara sahip olmalıdır.
Chris Johnsen

Tahmin ediyorum ki 2. depoda, aynalama artık bir seçenek değil (bu muhtemelen ilk etapta silmeye neden oldu).
Craig Walker

Yanıtlar:


103

Ben uzman değilim Ama deneyebilirsin

git fsck --full --no-reflogs | grep commit

silinen dalın HEAD yürütmesini bulmak ve geri almak için.


Daha önce fsck'i denedim; hangi işlemin doğru olduğunu nasıl bulacağınızı biliyor musunuz? Denemem gereken 20 tane var.
Craig Walker

1
Bu yaptı; Taahhüt mesajlarını aldıktan git branch <uid>sonra geri aldım. Teşekkürler!
Craig Walker

Duymak güzel. Sizin remotes.origin.mirrorve remotes.origin.fetchayarlarınız arasındaki çelişkiyi de çözdüğünüzden emin olun , aksi takdirde problemle tekrar karşılaşabilirsiniz (veya diğer depolardan kasıtsız olarak saldıran taahhütler).
Chris Johnsen

@Craig: Yardımcı olduğuma sevindim :)
iamamac

3
Bugün tahliye adayı şubesini kaybettim. Commit kimliğini bilmiyordum. Kullanarak kurtarıldı:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
spezifanta

23

sadece iki komut hayatımı kurtarır

1. Bu, önceki tüm HEAD'leri listeleyecektir

git reflog

2. Bu, HEAD'i sildiğiniz işleme geri döndürecektir.

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02

1
Şubeyi yerel olarak hiç kontrol etmedim, bu yüzden HEAD'im hiç orada olmadı, bu nedenle commit kimliğini bulamıyorum git reflog. Deneyebileceğim başka bir şey var mı?
zyy

1
@Zyy ile aynı İşlem, uzaktaki diğer ekip üyesi tarafından silindi, bu yüzden yerel makinemde geri almam gerekiyor (bu işlemi yerel olarak hiç yapmadım) ve geri
itmeliyim

11

Silinen şubeleriniz kaybolmaz, gösterdiğiniz getirme ile origin / contact_page ve origin / new_pictures “uzaktan izleme dalları” na kopyalandı (ayrıca gösterdiğiniz itme ile geri itildi, ancak refs / remote / origin / refs / heads / yerine). Kontrol git log origin/contact_pageve git log origin/new_picturesyerel kopyaları orada olması gerektiğini düşünüyorum ne olursa olsun “güncel” olup olmadığını görmek için. Gösterdiğiniz getirme ve itme arasında bu şubelere (başka bir depodan) herhangi bir yeni taahhüt gönderildiyse, bunları "kaybetmiş" olabilirsiniz (ancak muhtemelen bunları en son bu dalları iten diğer depoda bulabilirsiniz) .

Getirme / İtme Çakışması

Görünüşe göre normal, 'uzak modda' (uzak referanslar / kafalar / yerel olarak referanslar / uzaktan kumandalar / orijin / içinde saklanıyor), ancak 'yansıtma moduna' giriyorsunuz (yerel referanslar / uzak referanslara itiliyor /) . .Git / config dosyanızı kontrol edin ve remote.origin.fetchve remote.origin.pushayarları uzlaştırın .

Yedekleme yapmak

Herhangi bir değişikliği denemeden önce basit bir tar veya zip arşivi veya tüm yerel deponuzu yapın. Bu şekilde, olanlardan hoşlanmıyorsanız, geri yüklenen bir depodan tekrar deneyebilirsiniz.

Seçenek A: Yansıtma olarak Yeniden Yapılandırma

Uzak deponuzu yerel deponuzun bir aynası olarak kullanmayı düşünüyorsanız, şunu yapın:

git branch contact_page origin/contact_page &&
git branch new_pictures origin/new_pictures &&
git config remote.origin.fetch '+refs/*:refs/*' &&
git config --unset remote.origin.push &&
git config remote.origin.mirror true

Ayrıca, ayna modunda çalışıyorsanız (normal şubeleriniz normal uzaktan izleme dallarının yerini alır) faydalı olmadıklarından, tüm referanslarınızı / uzaktan kumandalarınızı / menşe / referanslarınızı silmek isteyebilirsiniz.

Seçenek B: Normal Uzaktan Kumanda Olarak Yeniden Yapılandırma

Ancak bu uzak depoyu birden çok "iş" deposu ile kullanıyormuşsunuz gibi göründüğünden, muhtemelen ayna modunu kullanmak istemezsiniz. Bunu deneyebilirsin:

git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror

Sonra, sonunda uzak repo sahte ref / uzaktan kumanda / menşe ref silmek isteyeceksiniz: git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures ….

Test Basımı

Uzak depoda herhangi bir değişiklik yapmadan git push --dry-runne git pushyapacağını görmeye çalışın . Yapacağını söylediği şeyi beğenmediyseniz, yedeğinizden (tar / zip) kurtarın ve diğer seçeneği deneyin.


1
Uzaktan takip şubelerinin, kopyalanmış olsalar bile saklandığını sanmıyorum. 'git branch -a' onları göstermiyor ve .git dizininde bu adlara sahip hiçbir dosya bulamıyorum. Son olarak, önerdiğiniz "git log" komutları "ölümcül: belirsiz bağımsız değişken 'kaynak / kişi_sayfa': bilinmeyen düzeltme veya çalışma ağacında olmayan yol": - \ Yine de teşekkürler.
Craig Walker

1
Şey, o dallar oradaydı, itme günlüğünüz bunu gösteriyor. Dizinde referans ararken , ek olarak .gitkontrol ettiğinizden emin olun . tüm yerel referanslarınızı (paketlenmiş veya 'gevşek') atacaktır. Onları orijinal olarak GitHub deponuza (farklı bir makinede mi? Başka birinin deposunda mı?) Gönderen repoda referansları hala bulabilmelisiniz. Uzun bir gc ya eriği yapmadıysanız gibi, Bu gerçekleşmediği takdirde sen gerekir sarkan kaydedilmesini incelemek ve bunları tekrar eklemeniz çıktı: . .git/packed_refs.git/refs/git show-refgit fsckgit branch contact_page-recovered <SHA-1-of-dangling-commit>
Chris Johnsen

pack_refs de yoktu. Taahhütler kesinlikle sallanıyordu; nasıl olduğu hakkında hiçbir fikrim yok. Yine de yardımınız için teşekkürler!
Craig Walker

8

Silme işlemi yeterince yeni ise (Oh-NO! Anı gibi), yine de bir mesajınız olmalıdır:

Deleted branch <branch name> (was abcdefghi).

hala koşabilirsiniz:

git checkout abcdefghi

git checkout -b <some new branch name or the old one>


8
  1. commit kimliğini bul

    git reflog

  2. yanlışlıkla sildiğiniz yerel şubeyi kurtarın

    git branch need-recover-branch-name commitId

  3. Uzak dalı daha önce de sildiyseniz, need-recovery-branch-adını tekrar itin

    git push origin need-recover-branch-name


2
Bu benim için çalıştı. Kabul edilen yanıtı tercih ederim çünkü çok daha az adımdı. git reflogTahmin etmek zorunda kalmadan ve ile yapılan taahhüt mesajımı görebildim git show.
theUtherSide

Bu bana 5 gün kesintisiz çalışarak 13 saat kazandırdı. çok teşekkür ederim. Uzaktan ve yerel
şubemi

3

Veriler hala github'da mevcut, eski verilerden yeni bir dal oluşturabilirsiniz:

git checkout origin/BranchName #get a readonly pointer to the old branch
git checkout –b BranchName #create a new branch from the old
git push origin BranchName #publish the new branch

1

"Getirme" ve "push" için uyumsuz bir yapılandırmanız olduğunu düşünüyorum, bu nedenle bu, varsayılan getirme / itme işleminin düzgün bir şekilde dönmemesine neden oldu. Neyse ki, daha sonra sildiğiniz dalları getirdiniz, bu nedenle onları açık bir itme ile yeniden oluşturabilmelisiniz.

git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures

@Chris Johnson'a yaptığım yorumda olduğu gibi, şubelerin artık yerel olarak (asla?) Bulunmadığı görülüyor. Bunu aldığımda git push origin origin/contact_page:contact_page: error: src refspec origin/contact_page does not match any
Craig Walker

Tamam, sanırım ne olduğunu anlıyorum (tam hata yardımcı olsa da). push, silinen dalı güncelledi ve referansı yerel olarak kaldırdı ve bir izleme ref. Ne git rev-parse refs/remotes/origin/origin/contact_pagediyor? Sahte 'ayna' yapılandırması nedeniyle, yerel depoda şimdi my dalına başvurulacak.
CB Bailey

Merhaba Charles; Bunu yazdığımdan beri, yapılandırmamı parçaladım (ve düzelttim), böylece artık (anlamlı) devir ayrıştırma çıktısını alamıyorum. Ancak, uzaktan kumandalarda çift yuvalanmış bir "başlangıç" dizini olduğunu düşünmüyorum.
Craig Walker

0

Kuruluşunuz JIRA veya git'e bağlı başka bir benzer sistem kullanıyorsa, biletin kendisinde listelenen taahhütleri bulabilir ve kod değişikliklerinin bağlantılarına tıklayabilirsiniz. Github şubeyi siler ancak yine de kiraz toplama için mevcut taahhütlere sahiptir.


-1

Çok temkinli görünebilir, ancak kaynak kontrol değişikliklerini yapmadan önce üzerinde çalıştığım şeyin bir kopyasını sık sık sıkıştırırım. Üzerinde çalıştığım bir Gitlab projesinde, birleştirme isteğini birleştirdikten sonra saklamak istediğim bir uzak dalı yanlışlıkla sildim. Taahhüt tarihiyle onu geri almak için tek yapmam gereken tek şey tekrar zorlamaktı. Birleştirme isteği hala Gitlab tarafından izleniyordu, bu nedenle dalın sağında mavi "birleştirilmiş" etiketi hala gösteriyor. Kötü bir şey olması durumunda yerel klasörümü hala sıkıştırdım.

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.