"Git commit" yerine "git commit --amend" nasıl geri alınır?


1294

Önceki taahhüdümü yanlışlıkla değiştirdim. Taahhüt, belirli bir dosyada yaptığım değişikliklerin geçmişini tutmak için ayrı olmalıdır.

Bu son taahhüdü geri almanın bir yolu var mı? Eğer böyle bir şey yaparsam git reset --hard HEAD^, ilk taahhüt de geri alınır.

(Henüz herhangi bir uzak dizine geçmedim)

Yanıtlar:


2290

Yapmanız gereken, mevcut HEADişlemle aynı ayrıntılarla , ancak önceki sürümündeki üst öğeyle yeni bir işlem oluşturmaktır HEAD. git reset --softşube işaretçisini hareket ettirir, böylece bir sonraki işlem, geçerli şube başlığının bulunduğu yerden farklı bir işlemin üstünde olur.

# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}

33
Çok güzel, +1. Hatta git reflogdoğru sayıyı bulmak için içine ikinci son değişiklik görünümü ile yaptım örneğin {2}.
JJD

179
Açık olmak gerekirse, ilk komut gerçek bir "geri al" dır. Önce HEAD, çalışma dizini (değişmedi) ve dizin durumunu üretir git commit --amend. İkincisi, yeni bir taahhüde "yeniden" denir. Bunlar git commitsadece herkes için işe yaramıyor --amend.
cdunn2001

60
Bu yüzden, kurtarmanız gereken yeni bir taahhüt mesajı ile değişiklik yapmadıysanız, ikinci kısım normal olabilir git commit.
Matt Montag

18
Çalıştırırken Nedense, bir hata başlamıştı git reset --soft HEAD@{1}: fatal: ambiguous argument 'HEAD@1': unknown revision or path not in the working tree. Use '--' to separate paths from revisions. Ben HEAD@{1}gösterilen eşdeğer taahhüt karma yerine git reflog(teşekkürler JJD!), Bu cevap harika çalıştı!
Tim Camber

20
@TimArnold kabuğuna bağlı olarak, tek veya çift tırnak koymanız gerekebilir HEAD@{1}. echo HEAD@{1}Örneğin tcsh'de çalıştırırsam çıktı, HEAD@1parantezlerin tcsh tarafından yorumlanmasıdır. Tek tırnak kullanırsam, parantez korunur.
Kelvin

136

ref günlüğünü kullanın :

git branch fixing-things HEAD@{1}
git reset fixing-things

daha sonra değiştirilmiş tüm değişikliklerinizi yalnızca çalışma kopyanızda yapmanız ve tekrar işleme koyabilmeniz gerekir.

önceki endeks türlerinin tam listesini görmek için git reflog


7
Bu, dizini de siler - hala yararlıdır, ancak basit bir "geri al" ın ötesine geçer.
cdunn2001

3
HEAD@{1}ve arasında herhangi bir fark var HEAD~1mı?
neaumusic

15
@ neaumusic: evet! HEAD~1, mevcut taahhüdün üst öğesiyle tamamen aynı HEAD^ve tanımlayıcıdır . Öte yandan, HEAD'ın bundan önce işaret ettiği taahhüdü ifade eder, yani farklı bir şubeyi kontrol ettiğinizde veya bir taahhüdü değiştirdiğinizde farklı taahhütler anlamına gelir. HEAD@{1}
knittl

@knittl ah bu daha önce mümkün olduğunu düşünmedim hiç merak ediyorum, tekrar teşekkürler, iyi bilgi
neaumusic

9
ilk adım gereksizdir. Basit git reset HEAD@{1}yeterlidir.
dwelle

79

Değiştirilmiş taahhütlerinizi şu şekilde bulun:

git log --reflog

Not: --patchAçıklık için taahhütlerin gövdesini görmek için ekleyebilirsiniz . İle aynı git reflog.

daha sonra şu şekilde iyi olduğu noktada HEAD'inizi önceki işlemlere sıfırlayın:

git reset SHA1 --hard

Not: Değiştir gerçek taahhüt karma ile SHA1. Ayrıca, bu komutun taahhüt edilmeyen değişiklikleri kaybedeceğini unutmayın , böylece bunları daha önce saklayabilirsiniz. Alternatif olarak, kullanmak --softson değişiklikleri korumak için yerine ve sonra bunları işlemek.

Daha sonra kiraz, ihtiyacınız olan diğer taahhüdü seçin:

git cherry-pick SHA1

26
Bunu yaparsanız git reset SHA1 --soft, en son değişiklikleri koruyabilir ve sonra bunları uygulayabilirsiniz.
pravj

24

Her zaman itibaren işlemeye bölebilirsiniz manuel

  • Git rebase -i commit ^ ile interaktif bir rebase başlatın, burada taahhüt bölmek istediğiniz taahhüttür. Aslında, herhangi bir taahhüt aralığı, söz konusu taahhüdü içerdiği sürece yapacaktır.
  • Bölmek istediğiniz taahhüdü "düzenle" eylemiyle işaretleyin.
  • Bu taahhüdü düzenleme söz konusu olduğunda, git reset HEAD ^ komutunu yürütün. Etkisi, HEAD'in birer birer geri sarılması ve endeksin uymasıdır. Ancak, çalışan ağaç aynı kalır.
  • Şimdi değişiklikleri ilk işleme dahil etmek istediğiniz dizine ekleyin. Bunu yapmak için git add (muhtemelen etkileşimli) veya git-gui (veya her ikisini) kullanabilirsiniz.
  • Şu an geçerli olan dizini, şu anda uygun olan herhangi bir ileti ile tamamlayın.
  • Çalışma ağacınız temiz olana kadar son iki adımı tekrarlayın.
  • Git rebase ile devam etmeye devam edin.

26
çok karmaşık. git reflogtek ihtiyacın olan
knittl

2
Birçok adım evet, ancak her adım karmaşık değildir ve yapılması kolaydır. Bu benim için çalıştı ve oyumu aldı.
OzBandit

5
buna ek olarak, bu cevap, git reset --soft HEAD @ {1} yaklaşımına (sorunum
BTW'yi

2
Reflog yöntemiyle de değişiklikleri seçerek seçebilirsiniz. Sadece git resetyerine yap git reset --soft, sonra yap git add --patch.
geekofalltrades

1
Bu hala tarihi yeniden yazıyor ve zorla itmeyi gerektiriyor. Durumunuza bağlı olarak bir sorun olabilir veya olmayabilir.
17'de Pajn

20

Muhtemelen kaydetme mesajı ile hala editörünüzdeyseniz, kaydetme mesajını silebileceğinizi ve git commit --amendkomutu iptal edeceğini belirtmek gerekir .


İşte bu o.
atilkan

Kurtarıldı benim ama ^^
engineercoding

14

Belki git reflogdeğişiklikten önce ve değişiklikten sonra iki taahhüt almak için kullanabilirsiniz .

Sonra git diff before_commit_id after_commit_id > d.diffdeğişiklikten önce ve değişiklikten sonra fark almak için kullanın .

git checkout before_commit_idİşlemden önce geri dönmek için bir sonraki kullanım

Yaptığınız git apply d.diffgerçek değişikliği uygulamak için son kullanım .

Bu benim sorunumu çözdü.


11

Eğer taahhüdü uzaktan kumandaya ittiyseniz ve daha sonra hatalı olarak bu taahhütte değişiklikler yaptıysanız, bu sorununuzu çözecektir. git logTaahhütten önce SHA'yı bulmak için a sayısını düzenleyin. (uzaktan kumandanın orijinli olduğu varsayılır). Şimdi bu SHA'yı kullanarak bu komutu verin.

git reset --soft <SHA BEFORE THE AMMEND>
#you now see all the changes in the commit and the amend undone

#save ALL the changes to the stash
git stash

git pull origin <your-branch> --ff-only
#if you issue git log you can see that you have the commit you didn't want to amend

git stash pop
#git status reveals only the changes you incorrectly amended

#now you can create your new unamended commit

3
Bu daha genel bir sorunun özel bir örneğidir, ancak benim acil ihtiyacımı tam olarak karşıladı.
dmckee --- eski moderatör yavru kedi

8

Aşağıdakileri geri almak için git commit —amend

  1. git reset --soft HEAD^
  2. git checkout files_from_old_commit_on_branch
  3. git pull origin your_branch_name

====================================

Artık değişiklikleriniz önceki gibi. Yani geri almayı bitirdingit commit —amend

Şimdi git push origin <your_branch_name>şubeye itmek için yapabilirsiniz .


3

Neredeyse 9 yıl geç kaldı, ancak aynı şeyi gerçekleştirdiğinden bahsettiğimiz bu varyasyonu görmedim (üstteki cevaba benzer şekilde, bunlardan birkaçının bir kombinasyonu ) ( https://stackoverflow.com/a/1459264/4642530 ) .

Daldaki tüm müstakil kafalarda ara

git reflog show origin/BRANCH_NAME --date=relative

Sonra SHA1 karma değerini bulun

Eski SHA1'e sıfırla

git reset --hard SHA1

Sonra tekrar yukarı itin.

git push origin BRANCH_NAME

Bitti.

Bu sizi tamamen eski taahhüdüne geri döndürecektir.

(Önceden üzerine yazılan bağımsız taahhüt başkanının tarihi dahil)


Evet, ancak --softdeğişikliklerimi korumak için genellikle sıfırlamak istiyorum . Sadece ayrı olarak işlenmesini istiyorum
Juan Mendes

2
  1. Son taahhüt ile geçici şubeye ödeme

    git branch temp HEAD@{1}

  2. Son taahhüdü sıfırla

    git reset temp

  3. Artık, tüm taahhütlerinizin yanı sıra önceki işlemlerinize de sahip olacaksınız. Tüm dosyaların durumunu kontrol edin.

    git status

  4. İşleme dosyalarınızı git aşamasından sıfırlayın.

    git reset myfile1.js (yakında)

  5. Bu taahhüdü yeniden bağlayın

    git commit -C HEAD@{1}

  6. Dosyalarınızı ekleyin ve yeni taahhütlere gönderin.

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.