Git'te geri döndürülmüş birleştirme işlemini yeniden yapma


231

Burada biraz sorunla karşılaştım: 28sGit'te genel developdalda birleştirdiğim probleme özgü bir şubem vardı . Çok hızlı yaptığım anlaşılıyor, bu yüzden birleşmeyi geri almak için git-revert kullandım. Ancak şimdi, birleşme zamanı 28sgeldi develop, ancak git-merge komutu orijinal birleştirmeyi görüyor ve her şeyin yolunda olduğunu ve dalların zaten birleştirildiğini mutlu bir şekilde duyuruyor. Ben şimdi ne yapacağım? Bir 'Geri döndür "Geri döndür 28s -> geliştirmek" "' taahhüt? Bunu yapmak için iyi bir yol gibi görünmüyor, ama şu anda başka bir şey hayal edemiyorum.

Ağaç yapısı neye benziyor:

Git günlük çıktısı


4
Bu GitX ( gitx.frim.nl ).
Toms Mikoss

Yanıtlar:


169

"Geri dönmek zorundasın". Orijinalin nasıl geri döndüğüne bağlı olarak, göründüğü kadar kolay olmayabilir. Bu konuyla ilgili resmi belgeye bakın .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

izin vermek:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Ama hepsi işe yarıyor mu? Elbette öyle. Bir birleştirmeyi geri döndürebilirsiniz ve tamamen teknik açıdan git, çok doğal bir şekilde yaptı ve gerçek bir sıkıntı yaşamadım.
Sadece "birleştirme öncesi durum" dan "birleştirme sonrası durum" a bir değişiklik olduğunu düşündü ve hepsi buydu.
Karmaşık bir şey yok, garip bir şey yok, gerçekten tehlikeli bir şey yok. Git bunu düşünmeden bile yapacak.

Yani teknik açıdan, bir birleştirmeyi geri döndürmenin yanlış bir yanı yoktur, ancak iş akışı açısından bu genellikle kaçınmaya çalışmanız gereken bir şeydir .

Mümkünse, örneğin, birleştirmeyi geri almak yerine ana ağaca birleştirilen bir sorun bulursanız, şunları yapmak için gerçekten çok çalışın :

  • sorunu birleştirdiğiniz şubeye ayırın ve düzeltin,
  • veya buna neden olan bireysel taahhüdü geri almaya çalışın.

Evet, daha karmaşık, ve hayır, her zaman işe gitmiyor (bazen cevabı: "oops, henüz hazır değildi çünkü gerçekten birleştirdiğinizden olmamalı ve gerçekten geri almak gerekir tüm arasında birleştirmek"). Bu yüzden birleştirmeyi gerçekten geri almalısınız, ancak birleştirmeyi yeniden yapmak istediğinizde, şimdi geri döndürerek bunu yapmanız gerekir.


10
İyi bağlantı (+1). Okuyucunun bu durumda ilgili seçenekleri hemen görmesine izin vermek için cevabınızda belgenin bir bölümünü kopyalama özgürlüğünü aldım. Kabul etmiyorsanız, geri dönmekten çekinmeyin.
VonC

5
Sadece bunu yapmamız gereken bir durumla karşılaştık ve eğlencenin burada bitmediğini gördük. Birleştirilmiş uzun bir daldı, bu yüzden güncellemeye devam etmemiz gerekiyordu. Buradaki yaklaşımım: tech.patientslikeme.com/2010/09/29/…
jdwyah

@ jdwyah'ın blog gönderisini takip ettim ve görkemliydi (cidden, sadece işe yaradı).
hellatan

2
@jdwyah kırık bir bağlantı gibi görünüyor, ama ilginç bir okuma gibi geliyor. İşte bir archive.org aynası ama görüntüleri eksik: web.archive.org/web/20111229193713/http://…
Alex KeySmith

15
Blog yayını yeniden gönderildi, teşekkürler: blog.jdwyah.com/2015/07/dealing-with-git-merge-revisions.html
jdwyah

53

Diyelim ki böyle bir geçmişe sahipsin

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

A, B başarısız olur ve W - M'ye geri döner

Bulunan sorunları düzeltmeye başlamadan önce, şubemde W'nin kiraz seçimini yapıyorum

git cherry-pick -x W

Sonra şubemde W taahhüdünü geri alıyorum

git revert W 

Sonra tamir etmeye devam edebilirim.

Nihai tarih şöyle görünebilir:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Bir PR gönderdiğimde, PR'nin geri alındığını ve bazı yeni taahhütler eklediğini açıkça gösterecektir.


3
Bu yararlı olabilir gibi görünüyor, ancak ayrıntılara o kadar seyrek (son diyagramda C, D nedir), kullanışlıdan daha sinir bozucu
Isochronous

4
@ Eşzamanlı C ve D, A ve B'nin getirdiği sorunları çözen taahhütler gibi görünüyor
Thomas

@Thomas tam olarak
Maksim Kotlyar

Bu örnekte bir PR kullanarak vurgulanmış olmanız iyidir, çünkü ustaya geri dönmeden önce son bir 'akıl sağlığı kontrolü' sağlayabilir.
Willem van Ketwich

kullanım Şubenizi neden orijinal W'den yeniden başlatıyorsunuz? Yani, konunuz W'den devam edelim, W` ve ardından C ve D? Bu bazı
çoğalmaları

12

İş akışınızı çok fazla yormadan geri döndürmek için:

  • Geliştirmenin yerel bir çöp kopyasını oluşturma
  • Geliştirmenin yerel kopyasına geri dönüş taahhüdünü geri alma
  • Bu kopyayı özellik dalınızla birleştirin ve özellik dalınızı git sunucunuza aktarın.

Özellik dalınız artık hazır olduğunuzda normal şekilde birleştirilebilmelidir. Buradaki tek dezavantajı, geçmişinizde birkaç ekstra birleştirme / geri alma taahhüdünüz olacak.


Sadece daha fazla karışıklığı önlemek için, özellik dalımın 'çöp' bir kopyasını da oluşturdum ve tersine çevrilmiş gelişimi birleştirdim.
jhhwilliams

Teşekkür ederim! Bunu yapmamanız gerektiğini söylemek yerine aslında nasıl yapılacağını açıklayan tek cevap budur. Gerçekten yararlı.
Emmy

Teşekkür ederim, bu gerçekten bana yardımcı oldu. :)
Daniel Stracaboško

11

GIT'deki bir geri döndürmeyi geri almak için:

git revert <commit-hash-of-previous-revert>

1
Geri dönmek için iş şubemde bunu kullanın, sonra geliştirmek için yeni PR. Şimdi git, önceki PR'da geri döndürülen tüm değişiklikleri görüyor. Teşekkürler.
Danstan

3

Kullanmak yerine git-revertbu komutu develşubede yanlış birleştirme taahhüdünü atmak (geri almak yerine) kullanabilirsiniz.

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Bu, çalışma dizininin içeriğini de buna göre ayarlayacaktır. Dikkatli ol :

  • Geliştirme dalında (yanlış birleşme beri) değişikliklerinizi kaydedin çünkü onlar da tarafından silinecektir git-reset. git resetArgüman olarak belirttiğinizden sonra tüm taahhütler gider!
  • Ayrıca, değişiklikleriniz zaten başka depolardan alınmışsa bunu yapmayın, çünkü sıfırlama geçmişi yeniden yazacaktır.

Bunu git-resetdenemeden önce man sayfasını dikkatlice incelemenizi tavsiye ederim .

Şimdi, sıfırlama işleminden sonra değişikliklerinizi yeniden uygulayabilir develve

git checkout devel
git merge 28s

Bu gerçek bir birleştirme olacak 28siçine devel(şu anda Git tarihinin silinir) başlangıçtaki gibi.


8
Git'e aşina olmayan ve bu talimatları takip etmek isteyebilecek herkes için: reset --hardve ile birleştirmeye dikkat edin push origin. Ayrıca, menşei zorlamanın GitHub'daki açık PR'ları gerçekten etkileyebileceğini unutmayın.
funroll

Özel bir git sunucusunda bazı birleştirme sorunlarını gidermek için çok yararlı. Teşekkürler!
mix3d

1
Bu teknik için +1. Potansiyel olarak yıkıcıdır, ancak makul bir şekilde uygulandığında size çok fazla baş ağrısından (ve karışık bir geçmişten) tasarruf edebilirsiniz.
siliconrockstar

1

Aynı soruyla karşı karşıya kaldığımda bu yazıyı buldum. Sıfırlama zorları vb yapmak için korkutucu yukarıda wayyy buluyorum. Sonunda istemediğim bir şeyi silerim ve geri alamazsınız.

Bunun yerine, şubeye geri dönmesini istediğim taahhüdü kontrol ettim git checkout 123466t7632723. Sonra bir şubeye dönüştürüldü git checkout my-new-branch. Daha sonra artık istemediğim şubeyi sildim. Tabii ki bu sadece berbat ettiğiniz dalı atabiliyorsanız işe yarayacaktır.


1
Daha git reflogsonra kayıp taahhütlere ihtiyacınız olduğunu keşfederseniz, birkaç ay boyunca sıfırlamada sizi koruyacaktır. Reflog yerel repo ile sınırlıdır.
Todd

1

Bir geri dönüşü geri almak için aşağıdaki adımları izlemenizi öneririm, örneğin SHA1.

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

Şimdi şube için PR oluşturun users/yourname/revertOfSHA1


1
  1. orijinal birleşmeden önce yeni şube oluşturun - buna 'geliştirme tabanı' deyin
  2. 'geliştirme tabanının' üstünde 'geliştir' etkileşimli yeniden oluşturma (zaten üstünde olmasına rağmen). Etkileşimli rebase sırasında, hem birleştirme taahhüdünü hem de birleştirmeyi tersine çeviren taahhüdü kaldırma, yani her iki olayı git geçmişinden kaldırma fırsatına sahip olacaksınız.

Bu noktada, düzenli olarak yaptığınız gibi özellik braketinizi birleştirebileceğiniz temiz bir 'geliştirme' şubesine sahip olacaksınız.


Geliştirme yaklaşımı başkalarıyla paylaşılırsa bu yaklaşım sorun yaratacaktır.
PSR
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.