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.
rebase
anlayışla çok yardımcı oldu