Git rebase'ini geri alma


3179

Git git tabanını nasıl kolayca geri alabileceğini bilen var mı?

Akla gelen tek yol, manuel olarak gitmektir:

  • git ana dalını her iki şubeye de kontrol et
  • oradan geçici bir dal oluşturun
  • el ile tüm taahhütleri kiraz toplama
  • elle oluşturduğum dalı elle oluşturduğum dalı değiştir

Şu anki durumumda bu işe yarayacak çünkü her iki şubeden de taahhütleri kolayca tespit edebiliyorum (biri benim eşyalarım, diğeri meslektaşımın eşyalarıydı).

Ancak yaklaşımım bana yetersiz ve hataya meyilli olarak bakıyor (diyelim ki kendi dallarımdan 2'sine yeniden dayanmıştım).

Herhangi bir fikir?

Açıklama: Bir grup taahhüdün tekrar oynatıldığı bir yeniden tabandan bahsediyorum. Sadece bir tane değil.


6
Ayrıca, bir rebase sırasında taahhütleri hariç tutabileceğinizi veya bunları ezebileceğinizi unutmayın; bu değişiklikler ya orijinal düğümlere bir işaretçi olmadan ya da reflog üzerinden elenmeksizin geri alınamaz, bu nedenle şifreleme işe yaramaz.
ANeves

Yanıtlar:


4337

En kolay yol, şubenin yeniden başlamasında yeniden başlamaya başlamadan hemen önce olduğu gibi, şube başkanlığını bulmak olacaktır ...

git reflog

ve mevcut dalı ona sıfırlamak için ( --hardseçenekle yeniden başlatmadan önce olağan uyarılarla ).

Eski taahhüdün HEAD@{5}ref günlüğünde olduğunu varsayalım :

git reset --hard HEAD@{5}

Windows'da referansı alıntılamanız gerekebilir:

git reset --hard "HEAD@{5}"

Adayın eski başkanının geçmişini sadece git log HEAD@{5}( Windows :) yaparak kontrol edebilirsiniz git log "HEAD@{5}".

Şube reflogları başına devre dışı bırakmadıysanız git reflog branchname@{1}, bir rebase son kafaya geri dönmeden önce şube kafasını ayırdığı için yapmanız gerekir . Son zamanlarda doğrulamadıysanız ben bunu iki kez kontrol ediyorum.

Varsayılan olarak, tüm reflog'lar çıplak olmayan depolar için etkinleştirilir:

[core]
    logAllRefUpdates = true

115
Git reflog harika, daha iyi biçimlendirilmiş çıktılar alabileceğinizi unutmayın git log -g(Scott Chacon'un progit.org/book adresinden bahşiş ).
karmi

60
@Zach: git rebase --abort( -ihiçbir anlam ifade etmiyor --abort) tamamlanmamış bir rebazı terk etmek - ya çatışmalar ya da etkileşimli ya da her ikisi yüzünden; bu, sorunun ne olduğu ile ilgili başarılı bir temeli geri almakla ilgili değildir. Hangi durumda olduğunuzu ya rebase --abortda reset --hardbulunduğunuz duruma bağlı olarak kullanırsınız . Her ikisini de yapmanıza gerek yoktur.
CB Bailey

311
Her ihtimale karşı, ilk olarak bir yedeğini: git tag BACKUP. Bir şeyler ters giderse buna geri dönebilirsiniz:git reset --hard BACKUP
kolypto

6
Eğer çok fazla taahhütte bulunduysanız, aradığınız HEAD @ {#} ile commit:karşılaşacaksınız rebase:. Kulağa belli geliyor ama biraz kafam karıştı.
Çözgü

4
Yanlışlıkla yeniden yapılanma sonrasında partiye katılmak: D. git reset --hard ORIG_HEADYanlışlıkla geri döndükten hemen sonra hile yapmaz mıydı ?
quaylar

1487

Aslında, rebase başlangıç ​​noktanızı kaydeder, ORIG_HEADbu genellikle bu kadar basittir:

git reset --hard ORIG_HEAD

Ancak reset, rebaseve mergetüm orijinal tasarrufu HEADiçine pointer ORIG_HEADböylece, size reflog kullanmak gerekecektir sonra geri almak için çalışıyoruz rebase bu yana bu komutların herhangi yaptıysanız.


34
Durumda ORIG_HEADartık yararlıdır, ayrıca kullanabilirsiniz branchName@{n}sözdizimi, nşube işaretçisi n'inci önceki pozisyonudur. Örneğin, featureAşubenizi masterşubenize yeniden adlandırırsanız, ancak yeniden dağıtımın sonucunu beğenmezseniz git reset --hard featureA@{1}, şubeyi yeniden oluşturmadan önce tam olarak bulunduğu yere sıfırlamak için yapmanız yeterlidir . Düzeltmeler için resmi Git belgelerinde şube @ {n} sözdizimi hakkında daha fazla bilgi edinebilirsiniz .

15
Bu en kolayı. Bir süre takip edin git rebase --abort.
Seph

1
@DaBlick, bu konuda hiçbir çatışması olmayan tamamen başarılı bir tekrardan sonra benim için iyi çalıştı git 2.17.0.
dvlsg

4
Ve tamamlayayım: git reset --hard ORIG_HEADtekrar tekrar geri dönmek için tekrar tekrar kullanabilirsiniz. Diyelim ki, A --- rebase --- B --- rebase --- C, şimdi git reset --hard ORIG_HEAD
C'deyim,

5
@Seph Neden takip etmeyi önerdiğini açıklayabilir misin git rebase --abort?
UpTheCreek

386

Charles'ın cevabı işe yarıyor, ancak bunu yapmak isteyebilirsiniz:

git rebase --abort

sonra temizlemek için reset.

Aksi takdirde, “ Interactive rebase already started” mesajını alabilirsiniz .


4
Bu benim istemde "| REBASE" bölümünü kaldırıldı. +1
Wouter Thielen

62
Soru bu değildi. Soru, bitmiş bir yeniden tabanın nasıl geri alınacağını soruyor.
Arunav Sanyal

2
Charles cevabı hakkında bir yorum olmalı, çünkü bu soruya cevap vermiyor
Murmel

Hm, bunu yapmak zorunda değildim.
Viktor Seč

1
Benim için çalışan tek kişi!
Alexandre Picard

90

Şubeyi eski ucunun sarkan taahhüt nesnesine sıfırlamak elbette en iyi çözümdür, çünkü herhangi bir çaba harcamadan önceki durumu geri yükler. Ancak bu taahhütleri kaybettiyseniz (örneğin, deponuzu bu arada çöp topladığınız için veya bu yeni bir klon olduğu için), şubeyi her zaman yeniden temellendirebilirsiniz. Bunun anahtarı --ontoanahtardır.

Let Diyelim ki bir konu şube yaratıcı denilen vardı ki topickapalı kollara olduğunu, masterne zaman ucumaster , 0deadbeeftaahhütlerin . Bir noktada topicdaldayken, yaptınız git rebase master. Şimdi bunu geri almak istiyorsunuz. Bunu nasıl yapacağınız aşağıda açıklanmıştır:

git rebase --onto 0deadbeef master topic

Bu, açık topicolmayan tüm taahhütleri alır masterve üstünden tekrar oynatır 0deadbeef.

İle --onto , geçmişinizi hemen hemen her şekle getirebilirsiniz .

İyi eğlenceler. :-)


3
Esnekliğinden dolayı bunun en iyi seçenek olduğunu düşünüyorum. B1'i master'dan ayırdım, sonra b1'i yeni bir b2 dalına tekrar dayandırdım, sonra b1'i tekrar master'a dayanmak istedim. Git'i çok seviyorum - teşekkürler!
ripper234

2
Buradaki en iyi seçenek! Şimdiki şubemde yaptığım tüm değişiklikleri sakladı ve istenmeyen tüm değişiklikleri sildi!
Alicia Tang

Ben bir kombinasyonu ile söyleyebilirim --ontove -igeçmişinizi hemen hemen her şekle yeniden düzenleyebilirsiniz. Yaptığınız şekilleri görmek için gitk (veya mac'ta gitx) kullanın :-).
rjmunro

69

Aslında herhangi bir önemsiz işlem yapmadan önce şubeye bir yedek etiket koymak (çoğu rebases önemsiz, ama karmaşık bir yerde görünüyorsa bunu yapardı).

Sonra geri yükleme kadar kolaydır git reset --hard BACKUP.


2
Bunu ben de yaparım. Ne demek istediğinizi değiştirdiğinizden emin olmak için git diff BACKUP..HEAD'i kullanmak da yararlıdır.
Paul Bone

5
Bunu ben de yapardım, ama reflogla daha rahat olduğum için artık gerekli olmadığını hissediyorum. Reflog, HEAD'i her değiştirdiğinizde bunu sizin adınıza yapacaktır.
Pete Hodgson

4
Anlamlı isimleri tercih ederim, çünkü reflogda doğru öğeyi aramak bazen hiç eğlenceli değildir.
Alex Gontmakher

12
Aslında bir yedekleme dalı yapmanız bile gerekmez, branchName@{n}sözdizimini kullanabilirsiniz , işte nşube işaretçisinin n'inci önceki konumu. Örneğin, featureAşubenizi masterşubenize yeniden adlandırırsanız, ancak yeniden dağıtımın sonucunu beğenmezseniz git reset --hard featureA@{1}, şubeyi yeniden oluşturmadan önce tam olarak bulunduğu yere sıfırlamak için yapmanız yeterlidir . branch@{n}Sözdizimi hakkında daha fazla bilgiyi revizyonlar için resmi Git belgelerinden okuyabilirsiniz .

2
Aslında, yukarıdaki sözdizimini kullanmanıza bile gerek yok, Pat Notz'un cevabınaHEAD göre, dalın orijinali geçici olarak saklanıyor ORIG_HEAD. Ancak bir yedek şube etiketi kullanma tekniği de işe yarıyor, sadece daha fazla adım.

68

Durumunda uzaktan depoya şube itilmiş olan ((genellikle 's kökenli) ve sonra (birleştirme olmadan) başarılı bir rebase yaptık git rebase --abortkolayca yapabilirsiniz "Hayır sürüyor rebase" verir) sıfırlama şube komutunu kullanarak:

git reset --hard origin / {branchName}

Misal:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

Bu benim için doğru cevap. Rebase'den önce rebase ve taahhüt aynı taahhüt kimliğine sahipti ve HEAD {1} 'e geri dönmek rebase'i geri döndürmeyecekti!
Bill Kotsias

23

Kullanmak reflogbenim için işe yaramadı.

Benim için işe yarayan, burada tarif edilene benziyordu . Yeniden temel alan dalın adını taşıyan .git / logs / refs dosyasında açın ve "rebase finsihed" içeren satırı bulun:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

Hatta listelenen ikinci taahhüdü kontrol edin.

git checkout 88552c8f

Bir kez bu kayıp değişiklikleri içeriyor onaylandıktan sonra dallı ve rahat bir nefes bıraktı.

git log
git checkout -b lost_changes


3
Vay canına - o bağlantıdan, "Bir uyarı var: Şubenin tarihini kaybettim ama bu durumda gerçekten önemli değildi. Değişikliklerimi almaktan mutluluk duydum." ?
Ruffin

16

Birden fazla taahhüt için, herhangi bir taahhüdün, söz konusu taahhüde giden tüm geçmişe atıfta bulunduğunu unutmayın. Charles'ın cevabında, "eski taahhüt" ü "eski taahhütlerin en yenisi" olarak okuyun. Söz konusu taahhüde sıfırlanırsanız, söz konusu taahhüde giden tüm geçmiş yeniden görünür. Bu istediğinizi yapmalı.


11

@Allan ve @Zearin çözümünün ardından, sadece bir yorum yapabilsem diliyorum ama yeterli itibarım yok, bu yüzden aşağıdaki komutu kullandım:

Yerine yapmanın git rebase -i --abort (not -i ) Ben sadece yapmak zorunda git rebase --abort( olmadan -i ).

Her ikisini birden -ive --abortaynı anda kullanmak Git'in bana kullanım / seçeneklerin bir listesini göstermesine neden olur.

Bu çözüm ile önceki ve şimdiki şube durumum:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

11

Eğer başarıyla uzak şube karşı basmış ve yapamıyorsanız git rebase --aborthala işinizi kaydetmek için bazı hile yapabilirsiniz ve zorla itme yok. Yanlışlıkla yeniden temel alınan mevcut dalınızın çağrıldığını your-branchve izlendiğini varsayalımorigin/your-branch

  • git branch -m your-branch-rebased # geçerli dalı yeniden adlandır
  • git checkout origin/your-branch # çıkış olduğu bilinen en son duruma ödeme
  • git checkout -b your-branch
  • eksik olan taahhütleri kontrol etmek git log your-branch-rebased, karşılaştırmak git log your-branchve tanımlamakyour-branch
  • git cherry-pick COMMIT_HASH her taahhüt için your-branch-rebased
  • değişikliklerinizi zorlayın. Lütfen iki yerel şubenin ilişkili olduğunu remote/your-branchve yalnızcayour-branch

4

Diyelim ki, özellik dalımın ustasını yeniden kazanıyorum ve bir şeyleri kıran 30 yeni taahhüt aldım. Ben sık sık kötü taahhütleri kaldırmak için en kolay buldum.

git rebase -i HEAD~31

Son 31 işlem için etkileşimli rebase (çok fazla seçim yaparsanız zarar vermez).

Sadece kurtulmak istediğiniz taahhütleri alın ve "pick" yerine "d" ile işaretleyin. Artık taahhütler, geri ödemeyi geri alarak etkili bir şekilde silinir (yalnızca yeniden basarken aldığınız taahhütleri kaldırırsanız).


3

Sıfırlama yapmaktan çok korkan yeniler / herkes için, taahhüdü reflogdan kontrol edebilir ve daha sonra yeni bir şube olarak kaydedebilirsiniz.

git reflog

Yeniden temel oluşturmaya başlamadan hemen önce taahhüdü bulun. Bulmak için daha aşağı kaydırmanız gerekebilir (Enter veya PageDown tuşuna basın). HEAD numarasını not edin ve 57'yi değiştirin:

git checkout HEAD@{57}

Şube / taahhütleri gözden geçirin, eğer iyi görünüyorsa bu HEAD'i kullanarak yeni bir şube oluşturun:

git checkout -b new_branch_name

2

Bir şubedeyseniz şunları kullanabilirsiniz:

git reset --hard @{1}

Sadece HEAD (tarafından elde edilen git reflog) için bir referans günlüğü yoktur, ayrıca her dal için (tarafından elde edilen git reflog <branch>) reflog'lar da vardır . Yani, üzerinde ise mastero zaman git reflog mastero alanın tüm değişiklikleri listeler. Sen tarafından bu değişikliklere başvurabilir master@{1}, master@{2}vb

git rebase genellikle HEAD değerini birkaç kez değiştirir ancak mevcut şube yalnızca bir kez güncellenir.

@{1}yalnızca geçerli dal için bir kısayoldur , dolayısıyla açık olup master@{1}olmadığınıza eşittir master.

git reset --hard ORIG_HEADgit resetbir etkileşimli sırasında kullandıysanız çalışmaz rebase.


1

Genelde yaptığım şey git reset #commit_hash

Rebase'in bir etkisi olmadığını düşündüğüm son işleme kadar.

sonra git pull

Şimdi şubeniz tam olarak usta gibi eşleşmeli ve yeniden temelli taahhütler içinde olmamalıdır.

Şimdi bu daldaki taahhütleri kiraz toplayabiliriz.


1

Sıfırlama ve reflog ile tüm önerileri başarılı olmadan denedim. IntelliJ'in yerel geçmişini geri yüklemek, kayıp dosyalar sorununu çözdü


Teşekkürler! Yerel tarihi daha önce hiç kullanmadım, ancak bu yanlışlıkla yeniden temel alan bir kodu kurtarmamın en kolay yolu olduğu ortaya çıktı. Çok güzel ama biraz gizli özellik.
Magnus W

0

git reset --hard origin / {branchName}

rebase tarafından yapılan tüm yerel değişikliklerinizi sıfırlamak için doğru çözümdür.


1
Sabit sıfırlama origin/branchyaparsanız HEAD ile o nokta arasındaki değişiklikleri kaybedebilirsiniz. Genel olarak konuşmasını istemezsiniz.
bluesmonk

Benim durumumda tam olarak istediğim buydu. Yani yukarı oy.
Mandar Vaze

-4

Bir git rebase içinde bir şey karıştırırsanız, örneğin git rebase --abort, taahhüt edilmemiş dosyalarınız varken, bunlar kaybolur ve git reflogyardımcı olmaz. Bu benim başıma geldi ve burada kutunun dışında düşünmen gerekecek. Benim gibi şanslıysanız ve IntelliJ Webstorm'u kullanıyorsanız right-click->local history, sürümleme yazılımında ne hata yaparsanız yapın dosya / klasörlerinizin önceki durumuna geri dönebilir ve geri dönebilirsiniz. Başka bir arıza emniyetinin çalışması her zaman iyidir.


5
git rebase --abortaktif bir rebase iptal eder, bir rebase geri almaz . Ayrıca, iki VCS'yi aynı anda kullanmak kötü bir fikirdir. Jetbrains yazılımında güzel bir özellik ama ikisini de kullanmamalısınız. Git'i öğrenmek, özellikle Git ile ilgili Yığın Taşması ile ilgili soruları cevaplarken daha iyi olur.
dudewad
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.