Git iş akışı ve rebase ve birleştirme soruları


971

Git'i birkaç aydır başka bir geliştiriciyle birlikte bir projede kullanıyorum. SVN ile birkaç yıllık tecrübem var , bu yüzden ilişkiye çok fazla bagaj getirdim.

Git'in dallanma ve birleşme için mükemmel olduğunu duydum ve şimdiye kadar görmüyorum. Elbette, dallanma çok basit, ama birleştirmeye çalıştığımda her şey cehenneme gidiyor. Şimdi, SVN'den alışkınım, ama bana öyle geliyor ki, sadece bir alt-par sürümleme sistemi diğeri için işlem yaptım.

Eşim bana sorunlarımın willy-nilly ile birleşme arzumdan kaynaklandığını ve birçok durumda birleştirme yerine rebase kullanmam gerektiğini söylüyor. Örneğin, işte koyduğu iş akışı:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature

Temel olarak, bir özellik dalı oluşturun, HER ZAMAN masterdan dala yeniden taban oluşturun ve şubeden master'a geri birleştirin. Dikkat edilmesi gereken önemli nokta, dalın her zaman yerel kalmasıdır.

İşte başladığım iş akışı

clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch

İki temel fark var (sanırım): Yeniden temel almak yerine her zaman birleştirme kullanıyorum ve özellik dalımı (ve özellik dalımı taahhüt ediyor) uzak depoya itiyorum.

Uzak dal için gerekçem, çalıştığım sırada işimin yedeklenmesini istiyorum. Depomuz otomatik olarak yedeklenir ve bir şeyler ters giderse geri yüklenebilir. Dizüstü bilgisayarım tam değil. Bu nedenle, dizüstü bilgisayarımda başka bir yere yansıtılmamış kod bulundurmaktan nefret ediyorum.

Rebase yerine birleştirme için nedenim, birleştirmenin standart ve rebase'in gelişmiş bir özellik gibi görünmesidir. Bağırsak hissim, yapmaya çalıştığım şeyin gelişmiş bir kurulum olmadığı, bu yüzden rebase gereksiz olması gerekiyor. Git'teki yeni Pragmatik Programlama kitabını bile inceledim ve birleştirmeden kapsamlı ve zar zor bahsetti.

Her neyse, yeni bir dalda iş akışımı takip ediyordum ve onu ustalıkla birleştirmeye çalıştığımda her şey cehenneme gitti. Fark etmemesi gereken şeylerle tonlarca çatışma vardı. Çatışmalar bana hiç mantıklı gelmedi. Her şeyi halletmek bir günümü aldı ve sonunda yerel ustamın tüm çatışmaları çözdüğü için uzak ustaya zorla iterek sonuçlandı, ancak uzak olan hala mutlu değildi.

Böyle bir şey için "doğru" iş akışı nedir? Git'in dallanmayı ve birleştirmeyi çok kolay hale getirmesi gerekiyor ve görmüyorum.

2011-04-15 Güncellemesi

Bu çok popüler bir soru gibi görünüyor, bu yüzden ilk sorduğumdan beri iki yıllık deneyimimi güncelleyeceğimi düşündüm.

En azından bizim durumumuzda orijinal iş akışının doğru olduğu ortaya çıkıyor. Başka bir deyişle, yaptığımız şey bu ve işe yarıyor:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature

Aslında, iş akışı biraz farklıdır, çünkü çiğ birleştirmeler yerine kabak birleştirmeler yapma eğilimindeyiz . ( Not: Bu tartışmalıdır, aşağıya bakın. ) Bu, tüm özellik dalımızı master üzerinde tek bir işleme dönüştürmemizi sağlar. Sonra özellik dalımızı sileriz. Bu, şubelerimizde biraz dağınık olsalar bile, taahhütlerimizi usta üzerinde mantıksal olarak yapılandırmamızı sağlar. Yani, yaptığımız şey bu:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature

Squash Birleştirme Tartışması - Birkaç yorumcunun işaret ettiği gibi, squash birleştirme özellik dalınızdaki tüm geçmişi atar. Adından da anlaşılacağı gibi, tüm taahhütleri tek bir parça halinde eziyor. Küçük özellikler için, bu onu tek bir pakette yoğunlaştırdığı için mantıklıdır. Daha büyük özellikler için, özellikle de bireysel taahhütleriniz zaten atomsa, muhtemelen harika bir fikir değildir. Gerçekten kişisel tercihinize bağlı.

Github ve Bitbucket (diğerleri?) Çekme İstekleri - Birleştirme / yeniden oluşturma işleminin Çekme İstekleri ile nasıl ilgilendiğini merak ediyorsanız, master'a geri dönmeye hazır olana kadar yukarıdaki tüm adımları izlemenizi öneririz. Git ile manuel olarak birleştirmek yerine, sadece PR'yi kabul edersiniz. Bunun bir squash birleştirme yapmayacağını (en azından varsayılan olarak değil), ancak Squash olmayan, hızlı ilerlemenin Çekme İsteği topluluğunda (bildiğim kadarıyla) kabul edilen birleştirme kuralı olduğunu unutmayın. Özellikle, şu şekilde çalışır:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin

Git'i sevmeye geldim ve asla SVN'ye geri dönmek istemiyorum. Eğer mücadele ediyorsanız, sadece buna uyun ve sonunda tünelin sonunda ışığı göreceksiniz.


31
Ne yazık ki, yeni Pragmstic Programming kitabı çoğunlukla SVN'de düşünürken Git'i kullanmaktan yazılmıştır ve bu durumda sizi yanlış yönlendirmiştir. Git'te rebase, işleri olabildiğince basit tutar. Deneyiminiz Git'in çalışmadığı değil, iş akışınızın Git'te çalışmadığını söyleyebilir.
Paul

18
Birleştirilen şey hakkında hiçbir bilgi kaydetmediği için bu durumda squash birleştirmeyi tavsiye etmem (sadece svn gibi, ancak burada birleştirme yok).
Marius K

7
Altta notu seviyorum, Git ile benzer bir mücadele deneyimim vardı, ama şimdi bunu kullanmadığınızı hayal etmek için mücadele ediyorum. Son açıklama için de teşekkürler, rebaseanlayışla çok yardımcı oldu
Jon Phenow

6
Özelliği bitirdikten sonra, new_feature'ı master yapmak için birleştirmeden önce son bir kez yeniden adlandırma yapmamalısınız?
softarn

17
İş
akışınız

Yanıtlar:


371

"Çatışmalar", "aynı içeriğin paralel evrimleşmeleri" anlamına gelir. Birleştirme sırasında "hepsi cehenneme" giderse, aynı dosya kümesinde büyük evrim geçirdiğiniz anlamına gelir.

Bir rebase'in bir birleştirmeden daha iyi olmasının nedeni şudur:

  • yerel taahhüt geçmişinizi kaptanın biriyle yeniden yazarsınız (ve daha sonra çalışmanızı yeniden uygular, herhangi bir çatışmayı çözersiniz)
  • son birleştirme kesinlikle bir "hızlı ileri" olacaktır, çünkü ustanın tüm taahhüt geçmişine ve sadece yeniden uygulamak için değişikliklerinize sahip olacaktır.

Bu durumda doğru iş akışının (ortak dosya kümesindeki gelişmeler) önce rebase olduğunu, sonra birleştirileceğini onaylıyorum .

Bununla birlikte, yerel şubenizi (yedekleme nedeni ile) iterseniz, bu dalın başkası tarafından çekilmemesi (veya en azından kullanılmaması) anlamına gelir (çünkü taahhüt geçmişi ardışık yeniden taban tarafından yeniden yazılır).


Bu konuda (rebase sonra iş akışını birleştir), barraponto yorumlarda her ikisi de randyfay.com'dan iki ilginç yazıdan bahsediyor :

Bu tekniği kullanarak, çalışmanız her zaman güncel dal ile güncel bir yama gibi kamu dalının üstüne gider HEAD.

( pazar için benzer bir teknik mevcuttur )


27
Yeniden
baslamaya

2
randyfay.com/node/91 ve randyfay.com/node/89 harika okumalardır. bu makaleler bana iş akışımda neyin işe yaradığını ve ideal bir iş akışının ne olacağını anlamamı sağladı.
Capi Etheriel

sadece düz almak için, ana şubeden yerelinize yeniden baslamak temelde yerel herhangi bir birleştirmeden sonra ustanın bildiği herhangi bir geçmişi güncellemektir?
hellatan

@dtan burada anlattığım şey ustanın üstüne yerel basmaktır. Yerel geçmişi tam olarak güncellemiyor, yerel şubedeki herhangi bir çatışmayı çözmek için yerel geçmişi master'ın üstüne yeniden uyguluyorsunuz.
VonC

386

TL; DR

Git rebase iş akışı, sizi çatışma çözümlemesinde kötü olan kişilerden veya bir SVN iş akışına alışkın olan kişilerden korumaz, örneğin Git Disasters: A Gory Story . Sadece çatışma çözümünü onlar için daha sıkıcı hale getirir ve kötü çatışma çözümlemesinden kurtulmayı zorlaştırır. Bunun yerine, diff3'ü kullanın, böylece ilk etapta o kadar zor olmaz.


Rebase iş akışı çatışma çözümü için daha iyi değil!

Ben tarihi temizlemek için çok profesyonelim. Ancak bir çatışmaya girersem, hemen geri ödemeyi iptal eder ve bunun yerine birleştirme yaparım! İnsanların çatışma çözümü için birleştirme iş akışına daha iyi bir alternatif olarak bir rebase iş akışını önerdikleri beni gerçekten öldürüyor (bu da tam olarak bu sorunun neyle ilgiliydi).

Birleştirme sırasında "hepsi cehenneme" giderse, bir rebase sırasında "cehenneme" ve potansiyel olarak çok daha fazla cehenneme gider! İşte nedeni:

Sebep # 1: Her taahhüt için çatışmaları bir kez yerine bir kez çözün

Birleştirme yerine yeniden temellendirdiğinizde, aynı çatışma için yeniden temellendirmeyi taahhüt ettiğiniz kadar çok sayıda ihtilaf çözümü gerçekleştirmeniz gerekecek!

Gerçek senaryo

Bir dalda karmaşık bir yöntemi yeniden düzenlemek için ustadan ayrılıyorum. Yeniden düzenleme işim, yeniden düzenleme ve kod incelemeleri almak için çalışırken toplam 15 taahhütten oluşur. Yeniden düzenleme işlemimin bir kısmı, daha önce master'da bulunan karışık sekmeleri ve boşlukları düzeltmeyi içerir. Bu gereklidir, ancak maalesef bu yöntemde daha sonra yapılan herhangi bir değişiklikle çelişecektir. Tabii ki, bu yöntem üzerinde çalışırken, birisi ana dalda benim değişiklikleri ile birleştirilmesi gereken aynı yöntem basit, meşru bir değişiklik yapar.

Şubemi usta ile birleştirmenin zamanı geldiğinde, iki seçeneğim var:

git merge: Bir anlaşmazlık yaşıyorum. Uzmanlaşmak ve şubemle (nihai ürünü) birleştirmek için yaptıkları değişikliği görüyorum. Bitti.

git rebase: İlk taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. İkinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Üçüncü taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Dördüncü taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Beşinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Altıncı taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Yedinci ile çatışıyorumtaahhüt. Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Sekizinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Dokuzuncu taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Onuncu taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Onbirinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. On ikinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. On üçüncü taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum. On dördüncü çocuğumla bir çatışma yaşıyorumtaahhüt. Çatışmayı çözdüm ve geri dönmeye devam ediyorum. Onbeşinci taahhüdümle bir çatışma yaşıyorum . Çatışmayı çözdüm ve geri dönmeye devam ediyorum.

Tercih ettiğiniz iş akışı bu ise benimle dalga geçiyor olmalısınız . Tek gereken, master'da yapılan bir değişiklikle çatışan ve her taahhüt çakışacak ve çözülmesi gereken bir boşluk düzeltmesidir. Ve bu sadece bir boşluk çatışması olan basit bir senaryodur. Cennet, dosyalar arasında büyük kod değişikliklerini içeren gerçek bir çatışmanın olmasını ve bunu birden çok kez çözmenizi yasaklar .

Yapmanız gereken tüm ekstra uyuşmazlık çözümüyle, hata yapma olasılığınızı artırır . Ama geri alabileceğiniz için hatalar iyi gidiyor, değil mi? Tabii ki ...

Sebep # 2: Rebase ile geri alınamaz!

Sanırım hepimiz çatışma çözmenin zor olabileceği ve bazı insanların bu konuda çok kötü olduğu konusunda hemfikiriz. Hatalara çok yatkın olabilir, bu yüzden git geri almayı kolaylaştırır!

Bir dalı birleştirdiğinizde git, çakışma çözümlemesi kötüye giderse atılabilen veya değiştirilebilen bir birleştirme taahhüdü oluşturur. Kötü birleştirme taahhüdünü zaten kamu / yetkili repoya itmiş olsanız bile, birleştirmenin git revertgetirdiği değişiklikleri geri almak ve yeni bir birleştirme işleminde birleştirmeyi doğru bir şekilde yeniden yapmak için kullanabilirsiniz.

Bir şubeyi yeniden oluşturduğunuzda, çakışma çözümlemesinin yanlış yapılması durumunda, mahvoldunuz. Artık her taahhüt kötü birleşmeyi içeriyor ve sadece yeniden tabanını yeniden yapamazsınız *. En iyi ihtimalle, geri dönmeli ve etkilenen taahhütlerin her birini değiştirmelisiniz. Eğlenceli değil.

Bir tekrardan sonra, taahhütlerin neyin bir parçası olduğunu ve kötü çatışma çözümünün bir sonucu olarak neyin getirildiğini belirlemek imkansızdır.

* Git'in dahili günlüklerinden eski referansları kazabiliyorsanız veya yeniden bastırmadan önce son işleme işaret eden üçüncü bir şube oluşturursanız, bir geri ödemeyi geri almak mümkün olabilir.

Çatışma çözümünü cehennemden çıkarın: diff3 kullanın

Örneğin bu çatışmayı ele alalım:

<<<<<<< HEAD
TextMessage.send(:include_timestamp => true)
=======
EmailMessage.send(:include_timestamp => false)
>>>>>>> feature-branch

Çatışmaya bakıldığında, her bir dalın neyi değiştirdiğini veya amacının ne olduğunu söylemek mümkün değil. Bence çatışma çözümünün kafa karıştırıcı ve zor olmasının en büyük nedeni budur.

kurtarmaya diff3!

git config --global merge.conflictstyle diff3

Diff3'ü kullandığınızda, her yeni çakışma, birleştirilmiş ortak ata olan 3. bölüme sahip olacaktır.

<<<<<<< HEAD
TextMessage.send(:include_timestamp => true)
||||||| merged common ancestor
EmailMessage.send(:include_timestamp => true)
=======
EmailMessage.send(:include_timestamp => false)
>>>>>>> feature-branch

İlk önce birleştirilmiş ortak ataları inceleyin. Ardından her bir dalın niyetini belirlemek için her iki tarafı da karşılaştırın. HEAD'in EmailMessage'ı TextMessage olarak değiştirdiğini görebilirsiniz. Amacı, aynı parametreleri ileterek TextMessage için kullanılan sınıfı değiştirmektir. Feature-branch'un amacının, include_timestamp seçeneği için true yerine false iletmek olduğunu da görebilirsiniz. Bu değişiklikleri birleştirmek için her ikisinin de amacını birleştirin:

TextMessage.send(:include_timestamp => false)

Genel olarak:

  1. Ortak atayı her dalla karşılaştırın ve hangi dalın en basit değişikliğe sahip olduğunu belirleyin
  2. Bu basit değişikliği diğer dalın kod sürümüne uygulayın, böylece hem daha basit hem de daha karmaşık değişikliği içerir
  3. Değişiklikleri bir araya getirdiğiniz bölüm dışındaki tüm çakışma kodu bölümlerini kaldırın

Alternatif: Şubenin değişikliklerini manuel olarak uygulayarak çözün

Son olarak, bazı çatışmalar diff3 ile bile anlaşılması korkunçtur. Bu, özellikle diff'in anlamsal olarak yaygın olmayan ortak hatları bulması durumunda gerçekleşir (örn. Her iki dalın da aynı yerde boş bir çizgisi oldu!). Örneğin, bir dal, bir sınıfın gövdesinin girintisini değiştirir veya benzer yöntemleri yeniden sıralar. Bu gibi durumlarda, birleştirmenin her iki tarafından yapılan değişikliği incelemek ve diff'i diğer dosyaya el ile uygulamak daha iyi bir çözüm stratejisi olabilir.

Birleştirme nerede bir senaryoda bir çatışmayı çözmek nasıl en atalım origin/feature1nerede lib/message.rbçatışmaları.

  1. Şu anda kullanıma alınmış şubemizin ( HEADveya --ours) veya birleştirmekte olduğumuz şubenin ( origin/feature1veya --theirs) uygulanmasının daha basit bir değişiklik olup olmadığına karar verin . Diff ile üçlü nokta ( git diff a...b) kullanılması, a ve b'nin ortak atasından b ile bolan son sapmasından bu yana meydana gelen değişiklikleri gösterir a.

    git diff HEAD...origin/feature1 -- lib/message.rb # show the change in feature1
    git diff origin/feature1...HEAD -- lib/message.rb # show the change in our branch
    
  2. Dosyanın daha karmaşık sürümüne göz atın. Bu, tüm çakışma işaretlerini kaldıracak ve seçtiğiniz tarafı kullanacaktır.

    git checkout --ours -- lib/message.rb   # if our branch's change is more complicated
    git checkout --theirs -- lib/message.rb # if origin/feature1's change is more complicated
    
  3. Karmaşık değişiklik işaretlendiğinde, daha basit değişikliğin farkını yukarı çekin (bkz. Adım 1). Bu farktaki her değişikliği çakışan dosyaya uygulayın.


4
Tüm çatışmaları bir seferde birleştirmek, bireysel taahhütlerden daha iyi nasıl çalışır? Tek taahhütleri birleştirmekten zaten problemler alıyorum (özellikle taahhütleri mantıksal bölümlere ayırmayan ve doğrulama için yeterli testler sağlayan kişilerden). Ayrıca, yedekleme seçenekleri, etkileşimli rebase'in akıllı kullanımı ve tortoisegit gibi araçların (hangi seçeneklerin dahil edilmesine izin verir) dahil olduğu söz konusu olduğunda, rebase birleştirme işleminden daha kötü değildir.
prusswan

8
# 1'deki nedene değindiğimi hissediyorum. Bireysel taahhütler mantıksal olarak tutarlı değilse, mantıksal olarak tutarlı dalı birleştirmek için daha fazla sebep, böylece çatışmayı anlamlandırabilirsiniz. Taahhüt 1 buggy ise ve 2 taahhüdü bunu düzeltirse, taahhüt 1'i birleştirmek kafa karıştırıcı olacaktır. Yukarıda özetlediğim gibi, arka arkaya 15 çatışma yaşamanızın meşru nedenleri vardır. Ayrıca, rebase'in daha kötü olmama iddiası biraz asılsızdır. Rebase, kötü birleşmeleri orijinal iyi taahhütlerle karıştırır ve tekrar denemenize izin vermek için iyi taahhütleri bırakmaz. Birleştirme yapar.
Edward Anderson

6
Nilbus'a tamamen katılıyorum. Harika gönderi; bazı şeyleri temizler. Acaba rerere burada herhangi bir yardım olup olmadığını merak ediyorum. Ayrıca, diff3 kullanma önerisi için teşekkürler, kesinlikle şu anda bunu açacağım.
derick

45
Bana tek başına diff3'ü anlattığım için +1 - ortak ataların ne söylemek zorunda olduğunu bana söylemekten sorumlu olan kimin ne sıklıkta anlaşılmaz bir çatışmaya baktığını. Çok teşekkür ederim.
John

4
Bu kabul edilen cevap olmalıydı. Rebase iş akışı da korkunçtur, çünkü zaman zaman kod tabanında büyük bir sapma olduğu gerçeğini gizler, bu da baktığınız kodun nasıl yazıldığını anlamak isteyip istemediğinizi bilmek için yararlı olabilir. Sadece çatışmayan küçük dallar ustaya yeniden temellendirilmelidir.
Robert Rüger

32

İş akışımda olabildiğince yeniden temellendiriyorum (ve sık sık yapmaya çalışıyorum. Tutarsızlıkların birikmesine izin vermemek, dallar arasındaki çarpışmaların miktarını ve şiddetini önemli ölçüde azaltır).

Bununla birlikte, çoğunlukla rebase tabanlı bir iş akışında bile, birleşme yeri vardır.

Birleştirme işleminin aslında iki ebeveyni olan bir düğüm oluşturduğunu hatırlayın. Şimdi aşağıdaki durumu göz önünde bulundurun: A ve B olmak üzere iki bağımsız özellik branşım var ve şimdi A ve B incelenirken hem A hem de B'ye bağlı olan özellik dalı C üzerinde bir şeyler geliştirmek istiyorum.

Sonra ne yapacağım şudur:

  1. A'nın üstünde C dalını oluşturun (ve ödeme yapın).
  2. B ile birleştir

Şimdi C dalı hem A hem de B'den değişiklikler içeriyor ve ben de geliştirmeye devam edebilirim. A'da herhangi bir değişiklik yaparsam, dalların grafiğini aşağıdaki şekilde yeniden oluştururum:

  1. A'nın yeni tepesinde T dalı oluştur
  2. T'yi B ile birleştir
  3. C'yi T'ye rebase
  4. şube T'yi sil

Bu şekilde, aslında dalların keyfi grafiklerini koruyabilirim, ancak ebeveyn değiştiğinde yeniden temel alma yapmak için otomatik bir araç olmadığı göz önüne alındığında, yukarıda açıklanan durumdan daha karmaşık bir şey yapmak zaten çok karmaşıktır.


1
Sadece rebases ile aynı şeyi elde edebilirsiniz. Birleştirme aslında burada gerekli değildir (taahhütleri çoğaltmak istemiyorsanız hariç - ancak bunu bir argüman olarak görmüyorum).
odwl

1
Gerçekten de taahhütleri çoğaltmak istemiyorum. Çalışmamın uçuş içi yapısını olabildiğince temiz tutmak istiyorum. Ama bu kişisel bir zevk meselesi ve herkes için doğru değil.
Alex Gontmakher

% 100 ilk paragrafı kabul ediyorum. (@ Edward'ın cevabı bunun böyle olmadığı yerde çalışır, ancak dünyadaki tüm projelerin önerdiğiniz gibi çalışmasını tercih ederim). Cevabın geri kalanı, A ve B devam ederken C üzerinde çalışmanın zaten riskli (en azından gerçekten A ve B'ye bağlı olduğu ölçüde) riskli olduğu ve hatta sonunda muhtemelen (C en son & en büyük üstüne basmış olur) birleştirme tutmak olmaz.
Alois Mahdal

23

Git push origin --mirror HERHANGİ BİR DURUMA DAĞITMAYIN.

Bunu yapmak istediğinizden emin olup olmadığınızı sormaz ve emin olmalısınız, çünkü yerel kutunuzda olmayan tüm uzak dallarınızı siler.

http://twitter.com/dysinger/status/1273652486


6
Ya da sonucun ne olacağından emin olmadığınız şeyleri yapmıyor musunuz? Yönetici olarak kullandığım bir makinede Instructions to this machine may lead to unintended consequences, loss of work/data, or even death (at the hands of the sysad). Remember that you are solely responsible for the consequences of your actions MOTD vardı .
richo

aynalı bir repo varsa kullanın (her ne kadar benim durumumda şimdi özel bir kullanıcı tarafından sonradan alma kanca kaynak repo yürütülür)
prusswan

14

Açıklamanızı okuduktan sonra bir sorum var: Hiç yapmadınız mı?

git checkout master
git pull origin
git checkout my_new_feature

özellik dalınızda 'git rebase / merge master' yapmadan önce?

Çünkü senin usta şube arkadaşının deposundan otomatik olarak güncellenir olmayacaktır. Bunu ile yapmak zorundasın git pull origin. Yani, belki de hiç değişmeyen bir yerel ana daldan kaçarsınız? Ve sonra itme zamanı gel, hiç görmediğiniz (yerel) taahhütleri olan bir havuzu itiyorsunuz ve böylece itme başarısız oluyor.


13

Sizin durumunuzda, eşinizin doğru olduğunu düşünüyorum. Yeniden temellendirmenin güzel yanı, değişikliklerinizin tümünün temiz bir sırayla gerçekleşmiş gibi görünmesidir. Bunun anlamı

  • değişikliklerinizi incelemek çok kolay
  • güzel, küçük taahhütler yapmaya devam edebilirsiniz ve yine de bu taahhütlerin setlerini (ustalıkla birleşerek) aynı anda herkese açık hale getirebilirsiniz.
  • herkese açık ana dala baktığınızda, farklı geliştiriciler tarafından farklı özellikler için farklı taahhütler dizisi görürsünüz, ancak bunların hepsi karışmaz

Yine de özel geliştirme dalınızı yedekleme uğruna uzak depoya aktarmaya devam edebilirsiniz, ancak diğerleri yeniden baslayacağınız için bunu bir "genel" dal olarak değerlendirmemelidir. BTW, bunu yapmak için kolay bir komutgit push --mirror origin .

Git'i kullanan Paketleme yazılımı makalesi , birleştirme ve yeniden bastırmadaki değişimleri açıklayan oldukça iyi bir iş çıkarıyor. Biraz farklı bir bağlam ama müdürler aynı - temel olarak şubelerinizin kamuya açık mı yoksa özel mi olduğuna ve bunları ana hatta nasıl entegre etmeyi planladığınıza bağlı.


1
Git kullanan Paketleme yazılımı bağlantısı artık çalışmıyor. Orijinal yanıtı düzenlemek için iyi bir bağlantı bulamadım.
Chetan

Yansıtmamalısınız origin, üçüncü bir özel yedekleme havuzuna yansıtmalısınız.
Miral

12

Her neyse, yeni bir dalda iş akışımı takip ediyordum ve onu ustalıkla birleştirmeye çalıştığımda her şey cehenneme gitti. Fark etmemesi gereken şeylerle tonlarca çatışma vardı. Çatışmalar bana hiç mantıklı gelmedi. Her şeyi halletmek bir günümü aldı ve sonunda yerel ustamın tüm çatışmaları çözdüğü için uzak ustaya zorla iterek sonuçlandı, ancak uzak olan hala mutlu değildi.

Ne partnerinizin ne de önerilen iş akışlarınızda, mantıklı olmayan çatışmalarla karşılaşmamış olmalısınız. Sahip olsanız bile, önerilen iş akışlarını izliyorsanız, çözümlemeden sonra 'zorunlu' push gerekli değildir. Gerçekte itmekte olduğunuz dalı birleştirmediğinizi, ancak uzak ucun soyundan gelmeyen bir dalı itmeniz gerektiğini gösteriyor.

Bence olanlara dikkatlice bakmanız gerekiyor. Başka biri, uzak ana dalı yerel şubeyi oluşturma ile yerel şubeye yeniden birleştirmeye çalıştığınız nokta arasında (kasıtlı olarak ya da değil) geri alabilir mi?

Diğer birçok sürüm kontrol sistemi ile karşılaştırıldığında Git'i kullanmanın araçla daha az savaşmayı içerdiğini ve kaynak akışlarınız için temel olan sorunlar üzerinde çalışmanıza izin verdiğini keşfettim. Git sihir yapmaz, bu yüzden çelişen değişiklikler çatışmalara neden olur, ancak taahhüt ebeveynliğini izleyerek yazma işini kolaylaştırmalıdır.


OP'nin sürecinde keşfedilmemiş bir yeniden tabanı veya hatası olduğunu ima ediyorsunuz, değil mi?
krosenvold

8

"Sadece birkaç şubesi olan tek bir geliştirici olsanız bile, rebase kullanma ve düzgün bir şekilde birleştirme alışkanlığına sahip olmaya değer. Temel çalışma modeli şöyle görünecek:

  • Mevcut A dalından yeni B dalı oluşturun

  • B şubesine değişiklik ekleme / taahhüt etme

  • A dalından güncellemeleri geri al

  • B dalından A dalına değişiklikleri birleştirin "

https://www.atlassian.com/git/tutorials/merging-vs-rebasing/


7

Gözlemlediğim kadarıyla git merge, birleştirmeden sonra bile dalları ayrı tutma eğilimindeyken, rebase daha sonra birleştirmek tek bir dalda birleştirir. İkincisi çok daha temiz gelirken, birincisinde, birleştirme işleminden sonra bile hangi taahhütlerin hangi şubeye ait olduğunu bulmak daha kolay olacaktır.


4

Git ile “doğru” iş akışı yoktur. Teknenizde yüzen her şeyi kullanın. Bununla birlikte, şubeleri birleştirirken sürekli çatışmalar yaşıyorsanız, çabalarınızı geliştirici arkadaşlarınızla daha iyi koordine etmelisiniz? İkiniz aynı dosyaları düzenlemeye devam edersiniz. Ayrıca, boşluk ve yıkım anahtar kelimelerine (“$ Id $” ve diğerleri) dikkat edin.


0

Sadece rebase iş akışını kullanıyorum, çünkü görsel olarak daha net (sadece GitKraken'de değil, aynı zamanda Intellij ve in'de de gitk, ama en çok ilkini tavsiye ediyorum): bir dalınız var, master'dan geliyor ve master'a geri dönüyor . Diyagram temiz ve güzel olduğunda, hiçbir şeyin cehenneme gitmediğini bileceksiniz .

resim açıklamasını buraya girin

İş akışım sizinkinden neredeyse aynı, ancak yalnızca küçük bir farkla: squashŞubemden önce rebaseen son değişiklikler üzerine yerel şubemde bir tane taahhüt ederim master, çünkü:

rebaseher taahhüt temelinde çalışır

yani, aynı çizgiyi değiştiren 15 taahhüdünüz varsa master varsa, ezmiyorsanız 15 kez kontrol etmeniz gerekir, ancak nihai sonuç nedir, değil mi?

Yani, tüm iş akışı:

  1. masterEn son sürüme sahip olduğunuzdan emin olmak için ödeme yapın ve çekin

  2. Oradan yeni bir şube oluşturun

  3. Orada işinizi yapın, birkaç kez özgürce işleyebilir ve uzaktan kumandaya girebilirsiniz, endişelenmeyin, çünkü bu sizin dalınızdır.

  4. Birisi size "hey, PR / MR onaylandı, şimdi ustalaşmak için birleştirildi" diyorsa, onları alabilir / çekebilirsiniz. İstediğiniz zaman veya 6. adımda yapabilirsiniz.

  5. Tüm işinizi yaptıktan sonra, taahhüt edin ve birkaç taahhüdünüz varsa, bunları ezin (hepsi sizin işinizdir ve bir kod satırını kaç kez değiştirdiğiniz önemli değildir; tek önemli şey son sürümdür). İster itin ister itmeyin, önemli değil.

  6. Ödeme için master, pullyine en son sağlamak için masteryerel. Diyagramınız şuna benzer olmalıdır:

resim açıklamasını buraya girin

Gördüğünüz gibi master, master(hem yerel hem de uzaktaki) meslektaşınızın değişiklikleriyle ilerlerken, eski bir durumdan kaynaklanan yerel şubenizdesiniz.

  1. Çıkış şubenize geri dönün ve ustalaşmak için yeniden temellendirin. Artık sadece bir taahhüdünüz olacak, bu yüzden çatışmaları sadece bir kez çözeceksiniz master. sevmek:

resim açıklamasını buraya girin

  1. Şimdi, dalınızdaki değişikliklerle birlikte en son değişikliklere sahipsiniz master. Artık uzaktan kumandanıza itebilirsiniz ve daha önce ittiyseniz, zorla itmeniz gerekecektir; Git size hızlı ileriye gidemeyeceğinizi söyleyecektir. Bu normaldir, rebase nedeniyle şubenizin başlangıç ​​noktasını değiştirdiniz. Ama korkmamalısın: gücü akıllıca kullan . Sonunda, uzaktan kumanda da sizin dalınızdır, bu yüzden masteryanlış bir şey yapsanız bile etkilemezsiniz .

  2. PR / MR oluşturun ve onaylanana kadar bekleyin, böylece masterkatkınız olacaktır. Tebrikler! Böylece masterşemayı temizlemek için ödeme yapabilir , değişikliklerinizi çekebilir ve yerel şubenizi silebilirsiniz. Ana dalda birleştirdiğinizde bu yapılmazsa, uzak dal da silinmelidir.

Son diyagram temiz ve nettir:

resim açıklamasını buraya girin

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.