Rebase'den sonra şubeye zorlayamazsınız


131

Git kullanıyoruz ve bir master şubemiz ve geliştirici şubelerimiz var. Yeni bir özellik eklemem ve ardından taahhütleri ana olarak yeniden düzenlemem, ardından ana bilgisayarı CI sunucusuna göndermem gerekiyor.

Sorun şu ki, yeniden yükleme sırasında çakışmalarım olursa, yeniden temelleme tamamlandıktan sonra uzaktaki şubemi çekene kadar uzak geliştirici dalıma (Github'da) aktaramıyorum. Bu, yinelenen kayıtlara neden olur. Çatışma olmadığında beklendiği gibi çalışır.

soru: yeniden bağlama ve çakışma çözümlemesinden sonra, yerel ve uzak geliştirici dallarımı yinelenen kaydetmeler oluşturmadan nasıl eşitleyebilirim

Kurmak:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

DÜZENLE

Bu yüzden iş akışını bozacak gibi görünüyor:

geliştirici1 myNewFeature geliştirici üzerinde çalışıyor2 hisNewFeature üzerinde çalışıyor, her ikisi de ana dal olarak ana dalı kullanıyor

geliştirici2 myNewFeature'ü Yeni Özelliği ile birleştirir

geliştirici1 yeniden adlar, çakışmaları çözer, ardından myNewFeature için uzak şubeye zorlar

birkaç gün sonra, geliştirici2, myNewFeature'ü tekrar NewFeature ile birleştirir

Bu, diğer geliştiricilerin geliştirici1'den nefret etmesine neden olacak mı?


bir çözüm değil, sadece bir düşünce. kim we? senden daha fazlası olan bir takımda mısın? they(benden daha fazlasını bilenler) eğer kodunuzu paylaşırsanız kullanmamanız gerektiğini söyleyin rebase. Neden yapmıyorsun git pullve git merge?
AdamT

üzgünüz, Biz = geliştirme ekibi
Matt

1
yani evet, muhtemelen kodu paylaşırken yeniden satış yapmamalısınız. bu, aşağıda listelenenlere benzer şeyler yapmak zorunda kalmanıza neden olabilir ( forceitme)
AdamT

oh pardon, dedikleri zaman rewriting history, bu birrebase
AdamT

Yanıtlar:


93

Öncelikle, sizin ve birlikte çalıştığınız kişilerin, bir konu / geliştirme şubesinin paylaşılan geliştirme için mi yoksa sadece size ait mi olduğuna karar vermeniz gerekir. Diğer geliştiriciler, geliştirme dallarımda birleşmemeleri gerektiğini biliyorlar çünkü bunlar herhangi bir zamanda yeniden fiyatlandırılacaklar. Genellikle iş akışı aşağıdaki gibidir:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

Ardından uzaktan kumandayla güncel kalmak için aşağıdakileri yapacağım:

 git fetch origin
 git checkout master
 git merge --ff origin/master

Bunu iki nedenden dolayı yapıyorum. Birincisi, geliştirme şubemden geçiş yapmaya gerek kalmadan uzaktan değişiklikler olup olmadığını görmeme izin veriyor. İkincisi, saklanmayan / kaydedilen değişikliklerin üzerine yazmadığımdan emin olmak için bir güvenlik mekanizmasıdır. Ayrıca, ana dala hızlı ileri saramazsam, bu, ya birinin uzaktaki ana bilgisayarı yeniden başlattığı (bunun için ciddi şekilde kırbaçlanması gerektiği) ya da yanlışlıkla ustalaşmayı taahhüt ettiğim ve sonumu temizlemem gerektiği anlamına gelir.

Sonra uzaktan kumandada değişiklikler olduğunda ve en yenisine hızlıca ilettiğimde, yeniden destekleyeceğim:

git checkout devel0
git rebase master
git push -f origin devel0

Daha sonra diğer geliştiriciler, devel şubelerini en son sürümümden yeniden düzenlemeleri gerektiğini biliyorlar:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

Hangi daha temiz bir geçmişle sonuçlanır:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

Yapma ileri geri kapris de kaydedilmesini birleştirme. Yalnızca yinelenen taahhütler oluşturmak ve geçmişi takip etmeyi imkansız kılmakla kalmaz, belirli bir değişiklikten gerilemeleri bulmak neredeyse imkansız hale gelir (bu yüzden ilk etapta sürüm kontrolünü kullanıyorsunuz, değil mi?). Yaşadığınız sorun, sadece bunu yapmanın sonucudur.

Ayrıca, diğer geliştiriciler sizin geliştirme dallarınız için taahhütler yapıyor gibi görünüyor. Bunu onaylayabilir misin?

Birleştirmenin tek zamanı, konu dalınızın kabul edilmeye hazır olduğu zamandır. master .

Bir yan not olarak. Birden fazla geliştirici aynı depoya bağlılık gösteriyorsa, geliştiricilerin geliştirme dalları arasında ayrım yapmak için adlandırılmış dalları kullanmayı düşünmelisiniz. Örneğin:

git branch 'my-name/devel-branch'

Dolayısıyla, tüm geliştiriciler konu dalları kendi iç içe geçmiş kümelerinde bulunur.


1
"Ayrıca, diğer geliştiriciler sizin geliştirme şubelerinize taahhütte bulunuyor gibi görünüyor. Bunu onaylayabilir misiniz?" EVET onlar ...
Matt

Ayrıca başka bir konuya dikkatimi çektiniz. Ofis ve ev arasında çalışmak. Her iki yerde de birleşmeler yapıyorum ve günün sonunda basıyorum ki kaldığım yerden devam edebiliyorum. Sonra yeniden satış yapma zamanı geldiğinde, tüm bu taahhütler kafa karışıklığı yaratır. Şubelerimi tek bir şube olarak değerlendirmem ve yeniden ödemem gerekiyor
Matta

@Matt Evet, bu iki sorun iş akışınızı gerçekten bozacak. İlk olarak, diğer geliştiricilere yalnızca sahibinin adlandırılmış bir dallanmış (örneğin 'matt / devel') taahhüt edebileceğini bildirirdim. IMHO, iki geliştirici zaten aynı şubeye taahhüt vermemelidir. Sadece kafa karışıklığı yaratır. Daha sonra, yeniden destekleme ve zorlama, iki konumu güncel tutmalıdır.
Trevor Norris

Mükemmel cevap. Bir yan sorum var, --forcebunu yaparken neden bayrağı kullanıyorsun git push -f origin devel0?
Nobita

2
@Nobita Bir git pushhızlı ileri sarılamadığında (yani sha geçmişi eşleşmediğinde), öğesinden oluşturulan yeni geçmişi önceki geçmişin üzerine yazmak için zorlamalısınız git rebase.
Trevor Norris

50

Taahhütleri satırın daha aşağısına taşıdıkça itmeyi zorlamanız gerekir git, dalın ucuna taahhütler eklemenizi bekliyor. git push -f origin myNewFeaturesorununuzu çözecek.

İpucu: Yukarıda meşru bir zorlama kullanımı var. Geçmişi asla halka açık bir depoya yeniden yazmayın, yoksa birçok insan sizden nefret eder.


1
Bunu, iş akışını sürdürmenin en uygun yolu buluyorum.
Syed Priom

1
Teşekkürler dostum. Bu komutu, yeniden düzenlenen yerel şubemi aynı uzak şubeye zorlamak için kullandım.
wei

11
kullanmak kullanmaktan git push --force-with-leaseçok daha güvenlidirgit push --force

git push --force-with-lease origin HEAD- hedef şubenizin zaten kontrol edildiğini varsayarsak
Lucaci Sergiu

31

Burada akılda tutulması gereken en önemli şey, perde arkasında çekme ve geri çekmenin ne yaptığıdır.

Çekme temelde iki şey yapar: getir ve birleştirme. --Rebase'i dahil ettiğinizde, birleştirme yerine bir yeniden ödeme yapacaktır.

Yeniden ödeme, dallanmanızdan bu yana tüm yerel değişikliklerinizi saklamak, şubenizi hedefteki en son taahhüde hızlı bir şekilde iletmek ve değişikliklerinizi en üstte sırayla açmak gibidir.

(Bu, bir yeniden ödeme yaparken neden birden fazla uyuşmazlık çözümü istemine karşı birleştirme ile elde edebileceğiniz bir uyuşmazlık çözümü alabileceğinizi açıklar. Taahhütlerinizi başka şekilde korumak için, yeniden ödenen HER taahhüdündeki bir çatışmayı çözme fırsatına sahipsiniz. )

Bu, geçmişi yeniden yazdığından, yeniden yapılan değişiklikleri asla uzak dallara göndermek istemezsiniz. Genelde, neredeyse her zaman istisnalar olduğu için asla biraz güçlü değildir. Örneğin, belirli bir ortamda çalışmak için yerel deponuzun uzak bir sürümünü korumanız gereken durum.

Bu, yeniden yapılan değişiklikleri zaman zaman zor kullanarak zorlamanızı gerektirir:

git push -f origin newfeature

Veya bazı durumlarda yöneticiniz zorlama özelliğini kaldırmış olabilir, bu nedenle silmeniz ve yeniden oluşturmanız gerekir:

git push origin :newfeature
git push origin newfeature

Her iki durumda da, uzaktaki şubenizde başka biri sizinle işbirliği yapıyorsa ne yaptığınızı bildiğinizden kesinlikle emin olmalısınız. Bu, başlangıçta birleşmelerle birlikte çalıştığınız ve bunları, çalışma dalınızda uzmanlaşmadan ve kaldırmadan hemen önce daha yönetilebilir bir taahhüt biçimine yeniden bağladığınız anlamına gelebilir.

Aşağıdakilerden yararlanarak neredeyse her zaman git'in GC'sine geri dönebileceğinizi unutmayın:

git reflog

Tüm geri ödeme / çatışma yönetiminizde kaybolursanız daha istikrarlı bir duruma geri dönebileceğiniz için bu BÜYÜK bir hayat kurtarıcıdır.


Yukarıdaki sil ve yeniden oluştur seçeneği benim için iyi çalıştı. Depomda zorlamaya izin yok!
Simon Holmes

2

Zorunlu bir itme yapmanız gerekiyor, yani git push -f origin myNewFeature

Oh, ve insanların geliştirme dalınıza hiçbir şey dayandırmadığından emin olsanız iyi olur - genellikle tarihi yeniden yazdığınız şubeleri yayınlamamanız gerekir (daha doğrusu, yayınlandıktan sonra tarihi yeniden yazmazsınız). Bunun bir yolu, bir şube adı kullanmak wip/myNewFeatureve daha sonra wipşubelerin zaman zaman ustalaşmak için yeniden borçlandırılacağını belirtmektir .


kullanmak kullanmaktan git push --force-with-leaseçok daha güvenlidirgit push --force

@MrCholo İnsanlar git -fnormal bir zorla itme gibi kısa bir seçenek ekleyene kadar bunu kullanmaya başlamayacaklar :)
ThiefMaster

ha evet, otomatik bir komut dosyasında kullandım tho

2

Zaten verilen genel cevap - yeniden yapılan git push -f origin myNewFeaturedeğişiklikleri zorlarken kullanmak için - iyi bir başlangıç ​​noktasıdır. Bu yanıtı, iş akışınızı bozup bozmayacağıyla ilgili düzenlemeyi ele almak için yazıyorum.

Size kullanıyor gidiyoruz olduğunu varsayarsak git pull --rebase ...(veya bu konuda biraz varyasyon), uzaktan dalına bir kuvvet-itme tarafından sonları sizin örnekte iş akışı developer2 birleşiyor olması ardından şeyi takip myNewFeatureiçine hisNewFeature. Başka kimse o dal üzerinde çalışmadığı sürece kendi özellik dalınızı yeniden oluşturabilmeniz mantıklıdır, bu nedenle dal bölgesini sınırlamak için kurallara ihtiyacınız vardır.

Bunu aşmak için a) yalnızca kendinizden birleştireceğiniz bir kural masteroluşturarak veya b) developkendi myNewFeatureşubenizi temel aldığınız bir kolektif şube oluşturarak ve yalnızca birleştireceğiniz bir kural oluşturarak geçebilirsiniz.develop . masterdaha sonra yalnızca kilometre taşları veya sürümler için ayrılacak (veya bunu ne şekilde ayarlamak isterseniz) ve developdiğer özellik dallarına entegre edilmeye hazır olduğunda her bir özelliği ittiğiniz yer olacaktır.

Bunun Gitflow iş akışının basitleştirilmiş bir sürümü olarak düşünülebileceğine inanıyorum.


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.