Git reset --hard HEAD ~ 1'i nasıl geri alabilirim?


1158

Aşağıdaki komutun neden olduğu değişiklikleri geri almak mümkün müdür? Öyleyse nasıl?

git reset --hard HEAD~1

8
Git ile olan herhangi bir kayıp taahhüdü kurtarmak için tam bir rehber yazdım. Hatta çizimler var :-) [Check it out] [fixLink] [fixLink]: programblings.com/2008/06/07/…
webmat

12
--hardtaahhüt edilmemiş değişiklikleri atar. Bunlar git tarafından izlenmediğinden, onları git üzerinden geri yüklemenin bir yolu yoktur.
Zaz


1
Bu , dosyalarınızı kurtarmanıza yardımcı olacak harika bir makaledir.
Jan Swart

2
Bu düz Github büyük bir kaynaktır: Git ile (neredeyse) her şeyi nasıl geri alınır
jasonleonhard

Yanıtlar:


1773

Pat Notz doğru. Birkaç gün içinde olduğu sürece taahhüdü geri alabilirsiniz. git, yeni çöpleri açıkça kaldırmasını söylemediğiniz sürece yaklaşık bir ay kadar sonra çöp toplar.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

Örnekte, donanım sıfırlamasının bir sonucu olarak dosya2'nin kaldırıldığını, ancak reflog yoluyla sıfırladığımda yerine yerleştirildiğini görebilirsiniz.


222
SHA1 kullanmaya gerek kalmadan "git reset --hard HEAD @ {1}" kullanabilirsiniz. Çoğu durumda "git reset --hard ORIG_HEAD" kullanmak yeterli olmalıdır.
Jakub Narębski

39
git log -greflog görüntülemek için biraz daha güzel bir yol olabilir git reflog.
Dan Moulding

60
Bu konuda çok önemli bir uyarı var .. ve bu "--hard" kısmı. --hard yerel taahhüt edilmemiş değişikliklerinizi uçurur. Ve onları böyle geri alamazsınız (hiçbir yerde taahhüt edilmedikleri için). Bu konuda yapabileceğiniz hiçbir şey olmadığına inanıyorum :(
Michael Anderson

3
^ Sadece bir sıfırlama yapmadan önce yerel değişikliklerinizi saklayabileceğinizi biliyorsunuz - sert ve sonra onları patlatın ve hiçbir şey kaybetmeyin! Git gitmeyi sevmeliyim.
Lethjakman

5
Tercihim git reflogüzerinde git log -gsen sha1, BAŞ bilgi tek satıra tüm bilgileri almak ve tüm dizilmiş mesajları işlemek çünkü. Okuması çok daha kolay.
Aralık'ta kar yağışı

371

Yapmak istediğiniz, geri yüklemek istediğiniz taahhüdün sha1 değerini belirtmektir. Ref1 ( git reflog) öğesini inceleyerek ve sonra

git reset --hard <sha1 of desired commit>

Ama çok fazla beklemeyin ... birkaç hafta sonra git sonunda bu taahhüdü referanssız olarak görür ve tüm lekeleri siler.


2
birkaç dakika önce kendim için uyarı : bu, tüm değişiklikleri sıfırlayacaktır. izlenmeyen dosyalara dokunmaz.
aexl

175

Cevap yukarıdaki ayrıntılı yanıtta gizlidir, şunları yapabilirsiniz:

$> git reset --hard HEAD@{1}

( Git reflog show çıktısına bakın )


17
Sıfırlamadan bu yana başka repo değişiklikleri yaptıysanız bunun çözüm olmadığını unutmayın. Kesinlikle bir şey çalıştırmadan önce reflog bir göz atın.
forresthopkinsa

2
Depomu yanlışlıkla sıfırladım, işimin sonsuza kadar kaybolduğunu düşündüm. Bu cevap günümü kurtardı.
Zaiyang Li

woh! beni gerçekten kurtardın gün =)
jfcogato

Harika. Gerçekten yardımcı oldu.
Prashant Biradar

117

Git henüz çöp toplamamışsa kurtarmak mümkündür.

Aşağıdakilerle sarkan taahhütlere genel bir bakış alın fsck:

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

Rebase ile sarkan taahhüdü kurtarın:

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

1
Hayatım kurtarıldı.
Mohhamad Hasham

Ayrıntılı bir açıklama burada bulunabilir: medium.com/@CarrieGuss/… . Hayat kurtaran şeyler.
tuan.dinh

49

Benim gibi gerçekten şanslıysanız, metin düzenleyicinize geri dönebilir ve 'geri al'ı tıklayabilirsiniz.

Bunun gerçekten doğru bir cevap olmadığını biliyorum, ama yarım günlük işimi kurtardı, umarım başka biri için de aynısını yapar!


3
Bu aslında çok iyi bir ipucu, beni birçok kez kurtardı;) Ve
git'te bir

3
ve bu dünyadaki tüm iyilikler için teşekkür ederim. teşekkür ederim. teşekkür ederim. teşekkür ederim.
Seyahat

9
Donanım sıfırlamasından sonra dosyalardaki değişmemiş değişiklikleri kurtarmanın tek yolu budur. Beni de
kurtardı

4
Ek bir ipucu olarak, tutulma olarak bazı IDE'ler de son dosya geçmişini kaydetti. Bu şekilde, düzenleyici kapatıldıktan sonra daha eski değişiklikleri kurtarabilirsiniz. Bu benim için harikalar yarattı.
martin

1
Tanrı seni korusun Chris
Adam Waite

45

bildiğim kadarıyla, --hardtaahhüt edilmemiş değişiklikleri atar. Çünkü git gitmiyorlar. ama geri alabilirsiniz discarded commit.

$ git reflog

listeler:

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....

nerede 4bac331olduğunu discarded commit.

Şimdi sadece kafayı şu işleme taşı:

$ git reset --hard 4bac331

34

IRL vakası örneği:

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <stian@Stians-Mac-mini.local>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.

2
Sarkan damla bir AD&D canavarı gibi geliyor!
sbichenko

Teşekkürler @Stian Peki açıkladı! Birden fazla "sarkan" taahhüdünüz varsa, son satırda rebase yapmak istediğinizden emin olmadığınızı bu cevabı bulan diğerlerine eklemek istiyorum :)
JimiSweden

git show dosyalarımı kaydetti, çok teşekkür ederim dostum!
William

32

Çoğu durumda, evet.

Komutu çalıştırdığınızda deponuzun bulunduğu duruma bağlı olarak, etkileri git reset --hardönemsizden geri almaya, temelde imkansız olabilir.

Aşağıda bir dizi farklı olası senaryo ve bunlardan nasıl kurtulabileceğinizi listeledim.

Tüm değişikliklerim yapıldı, ancak şimdi taahhütler gitti!

Bu durum genellikle olduğu git resetgibi bir bağımsız değişkenle çalıştırdığınızda oluşur git reset --hard HEAD~. Endişelenme, bunu kurtarmak kolaydır!

Daha yeni koştuysanız git resetve o zamandan beri başka bir şey yapmadıysanız, bu tek astarla bulunduğunuz yere geri dönebilirsiniz:

git reset --hard @{1}

Bu, en son değiştirilmeden önceki durum ne olursa olsun geçerli dalınızı sıfırlar (sizin durumunuzda, dalda yapılan en son değişiklik geri almaya çalıştığınız donanım sıfırlamasıdır).

Ancak, Eğer var reset beri dalına diğer modifikasyonlar yapılmış, tek satırlık yukarıdaki iş olmaz. Bunun yerine, şubenizde yapılan son değişikliklerin (sıfırlamalar dahil) bir listesini görmeye çalışmalısınız. Bu liste şöyle görünecek:git reflog <branchname>

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit

Bu listeden "geri almak" istediğiniz işlemi bulun. Yukarıdaki örnekte, "sıfırla: KAFA ~ 'ya taşınıyor" yazan ilk satır olacaktır. Ardından , işlemden önce (aşağıda) taahhüdün temsilini kopyalayın . Bizim durumumuzda, bu olurdu master@{1}(ya 3ae5027da her ikisi de aynı taahhüdü temsil eder) ve git reset --hard <commit>mevcut dalınızı bu taahhüdüne sıfırlamak için çalışır .

Değişikliklerimle birlikte sahneledim git addama asla taahhütte bulunmadım. Şimdi değişikliklerim gitti!

Bu kurtarmak için biraz daha zor. git yapar eklediğiniz dosyaların kopyaları var, ancak bu kopyaları herhangi bir bağlı asla beri tek seferde tüm değişiklikleri geri yükleyemezsiniz işlemek. Bunun yerine, git'in veritabanındaki dosyaları tek tek bulmanız ve manuel olarak geri yüklemeniz gerekir. Bunu kullanarak yapabilirsiniz git fsck.

Bununla ilgili ayrıntılar için bkz. Hazırlama alanındaki kullanılmayan dosyalarla birlikte geri almayı sıfırla - geri al .

Çalışma dizinimde hiç sahnelemediğim ve hiç işlemediğim dosyalarda değişiklikler yaptım git add. Şimdi değişikliklerim gitti!

Ah oh. Bunu söylemekten nefret ediyorum, ama muhtemelen şansın yok. git, eklemediğiniz veya taahhüt etmediğiniz değişiklikleri ve aşağıdakilere ilişkin belgeleregit reset göre depolamaz :

--zor

Dizin ve çalışma ağacını sıfırlar. O zamandan beri çalışma ağacında izlenen dosyalarda yapılan değişiklikler <commit>atılır.

Size bu mümkün olabilir disk kurtarma yardımcı programı ya da profesyonel veri kurtarma hizmeti çeşit değişiklikleri kurtarmanız mümkün, ama muhtemelen 's değerinde daha fazla dert var bu noktada.


1
Tek astar benim için çalıştı, teşekkür ederim, ama ben sadece "@ {1}" tam olarak ne yaptığını merak ediyorum ..
Stan Bashtavenko

1
@StanB Belgeler burada: git-scm.com/docs/git-rev-parse temel olarak geçerli daldaki ilk reflog girdisini ifade eder.
Eylül 15:20

Tüm davaları kapsadığınız için teşekkürler. Benim işimi yapmamış ya da eklememiştim.
xdhmoore

21

Deponuzu henüz çöp toplamadıysanız (örneğin git repack -dveya kullanmak git gc, ancak çöp toplama işleminin otomatik olarak da gerçekleşebileceğini unutmayın), o zaman taahhüdünüz hala oradadır - artık KAFA aracılığıyla ulaşılamaz.

Çıktılarına bakarak taahhüdünüzü bulmaya çalışabilirsiniz git fsck --lost-found.

Git'in daha yeni sürümlerinde "reflog" adı verilen bir şey vardır; bu, refs üzerinde yapılan tüm değişikliklerin günlüğüdür (depo içeriğinde yapılan değişikliklerin aksine). Yani, örneğin, HEAD'inizi her değiştirdiğinizde (yani git checkoutdalları değiştirmek için her yaptığınızda ) kaydedilecektir. Ve elbette, git resetHEAD'ı da manipüle ettiniz, bu yüzden de günlüğe kaydedildi. Eğer bir kullanarak, sizin depo eski durumlarını erişebilmesi benzer şekilde hakemlerimizle eski durumlarını erişebilir @yerine işaretini ~gibi git reset HEAD@{1}.

HEAD @ {1} ve HEAD ~ 1 arasındaki farkın ne olduğunu anlamak biraz zamanımı aldı, bu yüzden küçük bir açıklama:

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

Yani, HEAD~1"HEAD'ın şu anda işaret HEAD@{1}ettiği taahhütten önceki taahhüde git ", "HEAD'ın şu anda işaret ettiği yere işaret etmeden önce işaret ettiği taahhüt" anlamına gelir.

Bu, kayıp taahhüdünüzü kolayca bulmanızı ve kurtarmanızı sağlar.


2
Daha net olacağını düşündüğüm başka bir açıklama: HEAD ~ 1, "
HEAD'in

1
Sorun, VCS'lerde "tarih" teriminin gerçekten aşırı yüklenmiş olmasıdır. Yine ifade etmenin bir başka yolu, taahhüt tarihinde ~ geriye, kronolojik veya zamansal tarihe geri gitmek olacaktır . Ancak üç versiyonun hiçbiri özellikle iyi değil.
Jörg W Mittag

@ kizzx2 (ve Jorg) aslında bu 3 açıklama, birlikte alındığında, çok yardımcı olur - thx
Richard Le Mesurier

14

Yanıtlamadan önce bunun ne olduğunu açıklayarak biraz arka plan ekleyelim HEAD.

First of all what is HEAD?

HEADyalnızca geçerli daldaki geçerli taahhüde (en son) bir referanstır. Herhangi bir zamanda
sadece bir tane olabilir HEAD. (hariç git worktree)

İçeriği HEADdepolanır .git/HEADve mevcut taahhüdün 40 bayt SHA-1'ini içerir.


detached HEAD

En son taahhütte değilseniz - yani HEADtarihte önceki bir taahhüde işaret eden anlamına gelir detached HEAD.

resim açıklamasını buraya girin

Komut satırında HEAD, şu anki dalın ucuna işaret etmediği için , dal adı yerine SHA-1 gibi görünecektir.

resim açıklamasını buraya girin


Müstakil bir KAFADAN kurtarma için birkaç seçenek:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Bu, istenen taahhüde işaret eden yeni şubeyi kontrol edecektir.
Bu komut, verilen bir taahhüde ödeme yapar.
Bu noktada bir şube oluşturabilir ve bu noktadan itibaren çalışmaya başlayabilirsiniz.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Her zaman da kullanabilirsiniz reflog.
git refloggüncellenen değişiklikleri görüntüleyecek HEADve istenen reflog girişini kontrol HEADetmek bu işleme geri dönecektir.

HEAD her değiştirilişinde, reflog

git reflog
git checkout HEAD@{...}

Bu sizi istediğiniz taahhüde geri götürür

resim açıklamasını buraya girin


git reset HEAD --hard <commit_id>

Kafanı istenen işleme geri götür.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.


git revert <sha-1>

Verilen taahhüt veya taahhüt aralığını "Geri al".
Sıfırlama komutu, verilen işlemde yapılan değişiklikleri "geri alır".
Geri alma yamasıyla yeni bir taahhüt gerçekleştirilecek, orijinal taahhüt de tarihte kalacaktır.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Bu şema hangi komutun ne yaptığını gösterir.
Gördüğünüz gibi orada reset && checkoutdeğiştirin HEAD.

resim açıklamasını buraya girin


Örneğinizin stackoverflow.com/questions/4114095/… adresindengit reset HEAD --hard <commit_id> alınmış olduğu anlaşılıyor. - Durum buysa, lütfen ilişkilendirmede düzenleme yapabilir misiniz?
Rob

12

git reflog

  • Taahhüdünüzü listede bulun ve kopyalayıp bu komuta yapıştırın:

git cherry-pick <the sha>


1
git-cherry-pick - Mevcut bazı taahhütlerin getirdiği değişiklikleri uygulayın. Bence bu bağlamda basit ve çok faydalı
Amitesh

1
Herkes aslında sıfırlama değişikliklerinin nasıl geri alınacağını araştırdığında bunu arıyor. bu cevap daha fazla oy almalı
ErenL

@ErenL Sanırım sadece düşündüm, insanlar ekstra iş yapmaktan hoşlanıyor. haha
ScottyBlades

1
İşte bu, günümü kurtardın 🙂
Sylvernus Akubo

11

Bu eski bir konu olduğunu biliyorum ... ama birçok kişi Git'te bir şeyleri geri almanın yollarını ararken, burada ipuçları vermeye devam etmenin iyi bir fikir olabileceğini düşünüyorum.

Bir git tuşuna gittiğinizde veya git gui'de sol alttan sol alta herhangi bir şey taşıdığınızda, dosyanın içeriği bir blob içinde saklanır ve dosya içeriği bu blobdan kurtarmak mümkündür.

Bu nedenle, bir dosya işlenmemiş olsa da eklenmesi gerekiyorsa bile kurtarılabilir.

git init  
echo hello >> test.txt  
git add test.txt  

Şimdi blob oluşturulur, ancak indeks tarafından referanslandırılır, böylece sıfırlanana kadar git fsck ile listelenmez. Bu yüzden sıfırladık ...

git reset --hard  
git fsck  

sarkan bir damla alacaksın ce013625030ba8dba906f756967f9e9ca394464a

git show ce01362  

size "merhaba" dosya içeriğini verecek

Referanssız taahhütler bulmak için bir yerde bunu öneren bir ipucu buldum.

gitk --all $(git log -g --pretty=format:%h)  

Git GUI bir araç olarak var ve çok kullanışlı.


+1. Belirtildiği gibi stackoverflow.com/a/21350689/6309 , git fsck --lost-foundyardımcı olabilir.
VonC

7

Bir JetBrains IDE (IntelliJ tabanlı herhangi bir şey) kullanıyorsanız, "Yerel Geçmiş" özellikleri aracılığıyla taranmamış değişikliklerinizi bile kurtarabilirsiniz.

Dosya ağacınızdaki en üst düzey dizininize sağ tıklayın, içerik menüsünde "Yerel Geçmiş" i bulun ve "Geçmişi Göster" i seçin. Bu, son düzenlemelerinizin bulunabileceği bir görünüm açar ve geri dönmek istediğiniz düzeltmeyi bulduğunuzda sağ tıklayın ve "Geri Al" ı tıklayın.



3

Aradığı taahhüdü bulmayı biraz daha kolaylaştırmak için küçük bir senaryo hazırladı:

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

Evet, awk veya benzeri bir şeyle oldukça güzel hale getirilebilir, ancak basit ve ihtiyacım vardı. Başka birini 30 saniye kurtarabilir.


0

Benim sorunum neredeyse aynı. Girmeden önce taahhüt edilmediğim dosyalar var git reset --hard.

Neyse. Tüm bu kaynakları atlamayı başardım. Sadece geri alabileceğimi fark ettikten sonra (ctrl-z ) . 😊 Bunu yukarıdaki tüm cevaplara eklemek istiyorum.

Not. ctrl-zAçılmamış dosyalar için mümkün değildir .


0

Bu hayatımı kurtardı: https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c

Temelde çalıştırmanız gerekir:

for blob in $(git fsck --lost-found | awk ‘$2 == “blob” { print $3 }’); do git cat-file -p $blob > $blob.txt; done

Daha sonra dosyalarınızı doğru yapıya yeniden düzenlemek için acıyı manuel olarak geçin.

Takeaway: git reset --hardTamamen% 100 nasıl çalıştığını anlamadıysanız asla kullanmayın , en iyisi kullanmayın.

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.