Birden fazla taahhüt kiraz nasıl seçilir


875

İki şubem var. Teslim adiğer sahipken, birinin başıdır b, c, d, eve füstünde a. Ben taşımak istiyor c, d, eve ftaahhüt olmadan ilk dalına b. Kiraz onu almak kullanımı kolaydır: ödeme ilk şubesi birer birer kiraz almak ciçin fve birinci üzerine ikinci şubesini rebase. Ama bütün kiraz almak için herhangi bir yol yoktur c- fbir komuta?

İşte senaryonun görsel bir açıklaması (teşekkürler JJD ):

resim açıklamasını buraya girin


3
bahsettiğiniz rebase soru için gerçekten alakalı değil mi? (Daha sonra bdayanmak isteyebilirsin f, ama kiraz toplama ile ilgisi yok.)
Superole

Yanıtlar:


1281

Git 1.7.2 kiraz bir dizi taahhüt seçebilme özelliğini tanıttı. Gönderen sürüm notları :

git cherry-pickbir dizi taahhüt seçmeyi öğrendi (ör. cherry-pick A..Bve cherry-pick --stdin) git revert; bunlar rebase [-i]olsa da güzel sıralama kontrolü desteklemiyor .

Taahhüt gelen tüm kaydedilmesini kiraz-almak Aişlemeye B(burada Adaha eski B), çalıştırın:

git cherry-pick A^..B

A'nın kendisini yok saymak istiyorsanız , çalıştırın:

git cherry-pick A..B

(Yorumlarda kredi damian, JB Rainsberger ve sschaef'e gidiyor)


249
"Cherry-pick A..B" formunda, A B'den büyük olmalıdır. Yanlış sıralarsa komut sessizce başarısız olur.
damian

294
Ayrıca, bu kiraz A'yı seçmez, aksine A'dan B'ye kadar ve B dahil her şey
JB Rainsberger

455
A just typegit cherry-pick A^..B
kiritsuku

17
Eğer 1.7.1 git veya daha önceki ve olamaz güncelleştirme varsa, oldukça hızlı çalıştırarak bunları sırayla kiraz seçebilirsiniz git cherry-pick f~3ardından git cherry-pick f~2vb kadar git cherry-pick fçabuk numarası ve çalıştırmak önceki komut değiştirebilir alır böylece yukarı ok tuşuna basarak ( çoğu konsolda benzer olmalıdır).
David Mason

19
Bu sözdiziminin şube adlarıyla da çalıştığını bilmek iyi olabilir. git cherry-pick master..somebranchmaster'dan beri tüm taahhütleri seçer (zaten master'a dayandırıldığı varsayılarak) ve mevcut şubenize uygular.
Tor Klingberg

103

Bunu yapmanın en basit yolu ontoseçeneği ile rebase. Varsayalım de şube hangi akım bitirir o amybranch denir ve bu taşımak istediğiniz bu dalıdır c- füzerine.

# checkout mybranch
git checkout mybranch

# reset it to f (currently includes a)
git reset --hard f

# rebase every commit after b and transplant it onto a
git rebase --onto a b

1
Teşekkür ederim! git checkout secondbranch && git rebase mybranchTam cevap için de ekleyebilir misiniz
tig

1
Bu cevap, bu senaryoda hangi taahhüdün hangisi olduğunu kafama getirmeme yardımcı oldu. Ve: rebase'ın interaktif modunu da kullanabilirsiniz. Teşekkürler @Charles!
Oliver

1
Bu yaklaşımın güzelliği, --interactivebazı taahhütleri diziden çıkarmak veya "kiraz toplama" ndan önce yeniden sıralamak için kullanabilmenizdir. +1
Michael Merickel

Bu cömert bir komut, kafanı sarmak biraz zor ama harikalar yaratıyor.
Valerio

Yabani Eğer bunu taahhüt vermek zorunda değilsiniz (argumente biri olarak rebase istediğiniz bbu örnekte) ama evet bu benim için çalıştı.
asontu


68

Bir seri taahhüdü kullanabilir git rebaseve git branchbir grup taahhüdü başka bir dala uygulayabilirsiniz. Wolfc tarafından zaten yayınlandığı gibi , ilk komut taahhütleri kopyalar. Ancak, grubun en üst düzeyine bir dal adı ekleyene kadar değişiklik görünmez.

Lütfen resmi yeni bir sekmede aç ...

İş Akışı

Komutları metin biçiminde özetlemek için:

  1. Açık gitk komutunu kullanarak bir bağımsız süreç olarak: gitk --all &.
  2. Koş git rebase --onto a b f.
  3. Basın F5içinde gitk . Hiçbirşey değişmez. Ama hayır HEADişaretlidir.
  4. Çalıştırmak git branch selection
  5. Basın F5içinde gitk . Taahhütleri ile yeni şube görünür.

Bu bazı şeyleri açıklığa kavuşturmalıdır:

  • Taahhüt a, grubun yeni kök hedefidir .
  • Taahhüt b, grubun ilk taahhüdünden önceki taahhüttür (münhasır).
  • Bağlılık f, grubun (dahil) son taahhüdüdür.

Daha sonra, kullanabilirsiniz git checkout feature && git reset --hard bkaydedilmesini silmek ckadar fgelen featureşube.

Bu yanıta ek olarak , başka bir senaryoda komutların genel olarak kullanılmasına yardımcı olacak komutları açıklayan bir blog yazısı yazdım .


2
Artık mybranch (a..f işlemek) gerekli değilse, bu basitleştirilebilir: git rebase --onto a b mybranchve btw - bu şık git resimleri hangi programda?
Mr_and_Mrs_D

2
@Mr_and_Mrs_D Yorumunuz için teşekkürler. Sanırım resimleri çizmek için cacoo.com'u kullandım .
JJD

48

JB Rainsberger ve sschaef'in yorumlarını özellikle soruyu cevaplamak için uygulamak ... Bu örnekte bir kiraz toplama aralığı kullanmak için:

git checkout a
git cherry-pick b..f

veya

git checkout a
git cherry-pick c^..f

3
Kullandığım git 2.7.0.windows.1ve kaydedilmesini ve kiraz toplama aralığı çalıştığınızda her şey yolunda ama git yapmanız gereken her yerde söylemek olmadığını fark git cherry-pick --continue | --abort | --quitsize taahhüt çalışmadan önce / yeniden kiraz-seç. Bu nedenle, bir dizi taahhüdü seçerseniz, git cherry-pick --continueher hazır olduğunuzda (anlaşmazlıkları çözme) verilen aralıktan bir taahhütle çalıştırmanız gerekir .
kuskmen

Tamamen aynı, ama ölümcül: 'a..b' bulunamıyor
Amit Karnik

Nerede yanlış olduğumu bilmiyorum ama yanımda 'git cherry-pick c ^ .. f' yaptığımda, bu f komutunu içerir, ancak c'yi değil. Ama her yerde okuduğumda, c ve f'yi kapsayıcı olarak tanımlamak gerekiyordu. Yoksa yanılıyor muyum?
Samuel

@Samuel evet, bu doğru. ^Sonra c aslında bu durumda b "c önce taahhüt" anlamına gelir. Bu yüzden c^..feşanlamlıdır b..f. Yapmayı deneyin git log c^..fve c ile f arasındaki taahhütleri görmelisiniz, tıpkı sizin yaptığınız gibigit log b..f
Andy

41

Birleştirmek için seçici revizyonlarınız varsa, A, B, C, D, E, F, G, H, I, J'den A, C, F, J diyelim, aşağıdaki komutu kullanın:

git kiraz toplama ACFJ


1
güzel ve basit
spinup

21
git rev-list --reverse b..f | xargs -n 1 git cherry-pick

2
Çatışma yoksa mükemmel çalışır, aksi takdirde "yeniden", nerede durduğunu anlamanız ve yamaların geri kalanını yeniden uygulamanız gerekmeyeceğinden daha kolay olabilir.
Ruslan Kabalin

6
Lütfen bunun ne yaptığını açıklayan yorumlar ekleyin
Mr_and_Mrs_D

7
kimse açıklanmadığı için ... git rev-list, b'den f'ye (tersine çevrilmiş) tüm revizyonları yazdırır, böylece her satır (taahhüt karması) sırayla geçtiğinde, her birini mevcut git HEAD'e kiraz seçer. iegit cherry-pick {hash of c}; git cherry-pick {hash of d}; ...
coderatchet

8

Bir taahhüt kimliğinden dalın ucuna kadar kiraz seçmek için şunları kullanabilirsiniz:

git cherry-pick commit_id^..branch_name


Bu zaten cevabın bir parçası stackoverflow.com/a/31640427/96823
tig

1
Bu cevap aslında farklı ve bana yardımcı oldu. Son taahhüt SHA'sını değil, şube adını belirtir.
Subtletree

7

Bahsetmeye değer başka bir varyant n, bir daldan son taahhütleri istiyorsanız , ~sözdiziminin yararlı olabileceğidir:

git cherry-pick some-branch~4..some-branch

Bu durumda, yukarıdaki komut son 4 taahhüdü denilen bir şubeden seçer some-branch(ancak bir şube adı yerine bir taahhüt karması da kullanabilirsiniz)


1
ÇOK yararlı cevap, teşekkür ederim! :)
Jacek Dziurdzikowski

3

Aslında bunu yapmanın en basit yolu şunlar olabilir:

  1. iki dal arasındaki birleştirme tabanını kaydedin: MERGE_BASE=$(git merge-base branch-a branch-b)
  2. eski şubeyi daha hızlı ilerletin veya yeni şubeye yeniden adlandırın
  3. sonuçta ortaya çıkan dalı, adım 1'deki birleştirme tabanından başlayarak yeniden adlandırın ve istemediğiniz taahhütleri el ile kaldırın:

    git rebase ${SAVED_MERGE_BASE} -i
    

    Alternatif olarak, yalnızca birkaç yeni işlem varsa, 1. adımı atlayın ve yalnızca

    git rebase HEAD^^^^^^^ -i
    

    ilk adımda, ^birleştirme tabanını geçecek kadar kullanarak .

Etkileşimli rebase'de böyle bir şey göreceksiniz:

pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f

Ardından b satırlarını (ve istediğiniz diğerlerini) kaldırın


1
git format-patch --full-index --binary --stdout range... | git am -3

42
Lütfen bunun ne yaptığını açıklayan yorumlar ekleyin
Mr_and_Mrs_D

0

İşte kiraz komutları için şubeleri hangi kaynak ve hedefleyen ve taahhütlerin sayısını belirterek, komut satırına birden fazla komisyonu kiraz halinde seçmenize izin veren bir komut dosyası:

https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81

Şubenizden master'a kiraz seçmek için (geçerli dalı kaynak olarak kullanır):

./gcpl.sh -m

6.19.x şubenizden en son 5 işi ustalıkla seçmek için:

./gcpl.sh -c 5 -s 6.19.x -t master

Doğrudan Git ile yapabildiğinizde bu komut dosyasına neden ihtiyaç duyulur? ...
code_dredd

Daha az yazarak, komut dosyam otomatik olarak taahhütleri sizin için seçer, böylece SHA ile her birini kiraz seçmeniz gerekmez. Her neyse, YMMV.
nickboldt
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.