Git deposunu önceki bir işleme nasıl geri döndürebilirim?


7630

Mevcut durumumdan belirli bir taahhütte yapılan bir anlık görüntüye nasıl geri dönebilirim?

Ben yaparsanız git log, o zaman ben şu çıktıyı alıyorum:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

3 Kasım'dan itibaren taahhüde nasıl geri döneceğim, yani taahhüt 0d1d7fc?



116
İşte git'teki şeyleri doğrudan Github'dan geri alma hakkında çok açık ve kapsamlı bir yazı .
Nobita

3
İlgili: Halka açık bir repoda eski bir Git taahhüdüne geri dönme . Bu sorunun repo'nun herkese açık olduğuna dair bir kısıtlama getirdiğini unutmayın.

58
Git'i seviyorum, ama inanılmaz derecede basit olması gereken bir şeye 35 cevap olması, git ile ilgili büyük bir sorunu ortaya çıkarıyor. Yoksa dokümanlar mı?
Muffin Man

2
Nasıl kelime kullanarak dil "tuzak" olduğunu dönmek halk dilinde anlamı olarak sıfırlamak için burada bile hitap etmemektedir ??? 6594 şimdiye kadarki upvotes ve bu şekilde bir düzenleme değil, farkı vurgulamak için? Burada "dosya kaydetme" ifadesi ile "bir dosyayı kaydetme" anlamına gelmek daha kafa karıştırıcı olmaz ...
RomainValeri

Yanıtlar:


9728

Bu, "geri alma" ile ne demek istediğinize çok bağlıdır.

Geçici olarak farklı bir işleme geç

Geçici olarak geri dönmek, etrafta dolanmak, sonra bulunduğunuz yere geri dönmek istiyorsanız, tek yapmanız gereken istenen taahhüdü kontrol etmektir:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Veya siz oradayken taahhütte bulunmak istiyorsanız, devam edin ve siz oradayken yeni bir şube yapın:

git checkout -b old-state 0d1d7fc32

Bulunduğunuz yere geri dönmek için, bulunduğunuz şubeyi tekrar kontrol edin. (Şube değiştirirken her zaman olduğu gibi değişiklik yaptıysanız, onlarla uygun şekilde ilgilenmeniz gerekir. Onları atmak için sıfırlayabilirsiniz; saklamak, satın almak, yanınıza almak için saklamak için kullanabilirsiniz; orada bir şubeye ihtiyacınız varsa onları bir şubeye yönlendirin.)

Yayınlanmayan taahhütleri silmek zor

Öte yandan, o zamandan beri yaptığınız her şeyden gerçekten kurtulmak istiyorsanız, iki olasılık var. Birincisi, bu taahhütlerin hiçbirini yayınlamadıysanız, sıfırlayın:

# 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.

Ortalığı karıştırırsanız, yerel değişikliklerinizi zaten atmış olursunuz, ancak en azından daha önce sıfırlayarak tekrar bulunduğunuz yere geri dönebilirsiniz.

Yeni taahhütlerle yayınlanan taahhütleri geri al

Öte yandan, çalışmayı yayınladıysanız, muhtemelen geçmişi yeniden yazmaktan dolayı şubeyi sıfırlamak istemezsiniz. Bu durumda, taahhütleri geri alabilirsiniz. Git ile geri dönmenin çok özel bir anlamı vardır: ters yama ile iptal etmek için bir taahhüt oluşturun. Bu şekilde hiçbir geçmişi yeniden yazmazsınız.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

git-revertManpage aslında açıklamasında bu çok kapsar. Bir başka faydalı bağlantı ise git-revert tartışan bu git-scm.com bölümüdür .

Sonuçta geri dönmek istemediğinize karar verirseniz, geri döndürmeyi (burada açıklandığı gibi) geri alabilir veya geri dönmeden önce geri yükleyebilirsiniz (önceki bölüme bakın).

Bu yanıtı şu durumda da yararlı bulabilirsiniz:
HEAD'i önceki bir konuma nasıl taşıyabilirim? (Müstakil kafa)


118
Rod'un yorumun @ üzerinde git revert HEAD~3geri dönmek için en iyi wat olarak 3kaydedilmesini AM önemli kongre olduğunu.
Yeni İskenderiye

19
Sayının tamamını yazabilir misiniz? gibi:git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Spoeken

16
@MathiasMadsenStav Evet, elbette taahhütleri tam SHA1 ile belirtebilirsiniz. Cevabı daha okunaklı hale getirmek için kısaltılmış karmaları kullandım ve yazarken bunları da kullanma eğilimindesiniz. Kopyalama ve yapıştırma işlemi yapıyorsanız, tam karmayı kullanın. Taahhütleri nasıl adlandırabileceğinizin tam açıklaması için man git rev-parse'de Düzeltmeleri Belirtme konusuna bakın .
Cascabel

59
Bunu kullanabilir git revert --no-commit hash1 hash2 ...ve bundan sonra her bir geri git commit -m "Message"
dönüşü

6
'Yayınlama' bu bağlamda ne anlama geliyor?
Howiecamp

1849

Burada çok sayıda karmaşık ve tehlikeli cevap var, ama aslında kolay:

git revert --no-commit 0766c053..HEAD
git commit

Bu, HEAD'den taahhüt karmasına kadar her şeyi geri alacak, yani o zamandan beri her taahhüt geri yürüdüğü gibi çalışma ağacındaki bu taahhüt durumunu yeniden yaratacaktır . Daha sonra mevcut ağacı taahhüt edebilirsiniz ve bu, esas olarak "geri döndüğünüz" taahhüde eşdeğer yeni bir taahhüt oluşturacaktır.

( --no-commitBayrak, git'in tüm taahhütleri bir kerede geri döndürmesine izin verir - aksi takdirde aralıktaki her taahhüt için bir mesaj girmeniz istenir ve gereksiz yeni taahhütlerle geçmişinizi tahrip eder.)

Bu, önceki bir duruma geri dönmenin güvenli ve kolay bir yoludur . Hiçbir tarih yok edilmediğinden, daha önce kamuya açıklanmış olan taahhütler için kullanılabilir.


23
Gerçekten bireysel taahhütlere sahip olmak istiyorsanız (her şeyi büyük bir taahhütle geri almak yerine), --no-editbunun yerine geçebilirsiniz --no-commit, böylece her bir geri dönüş için bir taahhüt mesajını düzenlemeniz gerekmez.

87
0766c053..HEAD arasındaki birleştirme bir birleştirme ise, bir hata ortaya çıkacaktır (-m belirtilmemiş). Bu, aşağıdakilerle karşılaşanlara yardımcı olabilir: stackoverflow.com/questions/5970889/…
timhc22

7
Kullanmadan önce farkları görmek için git diff --cached.
John Erck

21
$ git revert --no-commit 53742ae..HEADdönerfatal: empty commit set passed
Alex G

10
@AlexG, geri dönmek istediğiniz karma işleminden önce karma değerini girmeniz gerektiğinden. Benim durumumda, hashler gibiydi: 81bcc9e HEAD{0}; e475924 HEAD{1}, ...(from git reflog), ve yaptığım şeyi geri almak istedim 81bcc9e, sonra yapmak zorundaydımgit revert e475924..HEAD
EpicPandaForce

1611

Rogue Coder?

Kendi başınıza çalışıyor ve sadece çalışmasını mı istiyorsunuz? Aşağıdaki talimatları izleyin, onlar ve benim için yıllardır güvenilir bir şekilde çalıştılar.

Başkalarıyla mı çalışıyorsunuz? Git karmaşık. Kızarık bir şey yapmadan önce bu cevabın altındaki yorumları okuyun.

Çalışma Kopyasını En Son İşleme Geri Döndürme

Herhangi bir değişikliği yok sayarak önceki bir işleme geri dönmek için:

git reset --hard HEAD

HEAD mevcut şubenizdeki son taahhüttür

Çalışma Kopyasını Daha Eski Bir İşleme Geri Döndürme

En son taahhütten daha eski bir taahhüdüne geri dönmek için:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Krediler benzer bir Stack Overflow sorusuna gider, Git'teki bir SHA karma işlemine geri dönülsün mü? .


33
Bunu ben yaptım, ama sonra uzak depoya bağlanamadım. Belirli bir eski taahhüdün KAFA olmasını istiyorum ...
Lennon

7
Bu, geri almak istediğiniz taahhütleri zaten itmiş olduğunuz anlamına gelir. Kodunuzu kontrol eden ve üzerinde çalışan kişiler için çok fazla sorun yaratabilir. Taahhüdünüzü sorunsuz bir şekilde uygulayamadıkları için. Böyle bir durumda git geri döndürmek daha iyi olur. Repoyu kullanan tek kişi sizseniz. Git push -f yapın (Ama bunu yapmadan önce iki kez düşünün)
vinothkr

6
Aşağıdaki gibi, sadece de yerine ilk karma sıfırlama yapmanın alternatif yumuşak sıfırlama çözümü için, işaret etmek istiyorum ve sert bir sıfırlama son, aslında ilk sert araştırma yapabilirsiniz: git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.

5
@nuton linus git'in yaratıcısı olan pauling, onu çok karmaşık olduğu için eleştirdi. Kayıtta "şok" olduğunu söyleyerek git karmaşıklığı göz önüne alındığında çok popüler oldu
boulder_ruby

5
@boulder_ruby Bence Linus Torvalds git'in yaratıcısı demek istedin. Ama bence Linus Pauling git'in karmaşık olduğu konusunda hemfikir.
Suncat2000

215

Benim ve muhtemelen diğerleri için en iyi seçenek Git reset seçeneğidir:

git reset --hard <commidId> && git clean -f

Bu benim için en iyi seçenek oldu! Basit, hızlı ve etkilidir!


** Not: ** Yorumlarınızda belirtildiği gibi, şubenizi eski taahhütlerin kopyalarına sahip diğer insanlarla paylaşıyorsanız bunu yapmayın

Ayrıca yorumlardan, daha az 'topaklı' bir yöntem istiyorsanız

git clean -i

37
Zorunlu Uyarı: şubenizi eski taahhütlerin kopyaları olan diğer insanlarla paylaşıyorsanız bunu yapmayın , çünkü böyle bir sıfırlama kullanmak onları yeni sıfırlanan dal ile çalışmalarını yeniden senkronize etmek zorunda bırakacaktır. Donanımdan sıfırlama ile işi kaybetmeden taahhütlerin nasıl güvenli bir şekilde geri döndürüleceğini ayrıntılı olarak açıklayan bir çözüm için bu cevaba bakınız .

7
İkinci Cupcake uyarısı ... sonuçlarının çok farkındayım. Bununla birlikte, eğer ihtiyaçlarınız gerçekten bu taahhütlerin sonsuza dek ortadan kaybolmasını sağlamaksa, bu sıfırlama + temizleme yönteminin bunu yapacağını ve değiştirilmiş dallarınızı herhangi bir uzaktan kumandaya zorlamak için zorlamanız gerektiğini unutmayın.
ashnazg

5
git clean -f TEHLİKE TEHLİKESİ
Tisch

2
Bu, yerel kopyamın kafasını istenen işleme ayarlar. Fakat uzaktan kumandanın arkasında olduğu için herhangi bir değişiklik yapamıyorum. Ve uzaktan kumandadan çekersem uzak daldaki en son taahhütte olduğu yere geri döner. Her iki yerel kopyamda da itilmiş olan (her yerden) birkaç taahhüdü nasıl tamamen yok edebilirim?
Ade

2
@Ade .. git push -fBayrağı kullanabilirsiniz .. Ama dikkatli olun, uzaktan kumandayı geçersiz kılar .. Ne yapmak istediğinizi bildiğinizden emin olun ...
Pogrindis

176

Cevaplamadan önce bunun ne HEADolduğunu açıklayan bir arka plan ekleyelim .

First of all what is HEAD?

HEADyalnızca geçerli daldaki geçerli taahhüde (en son) bir referanstır. HEADHerhangi bir zamanda yalnızca bir kişi olabilir (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 şu şekilde görünecektir - HEADgeçerli dalın ucuna işaret etmediğinden , dal adı yerine SHA-1 :

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 şu 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.

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


6
Mükemmel ipucu git reflog, tam da ihtiyacım olan şey
smac89

4
Ah! Tüm bunlar çok karmaşık görünüyor ... bu süreçte sizi geri adım atan basit bir komut yok mu? Projenizin 1.1 sürümünden 1.0 sürümüne geri dönmek gibi mi? Ben şöyle bir şey beklerdim: git stepback_one_commit falan ....
Kokodoko

var: git reset HEAD^--hard`
CodeWizard

3
@Kokodoko Evet, bu çok karmaşık bir durum ... ve yeni başlayanlar için uzmanların ne kadar az dikkate aldığının mükemmel bir örneği. Lütfen buradaki yanıtı ve ayrıca tavsiye ettiğim kitaba bakınız. Git sezgisel olarak alabileceğiniz bir şey DEĞİLDİR. Ve kesinlikle CodeWizard'ın bunu yapmadığından emin olabilirim.
mike rodent

145

"Kapatma" yapmak, son tamamlama mesajını silmek ve değiştirilen dosyaları tekrar evrelemeye koymak istiyorsanız, şu komutu kullanırsınız:

git reset --soft HEAD~1
  • --soft, taahhüt edilmeyen dosyaların, atılacak dosyalara karşı tutulmaları gerektiğini belirtir --hard.
  • HEAD~1son taahhüttür. Eğer 3 geri almak isterseniz kullanabilirsiniz HEAD~3. Belirli bir düzeltme numarasına geri dönmek isterseniz, bunu SHA karmasını kullanarak da yapabilirsiniz.

Bu, yanlış şeyi yaptığınız ve son taahhüdü geri almak istediğiniz durumlarda son derece yararlı bir komuttur.

Kaynak: http://nakkaya.com/2009/09/24/git-delete-last-commit/


3
Bu yumuşak ve
naziktir

124

Bunu aşağıdaki iki komutla yapabilirsiniz:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Önceki Git taahhüdünüzü kaldıracak.

Değişikliklerinizi korumak istiyorsanız şunları da kullanabilirsiniz:

git reset --soft [previous Commit SHA id here]

Sonra değişikliklerinizi kaydedecektir.


2
Ben bu kadar var bu yazı 1/2 bir düzine cevap denedim .. tüm bu diğerleri, benim git config itmeye çalışırken bana bir hata veren tuttu. Bu cevap işe yaradı. Teşekkürler!
Gene Bo

Benim için bir ayrıntı da fark etmedim .. hangi işe yaramadı taahhütte ne yaptığını görmek istedim. Bir dahaki sefere bu sıfırlama komutunu vermeden önce sadece bu verileri kaydedecektim
Gene Bo

1
Kötü bir birleşmeyi geri almanın tek yolu buydu, geri alma o durumda işe yaramadı. Teşekkürler!
Dave Cole

En iyi cevap. Teşekkürler
Imran Pollob

En iyi cevap, teşekkürler.
user1394

114

Git'teki yerel değişiklikleri geri almak için birçok yol denedim ve sadece en son taahhüt durumuna geri dönmek istiyorsanız, bu en iyi şekilde çalışıyor gibi görünüyor.

git add . && git checkout master -f

Kısa Açıklama:

  • Herhangi bir taahhüt OLUŞTURMAZ git revert.
  • HEAD'inizi olduğu gibi git checkout <commithashcode>ayırmayacaktır.
  • Tüm yerel değişikliklerinizi geçersiz kılacak ve şubedeki son işlemden bu yana eklenen tüm dosyaları SİLECEKTİR.
  • Sadece dal isimleriyle çalışır, böylece sadece daldaki en son taahhütlere geri dönebilirsiniz.

Yukarıdaki sonuçları elde etmenin çok daha kolay ve basit bir yolunu buldum:

git add . && git reset --hard HEAD

Burada HEAD mevcut şubenizdeki en son taahhüdü işaret eder.

Boulder_ruby tarafından önerilen kod koduyla aynıdır, ancak en son işleme geri döndüğümde çoğu insanın beklediğimden bu yana, son işlemden bu yana oluşturulan tüm yeni dosyaları silmek için daha git add .önce ekledim git reset --hard HEAD.


83

Tamam, Git'teki önceki taahhüdüne geri dönmek oldukça kolay ...

Geri döndür tutmadan değişiklikler:

git reset --hard <commit>

Değişiklikleri koruyarak geri dönün :

git reset --soft <commit>

Açıklama: kullanarak git reset, belirli bir duruma sıfırlayabilirsiniz. Yukarıda gördüğünüz gibi bir karma hash ile kullanmak yaygındır.

Ama gördüğünüz gibi fark iki bayrağı kullanıyor --softve --hardvarsayılan olarak bayrak git resetkullanıyor --soft, ancak her zaman bayrağı kullanmak iyi bir uygulamadır, her bayrağı açıklarım:


--yumuşak

Açıklandığı gibi varsayılan bayrak, sağlaması gerekmez, çalışma ağacını değiştirmez, ancak değiştirilen tüm dosyaları işlemeye hazır olarak ekler, böylece dosyalarda yapılan değişikliklerin değişmemiş hale geldiği kesinleştirme durumuna geri dönersiniz.


--zor

Bu bayrağa dikkat et. Çalışma ağacını ve izlenen dosyalarda yapılan tüm değişiklikleri sıfırlar ve hepsi gider!


Ayrıca Git ile çalışırken gerçek hayatta meydana gelebilecek aşağıdaki görüntüyü de oluşturdum:

Git bir işleme sıfırlandı


Varsayılan git resetdeğeri git reset --mixed, değil git reset --soft. Lütfen kontrol edin reset --mixed, --soft ve --hard arasındaki fark nedir? ve Açık İngilizce'de “git reset” ne yapar?
Fabio, Reinstate Monica'yı

70

Master hakkında ve ilgili dalda konuştuğunuzu varsayarsak (bu, endişelendiğiniz herhangi bir çalışma dalı olabilir):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Cevabı bir blog gönderisinde buldum (artık mevcut değil)

Bunun uzaktan kumandayı değiştirmeyi Sıfırlama ve Zorlama olduğunu unutmayın, böylece ekibinizdeki diğerleri git gitmişse, onlar için sorunlara neden olursunuz. Değişiklik geçmişini yok ediyorsunuz, bu da insanların git'i ilk başta kullanmasının önemli bir nedeni.

Sıfırlama yerine geri döndürme (diğer yanıtlara bakın) kullanmak daha iyidir. Eğer tek kişilik bir takımsanız muhtemelen önemli değil.


6
Bu cevap başkalarının sayısından nasıl farklı?
Matsmath

Bu talihsizlik. Blogcuya e-posta gönderdim - umarım hala vardır!
markreyes


2
Push sözdizimi, bunu nasıl çözeceğinize dair diğer önerilerin çoğunda eksik. Harika çalıştı.
jpa57

61

Diyelim ki bir metin dosyasında aşağıdaki işlemlerin var ~/commits-to-revert.txt( git log --pretty=onelinebunları alırdım)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Her birini geri almak için bir Bash kabuk betiği oluşturun :

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Bu, dosya ve dizin kreasyonları ve silmeler dahil olmak üzere her şeyi bir önceki duruma geri döndürür, dalınıza taahhüt eder ve geçmişi tutarsınız, ancak aynı dosya yapısına geri döndünüz. Git'in neden a sahip olmadığı git revert --to <hash>benim dışımda.


41
git revert HEAD~3Son 3 taahhüdü kaldırmak için bir yapabilirsin
Rod

25
@Rod - Hayır, bu doğru değil. Bu komut HEAD'ın üçüncü büyükbaba veya büyükannesi olan taahhüdü geri alacak (son üç taahhüt değil).
kflorence

1
@kflorence Tamam bilgi için teşekkürler. Çalışır mıydı git revert -n master~3..master~1? ( Kernel.org/pub/software/scm/git/docs/git-revert.html
Rod

3
@Rod - Kulağa doğru geliyor, tabii ki çirkin bir sözdizimi değil mi? Ben her zaman "geri dönmek" ve daha sezgisel taahhüt taahhüt taahhüt kontrol ettim.
kflorence

7
Bunu yapmanın böyle bir komut dosyasından çok daha kolay bir yolu var, sadece kullanın git revert --no-commit <start>..<end>, çünkü git revertGit'in yeni (veya tümü?) Sürümlerinde bir taahhüt aralığını kabul eder. Aralığın başlangıcının geri döndürülmediğini unutmayın.

58

Jefromi'nin Çözümlerine Ekstra Alternatifler

Jefromi'nin çözümleri kesinlikle en iyisidir ve kesinlikle kullanmalısınız. Ancak, tamlık uğruna, bir taahhüdü geri almak için de kullanılabilecek diğer alternatif çözümleri de göstermek istedim ( aynen ne olduğu gibi, önceki işlemlerde değişiklikleri geri alan yeni bir taahhüt oluşturduğunuzdagit revert ).

Açıkçası, bu alternatifler taahhütleri geri almanın en iyi yolu değildir , Jefromi'nin çözümleri , ancak sadece bu aynı yöntemleri elde etmek için bu diğer yöntemleri de kullanabileceğinizi belirtmek isterim git revert.

Alternatif 1: Sert ve Yumuşak Sıfırlamalar

Bu, Charles Bailey'nin Git'teki bir SHA karmaşasının taahhüdüne geri dönme çözümünün çok az değiştirilmiş bir versiyonudur. :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Bu temel olarak, yumuşak sıfırlama işlemlerinin indeks / aşamalama alanında bir önceki taahhüdün durumunu terk edeceği gerçeğini kullanarak çalışır.

Alternatif 2: Geçerli Ağacı Sil ve Yenisiyle Değiştir

Bu çözüm, svick'in Checkout eski taahhüdüne ve yeni bir taahhüt haline getirdiği çözümden gelir :

git rm -r .
git checkout <commit> .
git commit

Alternatif # 1'e benzer şekilde, bu <commit>, mevcut çalışan kopyadaki durumunu yeniden üretir . İlk önce yapılması gerekir, git rmçünkü git checkouto zamandan beri eklenen dosyaları kaldırmaz <commit>.


Alternatif 1 hakkında, kısa bir soru: Bunu yaparak, taahhütler arasında kaybetmiyoruz değil mi?
Bogac

2
@Bogac - noktalar bir dosya yolunu, bu durumda geçerli dizini gösterir, bu nedenle onu çalışma kopyanızın kökünden çalıştırdığınız varsayılır.
Tom

Uyarı cevapta birkaç kez tekrarlanır, ancak birisi neden bunların en iyi yol olmadığını ekleyebilir mi - git revert HEAD~2..HEAD@ Cascabel'in (@ Jefromi'nin) bağlantılı çözümüyle karşılaştırıldığında. Sorunu görmüyorum.
Joshua Goldberg

55

İşte bir önceki taahhüdüne geri dönmenin (ve bunu bağımsız bir durumda tutmanın, istediğiniz gibi yapmanın) çok daha basit bir yolu:

git reset HEAD~1

Yani, taahhüt kimliklerine gerek yok vb. :)


işe yaramadı, bu
verimden

1
@malhal Bunun nedeni, değişmemiş değişiklikleriniz olmasıydı. Stash / reset onları ve sonra bu hata olmadan çalışır.
Paul Walczewski

39

Özellikle eski taahhütleri geri almak ve sahnelemek için bir komut var (çekirdek Git'in bir parçası değil, git-extras paketinde):

git back

Başına adam sayfasında , aynı zamanda gibi kullanılabilir:

# Remove the latest three commits
git back 3

38

En iyi yol:

git reset --hard <commidId> && git push --force

Bu, şubeyi belirli bir işleme sıfırlar ve daha sonra uzak sunucuyu yerel olarak yaptığınız işlemlerle aynı yüklemelere yükler (bu, belirli bir işlemden sonra komutları tamamen ortadan kaldırır)

--forceBayrağa dikkat edin , seçilen işlemden sonra sonraki tüm taahhütleri kurtarma seçeneği olmadan kaldırır.


3
cazibe gibi çalıştı!
Gaurav Gupta

Cevabınızı aldım, çünkü cevabınızın zaten stackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886 veya stackoverflow.com/a/48756719/1723886 adreslerinde henüz verilmemiş olan yeni bilgileri nasıl sağladığını göremiyorum . Aslında çoğu taahhüt git reset --hard ve daha pek çok şey itmek için --force veya -f kullanarak bahseder.
Alex Telon

İşi tek bir komutla açık ve basit bir şekilde yapar. Eğer beğenmezseniz cevabımı aşağıya çevirmekte özgürsünüz.
david.t_92

1
Gelecek için göz önünde bulundurulması gereken bir başka seçenek de, daha önceki bir cevapta bir düzenleme önermek veya 'bunun && kullanarak bir satırda da yapılabileceğini' yorumlamaktır. Böylece herkes gelişmiş yanıtı tek bir yerde görebilir.
Alex Telon

36

Tüm değişikliklerden sonra, tüm bu komutları bastığınızda şunları kullanmanız gerekebilir:

git push -f ...

Ve sadece git push.


15
Zorunlu Uyarı: şubenizi eski komisyonların kopyalarına sahip diğer insanlarla paylaşıyorsanız bunu yapmayın , çünkü böyle bir kuvvet zorlaması onları çalışmalarını yeniden senkronize etmek zorunda bırakacaktır. Zorla zorlama ile işi kaybetmeden taahhütlerin nasıl güvenli bir şekilde geri döndürüleceğini ayrıntılı olarak açıklayan bir çözüm için bu cevaba bakınız .

3
Bazen istediğiniz budur. Örnek: birkaç taahhüdü yanlış şubeye (A şubesi) adamış ve itmiştir. B dalına kiraz topladıktan sonra, bu taahhütlerin A dalından çıkarılmasını istiyorum. A ve B dalı bir araya getirildiğinde geri dönüş uygulanacak. A dalında sıfırlama --hard <commitId> ve ardından bir kuvvet itme yapmak, B dalında onları korurken daldan çıkarır. A dalında kimsenin gelişmediğini biliyorum çünkü bundan kurtulabilirim.
Doug R

Teşekkürler! Uzak şubeyi yerel şubeme uyacak şekilde nasıl elde edeceğimi anlayamadım, Sadece bir kuvvet itmek gerekiyordu.
Mido

32

Tüm bu ilk adımları kendiniz tamamlayabilir ve Git veri havuzuna geri dönebilirsiniz.

  1. Komutunuzu kullanarak deponuzun en son sürümünü Bitbucket'ten çekin git pull --all.

  2. Git log komutunu -n 4terminalinizden çalıştırın. Sonraki sayı -n, yerel geçmişinizdeki en son işlemden başlayarak günlükteki taahhütlerin sayısını belirler.

    $ git log -n 4
    
  3. Deponuzun geçmişinin başını sıfırlayın; git reset --hard HEAD~Nburada N, başlığı geri almak istediğiniz taahhütlerin sayısıdır. Aşağıdaki örnekte başkan, depo tarihindeki son taahhüde bir taahhüt getirecekti:

  4. Değişikliği git push --forcezorlamaya zorlamak için değişikliği Git deposuna aktarın .

Git deposunun önceki bir işleme alınmasını istiyorsanız:

git pull --all
git reset --hard HEAD~1
git push --force


28

İstediğiniz taahhüdü seçin ve tarafından kontrol edin

git show HEAD
git show HEAD~1
git show HEAD~2 

gerekli taahhüdü alana kadar. HEAD'ı buna işaret etmek için

git reset --hard HEAD~1

ya git reset --hard HEAD~2da ya da her neyse.


7
Zorunlu Uyarı: şubenizi eski taahhütlerin kopyaları olan diğer insanlarla paylaşıyorsanız bunu yapmayın , çünkü böyle bir sıfırlama kullanmak onları yeni sıfırlanan dal ile çalışmalarını yeniden senkronize etmek zorunda bırakacaktır. Donanımdan sıfırlama ile işi kaybetmeden taahhütlerin nasıl güvenli bir şekilde geri döndürüleceğini ayrıntılı olarak açıklayan bir çözüm için bu cevaba bakınız .

2
Ayrıca, açık olmak gerekirse, git show HEADsadece kullanmaya eşdeğerdir git log HEAD -1.

25

Durum acil bir durumsa ve projenizin örneğin "projem" adlı bir dizin altında olduğunu varsayarak, sorgunun sorduğu şeyi hızlı ve kirli bir şekilde yapmak istiyorsanız :


HIZLI VE KİRLİ : koşullara bağlı olarak, hızlı ve kirli aslında çok iyi olabilir. Burada benim çözümdür gelmez DEĞİL dosyalarla çalışma dizinde geri döndürülemez sahip dosyaları değiştirmek tane olan Şeytanmışçasına zeki ve şeytani güçlü git komutlarını kullanarak .git / dizini altına gizlenen git depo derinliklerinde, çıkarılan / yukarı çekti birçok. Felaket bir durum olarak görülebilecek şeyleri kurtarmak için ÇOK DÜŞÜK DENİZ DALIŞI YAPMAK GEREKMEZ ve yeterli uzmanlık olmadan bunu yapmaya çalışmak ölümcül olabilir .


  1. Dizinin tamamını kopyalayın ve "projem - kopya" gibi başka bir ad verin. Git deposu ("repo") dosyalarınızın "projem" dizininin altında olduğunu varsayarsak (varsayılan yer, ".git" adlı bir dizinin altında), hem çalışma dosyalarınızı hem de repo dosyalarınızı kopyalamış olursunuz.

  2. Bunu "projem" dizininde yapın:

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Bu, "projem" altındaki repo durumunu bu taahhüdü yaptığınız zamanki haline döndürür ("taahhüt", çalışma dosyalarınızın anlık görüntüsü anlamına gelir). O zamandan beri tüm kaydedilmesini ... sonsuza "Projemin" başlığı altında kaybolmuş ANCAK edilecektir hala mevcut olacak altında repo "projemde - kopya" Kopyaladığınız beri tüm bu dosyaları -. ... / git altında olanlar da dahil olmak /.

Daha sonra sisteminizde iki versiyonunuz var ... ilgilenilen dosyaları veya herhangi bir şeyi önceki işlemden inceleyebilir veya kopyalayabilir veya değiştirebilirsiniz. Geri yüklenen taahhüdün hiçbir yere gitmediğinden bu yana yeni çalışmaya karar verdiyseniz, "projem - kopya" altındaki dosyaları tamamen atabilirsiniz ...

Bu geri alınan taahhüt, işi gerçekten atmadan projenin durumuna devam etmek istiyorsanız açık olan şey, dizininizi yeniden adlandırmaktır: Geri alınan taahhüdü içeren projeyi silin (veya geçici bir ad verin) ve " projem - dizini "projem" e geri kopyala. O zaman belki buradaki diğer cevaplardan bazılarını anlamaya çalışın ve muhtemelen kısa süre içinde başka bir taahhütte bulunun.

Git mükemmel bir yaratımdır, ancak kesinlikle hiç kimse "anında harekete geçiremez": bunu çok fazla açıklamaya çalışan insanlar da diğer VCS [Sürüm Kontrol Sistemleri] hakkında önceden bilgi sahibi olurlar ve çok derinlere inerler çok yakında ve "kontrol etmek" için değiştirilebilir terimler kullanmak gibi - bazen yeni başlayanların kafasını karıştırmak için neredeyse hesaplanmış gibi görünen - diğer suçları işleyin.

Kendinizi daha fazla stresden kurtarmak için yara izlerimden öğrenin. Git'te bir kitap okumak zorundasınız - "Git ile Sürüm Kontrolü" ni öneririm . Daha sonra değil, daha erken yapın. Bunu yaparsanız, Git'in karmaşıklığının çoğunun dallanma ve yeniden birleştirmeden geldiğini unutmayın: bu parçaları herhangi bir kitapta atlayabilirsiniz. Sorunuzun itibaren var insanların bilim ile kör olması için hiçbir sebep .

Özellikle, örneğin, bu çaresiz bir durumsa ve Git!

Not: Başka bir düşünce: Git repo'yu çalışma dosyalarının olduğu bir dizinde tutmak (şimdi) aslında oldukça basit. Bu, yukarıdaki hızlı ve kirli çözümü kullanarak Git deposunun tamamını kopyalamanız gerekmeyeceği anlamına gelir. --separate-git-dir Burada kullanarak Fryer'ın cevabına bakınız . Yine de uyarılırsınız : Kopyalamadığınız bir "ayrı dizin" deponuz varsa ve donanımdan sıfırlama yaparsanız, sıfırlama taahhüdünden sonraki tüm sürümler, kesinlikle gerektiği gibi olmadıkça sonsuza kadar kaybedilecektir. deponuzu düzenli olarak, tercihen diğer yerlerin yanı sıra Buluta (ör. Google Drive ) yedekler.

Bu "Bulut'a yedekleme" konusunda bir sonraki adım GitHub veya (benim görüşüme göre daha iyi) GitLab ile bir hesap açmak (elbette ücretsiz) . Daha sonra git pushCloud repo'nuzu "düzgün" güncel hale getirmek için düzenli olarak komut verebilirsiniz. Ama yine de, bunun hakkında konuşmak çok erken olabilir.


23

Bu, son zamanlarda yapılan bir taahhüde doğrudan sıfırlamanın bir yoludur

git stash
git stash clear

Son işlemden bu yana yaptığınız tüm değişiklikleri doğrudan temizler.

Not: Küçük bir sorunu var; ayrıca son zamanlarda sakladığınız tüm saklanan değişiklikleri de siler. Sanırım çoğu durumda önemli değil.


NOT: Dizine eklenmeyen yeni dosyalar saklanmaz. Bunları çok eklediniz veya manuel olarak sildiniz.
andreyro

Neden ah neden saklanıyor? Çözümsüz olmanın yanı sıra, bu aslında zararlıdır. Sorunun ilk cümlesinin okunması derhal stash çözümünü geçersiz kılar (SADECE SON işleme sıfırlamak için yararlı olabilir).
RomainValeri

22

Kodlayıcının dizinini bazı yanlışlıkla yapılan değişikliklerden tamamen temizlemek için kullandık:

git add -A .
git reset --hard HEAD

Sadece git reset --hard HEADdeğişikliklerden kurtulacak, ancak "yeni" dosyalardan kurtulamayacak. Onların durumunda, yanlışlıkla önemli bir klasörü rastgele bir yere sürüklediler ve tüm bu dosyalar Git tarafından yeni olarak ele alındı, bu yüzden reset --harddüzeltmedi. git add -A .Önceden koşarak , sıfırlama ile silinmek üzere hepsini git ile açıkça izledi.


21

Önceki taahhütten HEAD'e değişiklikleri korumak ve bir önceki işe geçmek için şunları yapın:

git reset <SHA>

Önceki HEAD taahhüdünde değişiklik yapılması gerekmiyorsa ve sadece tüm değişiklikleri atın, şunları yapın:

git reset --hard <SHA>


18

Geri alma, taahhütleri geri alma komutudur.

git revert <commit1> <commit2> 

Örneklem:

git revert 2h3h23233

Aşağıdaki gibi HEAD'den menzil alabilir. Burada 1 "son sözü geri al" diyor.

git revert HEAD~1..HEAD

ve sonra yap git push


14

İstediğiniz işleme sıfırlamayı deneyin -

git reset <COMMIT_ID>

(COMMIT_ID kullanımını kontrol etmek için git log )

Bu, değiştirilen tüm dosyaları eklenmemiş duruma sıfırlar.

Artık checkouttüm eklenmemiş dosyaları şu şekilde yapabilirsiniz:

git checkout .

Kontrol git log değişiklikleri doğrulamak için.

GÜNCELLEME

Reponuzda bir tane varsa ve sadece taahhütte bulunuyorsanız,

git update-ref -d HEAD


13

Taahhütleriniz uzaktan itildikçe, bunları kaldırmanız gerekir. Bana şube olduğunu farzedelim geliştirmek ve bitti itilir kökenli .

Önce kaldırmak gerekir geliştirmek dan köken :

git push origin :develop (note the colon)

O zaman istediğiniz duruma gelmeniz gerekiyor, taahhüt karmasının EFGHIJK olduğunu varsayalım:

git reset --hard EFGHIJK

Son olarak, tekrar geliştirmeyi itin :

git push origin develop

13

Dikkat! Bu komut, kullanıcı yanlış işlemeyi yanlışlıkla koyarsa işlem geçmişinin kaybedilmesine neden olabilir. Her zaman git'inizin ekstra yedeklemesini yapın, sadece hata yaparsanız, biraz daha güvenli olursanız. :)

Benzer bir sorun yaşadım ve daha önceki bir taahhüdüne geri dönmek istedim. Benim durumumda yeni taahhüdü korumak istemiyordum, bu yüzden kullandım Hard.

Ben böyle yaptım:

git reset --hard CommitId && git clean -f

Bu, yerel depoya geri dönecek ve kullandıktan sonra git push -fuzak depoyu güncelleyecektir.

git push -f

13

In GitKraken bunu yapabilirsiniz:

  1. Sıfırlamak istediğiniz taahhüdü sağ tıklayın, seçin: Bu taahhüdüne sıfırla / Sabit :

    Resim açıklamasını buraya girin

  2. Kesime tekrar sağ tıklayın, seçin: Geçerli şube adı / Push :

    Resim açıklamasını buraya girin

  3. Force Push'a tıklayın :

    Resim açıklamasını buraya girin

Göz. : Dikkatli olmalısınız, çünkü donanım sıfırlamasından sonraki tüm işlem geçmişi kaybolur ve bu eylem geri döndürülemez. Ne yaptığınızdan emin olmalısınız.


11

Son işlemdeki bir hatayı düzeltmek istiyorsanız, git commit --amend komutunu kullanmak iyi bir alternatif olacaktır . Son taahhüt herhangi bir referansla işaretlenmezse, bu son işlemle aynı ebeveynle bir taahhüt oluşturduğu için hile yapar. Son taahhüdün herhangi bir referansı yoksa, atılacaktır ve bu taahhüt son taahhüt olacaktır. Bu, taahhütleri tersine çevirmeden taahhütleri düzeltmenin iyi bir yoludur. Ancak kendi sınırlamaları vardır.

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.