git cherry-pick “… 38c74d bir birleştirme ancak -m seçeneği verilmedi” diyor


518

Ana dalımda bazı değişiklikler yaptım ve bunları yukarı doğru getirmek istiyorum. Ben kiraz almak zaman aşağıdaki taahhütleri ancak git diyor ki fd9f578 takılıp:

$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.

Git bana ne söylemeye çalışıyor ve cherry-burada kullanmak için doğru olanı seçiyor mu? Ana dal, yukarı akış dalında değiştirilmiş dosyalarda değişiklikler içerir, bu yüzden eminim bazı birleştirme çakışmaları olacak, ancak bu düzeltmek için çok kötü değil. Nerede hangi değişikliklerin gerekli olduğunu biliyorum.

Bunlar yukarı doğru getirmek istediğim taahhütler.

e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...

Yanıtlar:


606

Bir kiraz toplamanın çalışma şekli, bir değişiklik kümesinin temsil ettiği farkı (o noktadaki çalışma ağacı ile ebeveyninin çalışma ağacı arasındaki fark) alarak ve mevcut dalınıza uygulayarak.

Yani, bir taahhüdün iki veya daha fazla ebeveyni varsa, aynı zamanda iki veya daha fazla farkı temsil eder - hangisi uygulanmalıdır?

fd9f578İki ebeveynle birleşen kiraz seçimine çalışıyorsun . Bu nedenle, kiraz toplama komutuna, farkı kullanarak hangisinin hesaplanacağını söylemeniz gerekir -m. Örneğin git cherry-pick -m 1 fd9f578, temel olarak ebeveyn 1'i kullanmak için.

Özel durumunuz için kesin olarak söyleyemem, ancak git mergebunun yerine kullanmak git cherry-pickgenellikle tavsiye edilir. Eğer bir birleştirme taahhüt kiraz almak, bu daraltır tüm size belirtmedi ebeveyn yapılan değişiklikleri -mbu içine bir taahhüt . Tüm tarihlerini kaybedersiniz ve tüm farklarını bir araya getirirsiniz. Çağrınız.


3
@wufoo Muhtemelen de öğrenmelisiniz git rebase- bu bir birleşme gibidir, ancak iki dalı entegre etmek yerine birini diğerinin üzerine oturmak üzere nakletir.
Borealid

91
ebeveyn numarasını nasıl biliyorsun?
Mart'ta Anentropik

66
@Anentropik 1 "birinci ebeveyn", 2 "ikinci ebeveyn" vb. Sıra, taahhütte listelendikleri sıradır ( git showve benzeri göründüğü gibi).
12'de Borealid

2
@lkraav Ayrıca git reset --hard HEAD@{1}eksik taahhüdünüzü geri almak için bir de yapmış olabilirsiniz . git resettarihte "geriye" gitmekle sınırlı değildir. git checkout -b mybranch HEAD@{1}de işe yarar.
Borealid

4
UYARI: git mergeistenmeyen sonuçları olabilir. Bu komut, üst dalda bulunan diğer tüm (eski) taahhütleri ekler. Genellikle insanlar kiraz seçmeyi tercih ederler, çünkü diğer taahhütleri istemezler. Yalnızca istediğiniz değişiklikleri uyguladığınızı iki kez kontrol ettiğinizden emin olun!
Kay V

52

-m ana numara anlamına gelir.

Git doc'dan:

Genellikle bir birleştirmeyi seçemezsiniz, çünkü birleştirmenin hangi tarafının ana hat olarak kabul edilmesi gerektiğini bilmiyorsunuz. Bu seçenek, ana hattın üst numarasını (1'den başlayarak) belirtir ve kiraz seçiminin, belirtilen üst öğeye göre değişikliği yeniden oynatmasına izin verir.

Örneğin, taahhüt ağacınız aşağıdaki gibi ise:

- A - D - E - F -   master
   \     /
    B - C           branch one

Sonra git cherry-pick Esen karşılaştığı sorunu üretecek.

git cherry-pick E -m 1kullanarak anlamına gelir D-Eiken, git cherry-pick E -m 2araç kullanılarak B-C-E.


32

@ Borealid'in cevabı doğrudur, ancak bir dalın tam birleşme geçmişini korumayı umursamadığınızı ve sadece onun doğrusallaştırılmış bir versiyonunu seçmek istediğinizi varsayalım. İşte bunu yapmanın kolay ve güvenli bir yolu:

Başlangıç ​​durumu: Xdaldasınız ve taahhütleri kiraz almak istiyorsunuz Y..Z.

  1. git checkout -b tempZ Z
  2. git rebase Y
  3. git checkout -b newX X
  4. git cherry-pick Y..tempZ
  5. (isteğe bağlı) git branch -D tempZ

Ne yapar bir şube yaratmaktır tempZdayanan Z, fakat tarihi ile Yileriye doğrusallaştırılmış ve daha sonra bir kopyasını üzerine o kiraz almak Xdenir newX. (Bunu mutasyon yapmak yerine yeni bir dalda yapmak daha güvenlidir X.) Elbette 4. adımda olağan şekilde çözmeniz gereken çatışmalar olabilir ( bu açıdan cherry-pickçok rebaseişe yarar). Sonunda geçici tempZdalı siler .

Adım 2 "Geçerli şube tempZ güncel" iletisini veriyorsa, Y..Zzaten doğrusal ise, bu iletiyi yok sayın ve 3. adımdan devam edin.

Sonra inceleyin newXve bunun istediğinizi yapıp yapmadığını görün.

(Not: Bu, git rebase Xdalda basit olanla aynı değildir Z, çünkü Xve arasındaki ilişkiye hiçbir şekilde bağlı değildir Y; Ortak ata ile Yistemediğiniz arasında bir taahhüt olabilir .)


1
git rebase YdiyorCurrent branch tempZ is up to date
Basilevs

Bunun Y..Zzaten doğrusal olduğu anlamına geliyor . Böylece bu mesajı görmezden gelebilir ve 3. ve 4. adımlarla devam edebilirsiniz.
Daira Hopwood

1
İlginç bir fikir, neler olup bittiğini tam olarak takdir etmek için kağıt üzerine çizmek zorunda kaldım = D
Chris

2
Parlak. git cherry-pick bir dizi için ya -m seçeneği eksik ya da sağlandı şikayet etti. Çözümünüz altındı. (Bir öneri: tempZ şubesini sil)
Otheus

1
bu harika! Ben kiraz toplama ile mücadele ve sadece bu mantıklı. Alınan harflerle biraz sorun yaşadım (bazı şubeler ve taahhütler büyük harfler ve bazı şubeler küçük)
pcarvalho

19

Basitleştirin. Taahhütleri kiraz topla. Birleştirmeyi kiraz seçmeyin.

İşte olası yaklaşımların avantajlarını / risklerini ideal bir şekilde açıklayan kabul edilen cevabın yeniden yazımı:

İki ebeveyn ile birleştirme olan fd9f578'i kiraz almaya çalışıyorsunuz.

Bir birleştirmeyi kiraz toplamak yerine, en basit şey, birleştirme işlemindeki her daldan gerçekte istediğiniz taahhütleri kiraz olarak seçmektir.

Zaten birleştirme yaptığınızdan, büyük olasılıkla istediğiniz tüm taahhütler listenizdedir. Kirazları doğrudan seçin ve birleştirme taahhüdüyle uğraşmanıza gerek yok.

açıklama

Bir kiraz toplamanın çalışma şekli, bir değişiklik kümesinin temsil ettiği farkı (o noktadaki çalışma ağacı ile ebeveyninin çalışma ağacı arasındaki fark) almak ve değişiklik kümesini geçerli dalınıza uygulamaktır.

Bir taahhüdün bir birleştirmede olduğu gibi iki veya daha fazla ebeveyni varsa, bu taahhüt de iki veya daha fazla farkı temsil eder. Hata, farkın uygulanması gereken belirsizlik nedeniyle oluşur.

alternatifleri

Birleştirme ve kiraz toplama ile ilgili taahhütleri dahil etmeniz gerektiğini belirlerseniz, iki seçeneğiniz vardır:

  1. (Daha karmaşık ve belirsiz; ayrıca geçmişi atar) hangi ebeveynin başvurması gerektiğini belirtebilirsiniz.

    • -mBunu yapmak için seçeneği kullanın . Örneğin, birleştirme git cherry-pick -m 1 fd9f578işleminde listelenen ilk üst öğeyi temel olarak kullanır.

    • Ayrıca bir birleştirme taahhüt kiraz almaya gelirken, daraltıldığında düşünün tüm size belirtmedi ebeveyn yapılan değişiklikleri -mbu içine bir taahhüt . Tüm tarihlerini kaybedersiniz ve tüm farklarını bir araya getirirsiniz. Çağrınız.

  2. (Daha basit ve daha tanıdık; geçmişi korur) git mergeyerine kullanabilirsiniz git cherry-pick.

    • Her zaman olduğu gibi git merge, birleştirdiğiniz dalda bulunan tüm taahhütleri uygulamaya çalışacak ve bunları git günlüğünüzde ayrı ayrı listeleyecektir.

2

@Daira Hopwood yönteminin basitleştirilmesi tek bir taahhüt seçmek için iyi. Geçici şubeye gerek yok.

Yazar durumunda:

  • Z aranıyor (fd9f578)
  • Y ondan önce
  • X mevcut çalışma dalı

o zaman yap:

git checkout Z   # move HEAD to wanted commit
git reset Y      # have Z as changes in working tree
git stash        # save Z in stash
git checkout X   # return to working branch
git stash pop    # apply Z to current branch
git commit -a    # do commit

2
Bu elbette orijinal işlemle ilişkili meta verileri kaybeder. Sanırım daha basit olup olmadığı bir görüş meselesi. Ben ne zaman Bazen bunu kullanırım istediğiniz meta verileri kaybeder ve sadece genel kod değişiklikleri tutmak. Y'nin Z'nin hemen bir ebeveyni olmasa bile çalıştığını unutmayın (bu durumda değişiklikler ezilir).
Daira Hopwood
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.