Aşağıdaki depo düzenine sahibim:
Elde etmek istediğim şey, çalışma dalından bir dizi taahhüt seçmek ve bunları entegrasyon dalıyla birleştirmek. Git'te oldukça yeniyim ve depoyu karıştırmadan bunu tam olarak nasıl yapacağımı (tek bir işlemde commit aralıklarını seçme, birleştirme değil) bulamıyorum. Bu konuda herhangi bir ipucu ya da düşünceniz var mı? Teşekkürler!
Bir dizi taahhüt söz konusu olduğunda, kiraz toplama is was pratik değildir.
Keith Kim]2 tarafından aşağıda belirtildiği gibi, Git 1.7.2+, bir dizi taahhütü kiraz toplama özelliğini tanıttı (ancak yine de gelecekteki birleştirme için kiraz toplamanın sonucunun farkında olmanız gerekir)
git cherry-pick" bir dizi taahhüt seçmeyi öğrendi (örneğin "
cherry-pick A..B
" ve "cherry-pick --stdin
"), "git revert
"; ancak bunlar "rebase [-i]
"'nin sahip olduğu daha güzel sıralama kontrolünü desteklemez.
damian yorumlar ve bizi uyarıyor:
"
cherry-pick A..B
" formunda,A
B
den daha yaşlı olmalıdır.
Eğer sıralama yanlışsa komut sessizce başarısız olacaktır.
Eğer Bden
D`ye (dahil) kadar olan aralığı seçmek isterseniz, bu B^..D
olacaktır.
Örnek olarak "Git create branch from range of previous commits?" bölümüne bakın.
Jubobs'un][7] yorumlarda bahsettiği gibi:
Bu
B
nin bir kök commit olmadığını varsayar; aksi takdirde "bilinmeyen revizyon
" hatası alırsınız.
Not: Git 2.9.x/2.10 (Q3 2016) itibariyle, bir yetim dalda (boş kafa) doğrudan bir dizi işlem yapabilirsiniz: "git'te mevcut dal nasıl yetim yapılır" bölümüne bakın.
Orijinal cevap (Ocak 2010)
Charles Bailey'nin burada tarif ettiği gibi, entegrasyon dalınızın üstünde verilen commit aralığını tekrar oynattığınız bir rebase --onto' daha iyi olacaktır[10]. (ayrıca,
git rebase --onto` uygulamasının pratik bir örneğini görmek için git rebase man page'de "Here is how you would transplant a topic branch based on one branch to another" kısmına bakın)
Mevcut şubeniz entegrasyon ise:
# Checkout a new temporary branch at the current location
git checkout -b tmp
# Move the integration branch to the head of the new patchset
git branch -f integration last_SHA-1_of_working_branch_range
# Rebase the patchset onto tmp, the old location of integration
git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration
Bu, aradaki her şeyi tekrar oynatacaktır:
üst öğesinden sonra (dolayısıyla
~1`): yeniden oynatmak istediğiniz ilk commitintegration
" (bu da working
dalından yeniden oynatmak istediğiniz son commit'e işaret eder)to "tmp
" (integrasyon
un daha önce işaret ettiği yere işaret eder)
Bu taahhütlerden biri tekrar oynatıldığında herhangi bir çakışma olursa:
git rebase --continue
" çalıştırın.git rebase --skip
" çalıştırın;git rebase --abort
" ile her şeyi iptal edin (ve tmp
dalı üzerine integration
dalını geri koyun)Bundan sonra rebase --onto
, integration
entegrasyon dalının son commit'ine geri dönecektir (yani "tmp
" dalı + tüm yeniden oynatılan commitler)
Cherry-picking veya rebase --onto
ile, burada açıklandığı gibi sonraki birleştirmeler üzerinde sonuçları olduğunu unutmayın.
Saf bir "cherry-pick
" çözümü burada tartışılmıştır ve şöyle bir şey içerecektir:
Eğer bir yama yaklaşımı kullanmak istiyorsanız "git format-patch|git am" ve "git cherry" seçeneklerinizdir.
Şu anda,git cherry-pick
yalnızca tek bir commit kabul etmektedir, ancakB
ileD
aralığını seçmek istiyorsanız, bu git dilindeB^..D
olacaktır, yani
git rev-list --reverse --topo-order B^..D | while read rev
do
git cherry-pick $rev || break
done
Ancak yine de, bir dizi taahhütü "yeniden oynatmanız" gerektiğinde, "yeniden oynat" kelimesi sizi Git'in "rebase
" özelliğini kullanmaya itmelidir.
Dalları gerçekten birleştirmek istemediğinize emin misiniz? Çalışma dalında istemediğiniz bazı yeni taahhütler varsa, istediğiniz noktada bir HEAD ile yeni bir dal oluşturabilirsiniz.
Şimdi, herhangi bir nedenle gerçekten bir dizi taahhüt seçmek istiyorsanız, bunu yapmanın zarif bir yolu sadece bir yama kümesini çekmek ve yeni entegrasyon dalınıza uygulamaktır:
git format-patch A..B
git checkout integration
git am *.patch
Bu aslında git-rebase'in zaten yaptığı şeydir, ancak oyun oynamaya gerek yoktur. Birleştirmeniz gerekiyorsa git-am
e --3way
ekleyebilirsiniz. Talimatları harfi harfine uygularsanız, bunu yaptığınız dizinde zaten başka *.patch dosyası olmadığından emin olun...
VonC'nin kodunu]1 kolay çalıştırmak için git-multi-cherry-pick
adında kısa bir bash betiği haline getirdim:
#!/bin/bash
if [ -z $1 ]; then
echo "Equivalent to running git-cherry-pick on each of the commits in the range specified.";
echo "";
echo "Usage: $0 start^..end";
echo "";
exit 1;
fi
git rev-list --reverse --topo-order $1 | while read rev
do
git cherry-pick $rev || break
done
Şu anda bunu, aynı svn gövdesinde hem 3. taraf kodunun hem de özelleştirmelerin birbirine karıştığı bir projenin geçmişini yeniden oluştururken kullanıyorum. Şimdi, ileriye dönük özelleştirmelerin daha iyi anlaşılması için çekirdek 3. taraf kodunu, 3. taraf modüllerini ve özelleştirmeleri kendi git dallarına ayırıyorum. Aynı depoda, ancak ortak bir atası olmayan iki ağacım olduğu için git-cherry-pick
bu durumda yardımcı oluyor.