Zaten uzak şubeye itilmiş bir birleştirme taahhüdü nasıl geri alınır?


961

git revert <commit_hash>yalnız işe yaramaz. -mbelirtilmelidir ve bu konuda oldukça kafam karıştı.

Bunu daha önce deneyimleyen var mı?


3
Bu sorunun cevabına bir göz atın: stackoverflow.com/questions/2318777/…
eugen


Buradaki bağlantı, birleştirilmiş taahhüdü geri döndürmeyi gösteren en iyi örnektir: christianengvall.se/undo-pushed-merge-git
SK Venkat

Bu, tasarımının herkesin kullandığı -ish iş akışıyla giteşleşmediğine bir örnektir git-flow. Eğer varsa developteslim, elbette bir böcek ve uzun dev dal paylaşılan yıl tanıtıldı 2-taahhüt özellik dalını geri döndürmek istiyor. Onu seçmek için saçma geliyor -m 1.
pkamb

2
Daha önce aklıma gelmeyen başka bir öneri daha - şubelerin taahhüt listelerinden biri küçükse, taahhütlerin tamamı yerine bireysel taahhütleri geri almak daha rahat hissedebilirsiniz.
Sridhar Sarnobat

Yanıtlar:


1153

-mSeçenek belirten ebeveyn numarasını . Bunun nedeni, bir birleştirme işleminin birden fazla üst öğeye sahip olması ve Git'in hangi üst öğenin ana hat olduğunu ve birleştirmek istediğiniz dalın hangi üst öğe olduğunu otomatik olarak bilmemesidir.

Çıktısında bir birleştirme taahhüdü görüntülediğinizde git log, ebeveynlerinin şununla başlayan satırda listelendiğini görürsünüz Merge:

commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <ben@example.com>
Date:   Wed Aug 17 22:49:41 2011 +0100

Merge branch 'gh-pages'

Conflicts:
    README

Bu durumda, git revert 8f937c6 -m 1o olduğu gibi size ağacı alacak 8989ee0ve git revert -m 2o olduğu gibi ağaç eski haline getireceğiz 7c6b236.

Ana kimlikleri daha iyi anlamak için şunları çalıştırabilirsiniz:

git log 8989ee0 

ve

git log 7c6b236

127
İki numaralardan gelen 8989ee0, 7c6b236gitmek biri. Nasıl anlarım?
Arup Rakshit

12
Geri döndükten sonra, kolayca kaynak dalındaki kodu düzeltmek ve yeniden birleştirme mümkün olacağını sanmıyorum ? kernel.org/pub/software/scm/git/docs/howto/…
IsmailS

10
Daha iyi bir açıklama aramak için uğraşırken, ayrıntıları gözden geçirmek için harika bir iş çıkardığını düşündüğüm bu makaleyi buldum. Okuduktan sonra gerçekten aradığım şeyin RESET komutu olduğunu ve ardından bir kuvvet itme olduğunu keşfettim. Belki başka birine yardım eder. atlassian.com/git/tutorials/…
Funktr0n

46
Koşarsan @ArupRakshit git log 8989ee0ve git log 7c6b236, cevabı bilmeli.
BMW

4
git log - tüm birleştirmeleri görmek için birleşir ve git log --no-merges birleşmeleri olmayan geçmişi görmek için kullanılır. Bir şubeyi birleştirmek, birleştirilen şube geçmişini hedefe getirir ve düz git
logunu

369

İşte birisine yardımcı olması umuduyla tam bir örnek:

git revert -m 1 <commit-hash> 
git push -u origin master

Nerede <commit-hash>Geri döndürmek istiyorum birleştirme karmasını işlemek ve açıklaması belirtildiği gibi bu cevap , -m 1birleştirmede öncesinde ilk ebeveynin ağacına dönmek istiyorum belirtir.

git revert ...İkinci satır uzak dalına iterek değişiklikler kamu yapar iken çizgi esasen değişiklikleri taahhüt.


21
git revertKomutun oluşturulan taahhüt nesnesini zaten taahhüt ettiğine inanıyordum . Bunun gerçekleşmemesi için --no-commitbayrağı
girmek zorunda kalacaksınız

2
@Delfic'in de belirttiği gibi, taahhüt zaten ilk satır tarafından yönetiliyor (doğrulamak için a: wq gerekli), bu yüzden ikinci satır gerekli değil.
eka808

1
bu kafa karıştırıyor. sadece 2 satır var ve git taahhüt .. birisi düzenlemek lütfen.
Jay Random

176

Ben size birleştirme taahhüdünü nasıl geri alacağınızı söyledi, ancak bunu yaparken fark etmeniz çok önemlidir.

"... birleştirmenin getirdiği ağaç değişikliklerini hiçbir zaman istemeyeceğinizi beyan eder. Sonuç olarak, daha sonra birleşme yalnızca önceden döndürülmüş birleştirme işleminin atası olmayan komisyonların getirdiği ağaç değişikliklerini getirir. Bu olabilir veya olmayabilir. ne istediğini. " (git-birleştirme adam sayfası) .

Kılavuz sayfasından bağlantı verilen bir makale / posta listesi mesajı , ilgili mekanizmaları ve hususları açıklar. Birleştirme taahhüdünü geri döndürürseniz, şubeyi daha sonra tekrar birleştiremeyeceğinizi ve aynı değişikliklerin geri gelmesini bekleyemeyeceğinizi anladığınızdan emin olun.


81
Ama gerçekten gerekiyorsa onları geri almak için geri dönebilirsiniz.
dalore

5
Teşekkürler. Bir hata nedeniyle diyelim - bir birleştirmeyi geri almak için kullanım durumu olarak bilmek ve hata giderildikten sonra tüm dalı yeniden birleştirmek çok yaygındır.
Bileşen 10

3
Eğer benim gibiyseniz ve daha sonra birleştirme yapmak istediyseniz ya geri dönüşü ya da kiraz geri döndürdüğünüz değişikliği seçebilirsiniz.
UnitasBrooks

Benim durumumda, değişiklikleri geri alma sorunumu elde etmek için 'geri döndürme' ihtiyacını vurdum. Kiraz toplama daha temiz bir yol olabilir mi? Bir dahaki sefere deneyeceğim ...
Steven Anderson

79

Yanlış komutları geri almak veya uzak dalınızı doğru HEAD / durumuna sıfırlamak için bu adımları uygulayabilirsiniz.

  1. yerel şubeye uzak şubeyi kontrol edin.
    git checkout development
  2. komut karmasını (yani yanlış komuttan hemen önce komutun kimliği) git log'dan kopyala git log -n5

    çıktı:

    7cd42475d6f95f5896b6f02e902efab0b70e8038 "Şube 'yanlış-
    taahhüt'ü ' geliştirme 'ile birleştir" işlem f9a734f8f44b0b37ccea769b9a2fd774c0f0c012 "bu yanlış bir
    işlemdir" taahhüt

  3. şubeyi önceki adımda kopyalanan işleme karmasına sıfırla
    git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)

  4. çalıştırmak git statusyanlış taahhüt parçası olan tüm değişiklikleri göstermek için.
  5. git reset --hardtüm bu değişiklikleri geri almak için çalıştırın .
  6. yerel şubenizi uzaktan zorlayın ve taahhüt geçmişinizin kirlenmeden önceki gibi temiz olduğunu görün.
    git push -f origin development

4
ya bu arada 20 geliştirici en son geliştiriciyi bir araya getirdiyse?
Ewoks

2
Bu dalı kullanan ekipte 20 geliştirici olduğunda bir geliştirme dalını zorlamaya zorlamam. :) Bu durumda, sadece bir geri dönüş yapmak akıllıca olacaktır.
ssasi

4
Bu, kendiniz çalışırken çok iyi bir çözümdür ya da başka hiçbir geliştiricinin berbat ettiğiniz taahhütleri çekmediğinden eminsiniz
Kyle B


30

Hiçbir şey olmadıkça günlüğü temiz tutmak için (bu yaklaşımla bazı olumsuzluklarla (push -f nedeniyle)):

git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>

Birleştirme işleminden sonra 'birleştir-hash-önce-birleştir' günlüğünden (git günlüğü) gelir.


İpucu: Bunu şirketinizde yapıyorsanız, izniniz olmayabilir.
eneski

3
asla push -fpaylaşılan bir repo yapmayın
Baptiste Mille-Mathias

17

Bazen geri almanın en etkili yolu geri adım atıp değiştirmektir.

git log

2. tamamlama karmasını (tam hata, listelenen hatadan önce geri döndürmek istediğiniz hash) kullanın ve sonra oradan yeniden ayrılın.

git checkout -b newbranch <HASH>

Ardından eski dalı silin, yeni dalını yerine kopyalayın ve oradan yeniden başlatın.

git branch -D oldbranch
git checkout -b oldbranch newbranch

Yayınlanmışsa, eski dalı tüm depolardan silin, redone dalını en merkeze doğru itin ve tekrar aşağı doğru çekin.


4
Yayın hakkındaki uyarı, bunun ne kadar korkunç bir fikir olduğu konusunda daha açık olmalıdır. Bu, herkesin bu dalın sürümünü bozar ve yalnızca sizin erişebildiğiniz bir uzak depo (github / bitbucket) ile çalışıyorsanız gerçekten yararlıdır.
RobbyD

Değiştirilmiş yapılandırma dosyalarını üretime aktarma kadar kötü değil. Bozulmayacak, sadece daha önceki bir taahhütten vazgeçti, bu yüzden şube işaretçisini önceki bir sürüme taşımak için yuvarlak bir yol. Umarım sadece yerel depoyu etkiler
ppostma1

5

Bir mergetaahhüdü geri almak istiyorsanız , işte yapmanız gerekenler.

  1. İlk olarak, git logbirleştirme işleminizin kimliğini bulmak için simgesini kontrol edin . Birleştirme ile ilişkili birden fazla üst kimlik de bulacaksınız (aşağıdaki resme bakın).

resim açıklamasını buraya girin

Sarı ile gösterilen birleştirme taahhüdü kimliğini not edin. Üst kimlikler sonraki satırda olarak yazılan kimliklerdir Merge: parent1 parent2. Şimdi ...

Kısa hikaye:

  1. Birleştirme yapıldığı şubeye geçin. Sonra sadece git revert <merge commit id> -m 1hangi vitaahhüt mesajı girmek için bir konsol açılacaktır . Yazın, kaydedin, çıkın, bitti!

Uzun Hikaye:

  1. Birleştirme yapıldığı şubeye geçin. Benim durumumda, testşube ve şube ondan kaldırmaya çalışıyorum feature/analytics-v3.

  2. git revertherhangi bir taahhüdü geri alan komuttur. Ama bir mergetaahhüdü geri alırken kötü bir hile var . -mBayrağı girmeniz gerekir, aksi takdirde başarısız olur. Buradan sonra, şubenizi geri döndürmek ve tam olarak olduğu gibi mi parent1yoksa şu parent2yolla mı görünmek istediğinize karar vermeniz gerekir :

git revert <merge commit id> -m 1(geri döner parent2)

git revert <merge commit id> -m 2(geri döner parent1)

Gitmek istediğiniz yolu bulmak için bu ebeveynleri günlüğe kaydedebilirsiniz ve bu tüm karışıklığın köküdür.


5

Tüm cevaplar zaten çoğu şeyi kapsıyordu ama ben 5 sent ekleyeceğim. Kısacası birleştirme taahhüdünü geri almak oldukça basittir:

git revert -m 1 <commit-hash>

İzniniz varsa doğrudan "ana" şubeye gönderebilirsiniz, aksi takdirde "geri" şubenize yönlendirip çekme isteği oluşturabilirsiniz.

Bu konuyla ilgili daha fazla bilgiyi burada bulabilirsiniz: https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html


1

Bildiğim iki uç nokta arasında ters bir yama oluşturmayı ve bu yamayı uygulamak işe yarayacağını buldum. Bu, ana dalınızdan anlık görüntüler (etiketler) oluşturduğunuzu ve hatta ana dalınızın yedeklemesinin master_bk_01012017 olduğunu varsayar.

Master ile birleştirdiğiniz kod şubesinin mycodebranch olduğunu varsayalım.

  1. Ödeme ustası.
  2. Master ve yedeklemeniz arasında tam bir ikili ters yama oluşturun. git diff --binary master..master_bk_01012017 > ~/myrevert.patch
  3. Yamanızı kontrol edin git apply --check myrevert.patch
  4. Oturum kapalıyken düzeltme eki uygula git am --signoff < myrevert.patch
  5. Sabitlendikten sonra bu kodu tekrar getirmeniz gerekecekse, geri döndürülen yöneticiden dallamanız ve düzeltme dalını kontrol etmeniz gerekir. git branch mycodebranch_fix git checkout mycodebranch_fix
  6. Burada geri dönmek için SHA anahtarını bulmanız ve geri döndürmeniz gerekir git revert [SHA]
  7. Artık sorunları çözmek, tamamlayıp bir kez tamamlandığında master ile birleştirmek için mycodebranch_fix'inizi kullanabilirsiniz.

1

Doğru işaretlenmiş cevap benim için çalıştı ama neler olup bittiğini belirlemek için biraz zaman harcamak zorunda kaldım .. Bu yüzden benimki gibi durumlar için basit ve basit adımlarla bir cevap eklemeye karar verdim ..

Diyelim ki A ve B dalları var. A dalını B dalına birleştirdiniz ve B dalını kendinize ittiniz, böylece birleştirme artık bir parçası .. Ama birleştirme işleminden önceki son işleme geri dönmek istiyorsunuz .. Ne yapalım? siz yapıyorsunuz?

  1. Git root klasörünüze gidin (genellikle proje klasörü) ve git log
  2. Son işlemlerin geçmişini göreceksiniz - işlemlerin taahhüt / yazar / tarih özellikleri varken birleştirmelerin bir birleştirme özelliği de vardır - böylece bunları şöyle görürsünüz:

    commit: <commitHash> Merge: <parentHashA> <parentHashB> Author: <author> Date: <date>

  3. Kullanın git log <parentHashA>ve git log <parentHashB>- bu ana dalların taahhüt geçmişlerini göreceksiniz - listedeki ilk taahhütler en son olanlardır

  4. İstediğiniz <commitHash>taahhüdü alın, git kök klasörünüze gidin ve kullanın git checkout -b <newBranchName> <commitHash>- bu birleştirme işleminden önce seçtiğiniz son işlemden başlayarak yeni bir dal oluşturur .. Voila, hazır!


0

Ayrıca bu sorunu GitHub repo'sunun ana şubesi ile birleştirilen bir halkla ilişkilerde de yaşadım.

Ben sadece bazı modifiye dosyaları değiştirmek istedim ama tamamını değil değişiklikler PR getirdi beri, zorunda olan .amendmerge commitgit commit --am

Adımlar:

  1. Değiştirilmiş bazı dosyaları değiştirmek / geri almak istediğiniz şubeye gidin
  2. Değiştirilen dosyalara göre istediğiniz değişiklikleri yapın
  3. koş git add *ya dagit add <file>
  4. koş git commit --amve doğrula
  5. Çalıştırmak git push -f

Neden ilginç:

  • PR yazarının değişmeden kalmasını sağlar
  • Git ağacını kırmaz
  • Committer olarak işaretlenirsiniz (birleştirme taahhüdü yazarı değişmeden kalır)
  • Git, anlaşmazlıkları çözmüş gibi davranır, değiştirilmiş dosyalardaki kodu, GitHub'a manuel olarak olduğu gibi birleştirmemesini söyler gibi kaldırır / değiştirir

0

Bu bağlantıdan Birleştirme Nasıl Geri Dönülür için iyi bir açıklama buldum ve aşağıdaki açıklamayı yapıştırdım ve aşağıdaki bağlantı çalışmazsa yardımcı olacaktır.

Hatalı bir birleşme nasıl geri alınır Alan (alan@clueserver.org) dedi:

Bir ana dalım var. Bazı geliştiricilerin üzerinde çalıştığı bir şubemiz var. Hazır olduğunu iddia ediyorlar. Ana dalda birleştiriyoruz. Bir şeyleri kırar, böylece birleşmeyi geri alırız. Kodda değişiklik yaparlar. onlar-cekti var olmak ok ve tekrar birleştirmek bir noktaya olsun. İncelendiğinde, geri dönmeden önce yapılan kod değişikliklerinin ana dalda olmadığını, ancak sonraki kod değişikliklerinin ana dalda olduğunu görürüz. ve bu durumdan kurtulmak için yardım istedi.

"Birleşmenin geri dönüşü" nün hemen ardından tarih şöyle görünecektir:

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

A ve B, çok iyi olmayan yan gelişimde, M, bu erken değişiklikleri ana hatta getiren birleşme, x, yan dalın yaptığı ve ana hatta zaten yaptığı şeyle ilgili olmayan değişikliklerdir ve W, " M birleşimini geri döndür "(W baş aşağı bakmıyor mu?). IOW, "diff W ^ .. W", "diff -RM ^ .. M" ye benzer.

Böyle bir birleşmenin "geri dönüşü" aşağıdakilerle yapılabilir:

$ git revert -m 1 M Yan dal geliştiricileri hatalarını düzelttikten sonra tarih şöyle görünebilir:

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

C ve D, A ve B'de kırılanları düzeltmek içindir ve W'dan sonra ana hat üzerinde başka değişiklikleriniz olabilir.

Güncellenmiş yan dalı birleştirirseniz (D ucunda), A veya B'de yapılan değişikliklerin hiçbiri sonuçta olmaz, çünkü W tarafından geri döndürülürler. Alan'ın gördüğü buydu.

Linus durumu açıklıyor:

Düzenli bir taahhüdü geri almak, söz konusu taahhüdün yaptıklarını etkili bir şekilde geri alır ve oldukça basittir. Ancak bir birleştirme taahhüdünü geri almak aynı zamanda taahhüdün değiştiği verileri geri alır , ancak birleştirmenin tarih üzerindeki etkileri üzerinde kesinlikle hiçbir şey yapmaz . Böylece birleştirme hala var olacak ve yine de iki dalı birleştirmek olarak görülecek ve gelecekteki birleşmeler bu birleşmenin son paylaşılan devlet olarak görüleceğini - ve birleşmeyi geri döndüren geri dönüşün bunu etkilemeyeceğini görecektir. Yani bir "geri alma" veri değişikliklerini geri alır, ama çok fazla değilbir taahhüdün depo tarihi üzerindeki etkilerini geri almaması anlamında bir "geri al". Eğer "geri al" ı "geri al" olarak düşünürseniz, geri dönüşlerin bu kısmını her zaman özleyeceksiniz. Evet, verileri geri alır, ancak hayır, geçmişi geri almaz. Böyle bir durumda, ilk önce geçmişi geri döndürmek istersiniz, bu da tarihin böyle görünmesini sağlar:

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

burada Y, W'nin geri dönüşüdür. Böyle bir "geri dönüş" geri dönüşü şu şekilde yapılabilir:

$ git revert W Bu geçmiş (W ve W..Y'nin değiştirdiği şeyler arasındaki olası çakışmaları yok sayarak), geçmişte W veya Y'ye sahip olmamakla eşdeğerdir:

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

ve yan dalın yeniden birleştirilmesi, daha önceki bir geri dönüş ve geri dönüşten kaynaklanan bir çatışmaya sahip olmayacaktır.

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

Elbette C ve D'de yapılan değişiklikler hala x'in herhangi biri tarafından yapılanlarla çelişebilir, ancak bu sadece normal bir birleşme çatışmasıdır.


-2

Ryan'ın belirttiği gibi, git revertbirleşmeyi yolda zorlaştırabilir, bu yüzden git revertistediğiniz şey olmayabilir. git reset --hard <commit-hash-prior-to-merge>Burada komutun daha kullanışlı olduğunu gördüm .

Sert sıfırlama parçasını yaptıktan sonra, uzak dalı, yani genellikle adlandırılan git push -f <remote-name> <remote-branch-name>yere zorla itebilirsiniz . Bu noktadan sonra yeniden birleştirebilirsiniz.<remote-name>origin


4
Repoyu kullanan tek kişi değilseniz ve ne yaptığınızı tam olarak bilmediğiniz sürece, zorlama içeren her şey kötü bir fikirdir. Git geri döndürme ile geri dönme ve sonra git geri döndürme ile geri döndürme (bir şeyleri tekrar geri getirmeniz gerekiyorsa) çok daha güvenli bir alternatiftir.
oyvind
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.