Git çekme, kaydetme günlüğünde gereksiz "Dalları birleştir" mesajlarına neden oluyor


110

Bir proje üzerinde başka bir geliştiriciyle çalışıyorum ve Github'u uzak depomuz olarak kullanıyoruz. Git 1.7.7.3 kullanan bir Mac'teyim, Windows'ta git 1.7.6 kullanıyor.

Olan bu

  1. Birimiz (ona geliştirici A diyelim, ancak hangisinin olduğu önemli değil) GitHub'a bir dizi taahhüt gönderiyor.
  2. Diğeri (geliştirici B) bazı yerel taahhütler yapar.
  3. B, a yapar git pull.
  4. B, a yapar git push.
  5. Kaydetme geçmişi günlüğüne baktığımda, github.com:foo/bar'ın Merge branch 'master'ını görüyorum

Kaydetme günlüğü zamanla "Dalları birleştir" mesajlarıyla doludur ve ayrıca geliştirici B'nin geliştirici A'nın yaptığı değişiklikleri gerçekleştirdiğini gösterir. Bu sorunu önlemenin tek yolu git pull --rebase3. adımda a yapmaktı , ancak yeniden düzenlemenin hangi yan etkilere yol açacağını bilmiyorum. İlk kez çok geliştiricili bir git deposu üzerinde çalışıyorum, bu yüzden bu normal bir davranış mı? Bu sorunun nasıl çözüleceğine dair herhangi bir fikriniz var mı?


2
Günlüğü git log --no-merges
şununla

Yanıtlar:


88

Gördüğünüz taahhüt tamamen iyi. pullEtkili bir şekilde çalışır git fetchve ardından git mergekoştuğunuzda genellikle bir birleştirme gerçekleşir git pull.

Birleştirme yerine yeniden oluşturmanın alternatifi mümkündür, ancak genellikle bundan kaçınmalısınız. Yeniden oluşturma, doğrusal bir geçmiş tutmanıza izin verir, ancak aynı zamanda başlangıçta meydana gelen dallanma hakkındaki tüm bilgileri kaldırır. Ayrıca, geçerli dalın geçmişinin yeniden yazılmasına, hedef dalda bulunmayan tüm işlemlerin (sizin durumunuzda, uzaktaki) yeniden oluşturulmasına neden olacaktır. Yeniden oluşturulan taahhütler farklı taahhütler olduğundan, bu, başkalarıyla birlikte geliştirirken çok fazla kafa karışıklığına neden olabilir, özellikle insanlar yeniden yazılmadan önce bu taahhütlerin bazı kısımlarını kontrol ettiklerinde (örneğin, özellik dalları ile). Bu nedenle, genel bir kural olarak , zaten itilmiş olan hiçbir işlemi asla yeniden yazmamalısınız.

Gördüğünüz taahhütler iki (veya daha fazla) şubeyi birleştirmek için oradadır. Birden fazla şubeyi birleştirdikten sonra başka hiçbir şey yapmayan bir işleme sahip olmak tamamen iyidir. Aslında, geçmişe bakarken dalları birleştiren bir birleştirme taahhüdünüz olduğunda bunu çok netleştiriyor. Yeniden satışa kıyasla, birleştirme aynı zamanda , bir arada bulunan gerçek şubeler de dahil olmak üzere orijinal geçmişi geliştirildiği şekliyle etkili bir şekilde görmenize olanak tanır .

Yani, uzun lafın kısası: Evet, birleştirme taahhütlerine sahip olmak tamamen iyidir ve bunlar için endişelenmemelisiniz.


2
Çok güzel cevap. Bazı açık kaynak projeleri katkı kılavuzlarında önerildiği için yeniden ödeme stilini kendim denedim ve sorunlara neden oldu. Takımdaki yeni bir üye de aynısına sahipti. Geri ödeme seçeneğinin tüm gün birlikte çalışan ekipler için olmadığını düşünüyorum, ancak ana katkıda bulunanlar ve yalnızca yama gönderen diğer katkıda bulunan projeler için doğru. Bunlar, ana depoyu iyi getirmeli ve bir çekme talebinde bulunmadan hemen önce değişikliklerini yeniden düzenlemelidir.
Meligy

2
@sTodorov Yeni değişiklik yoksa, çekmenin getirme kısmı hiçbir şey yapmaz, ancak birleştirme hala yürütülmektedir. Dolayısıyla, mevcut yerel şubeniz güncel değilse, yeni değişiklikleri şubenizle birleştirecektir. Ve hızlı ileri birleştirme yapamazsa (farklı kaydetmeleriniz varsa), o zaman bir birleştirme kaydı oluşturur.
dürtmek

28
Bu cevap, OP'nin açıkladığı gibi yeniden taban kullanmanın tehlikeli olduğunu gösteriyor, ancak öyle değil. 3. adımda yeniden başlatmak, tüm geçmişi yeniden yazmaz. Yalnızca aktarılmamış yerel taahhütler, yeni HEAD'in (o şubeye gönderilen en son kayıt) üzerine yeniden uygulanarak yeniden yazılır. Bu, gereksiz birleştirme işlemlerini önler ve başka hiçbir yan etkisi yoktur.
bob esponja

1
@bobesponja Çekilmiş uzak dalda olmayan tüm kayıtlar yeniden yazılır. Bu, diğer şubelerden, örneğin diğerlerinin daha önce erişmiş olabileceği özellikli şubelerden yayınlanmış taahhütleri içerebilir. Bu nedenle, evet, neyi yeniden ürettiğinizi düşünmeden yeniden satış yapmak biraz tehlikelidir.
dürtmek

1
@bobesponja Evet, eğer özellik şubenizi erken yayınlıyorsanız (çünkü diğerleri üzerinde çalışıyor veya sadece yedek olarak), o zaman onu yeniden başlatmamalısınız çünkü diğerleri zaten almış olabilir. O halde yeniden satış - sizin de söylediğiniz gibi - cevabımda belirttiğim yeniden finansman kurallarına aykırıdır. Ancak, taahhütlerinizi yayınlamazsanız, eğer isterseniz ve doğrusal geçmişe aldırış etmiyorsanız, yeniden ödeme yapmak iyidir. Ancak bu, nasıl çalıştığınıza bağlıdır, bu yüzden genel cevap, gerçekten güvenli olmadığı sürece bundan kaçınmaktır. Btw. Cevabımı gözden geçirdim, bu yüzden sorun çözülürse, olumsuz oyunuzu kaldırırsanız çok memnun olurum.
dürtmek

48

Anladığım kadarıyla, diyagramlar ve sonuçlar yanlış olduğu için bu cevap revize edildi.


git pullgit birleştiği için birleştirme işlemlerine neden olur. Bu, şubelerinizi birleştirme yerine yeniden taban kullanacak şekilde ayarlayarak değiştirilebilir. Bir çekmede birleştirme yerine yeniden taban kullanmak, paylaşılan havuza daha doğrusal bir geçmiş sağlar. Öte yandan, birleştirme taahhütleri şubedeki paralel gelişim çabalarını göstermektedir.

Örneğin aynı şubede iki kişi çalışıyor. Şube şu şekilde başlar:

...->C1

Birinci kişi işini bitirir ve şubeye iter:

...->C1->C2

İkinci kişi işini bitirir ve zorlamak ister, ancak güncelleme yapmaları gerektiği için yapamaz. İkinci kişi için yerel veri havuzu şöyle görünür:

...->C1->C3

Çekme birleştirilecek şekilde ayarlanmışsa, ikinci kişilerin deposu gibi görünecektir.

...->C1->C3->M1
      \      /
       ->C2->

M1 bir birleştirme taahhüdüdür. Bu yeni şube geçmişi depoya aktarılacaktır. Bunun yerine, çekme yerel repo şöyle görünecektir:

...->C1->C2->C3

Birleştirme taahhüdü yoktur. Tarih daha doğrusal hale getirildi.

Her iki seçenek de şubenin tarihini yansıtır. git, hangi geçmişi tercih ettiğinizi seçmenize izin verir.

Rebase'in uzak şubelerde soruna neden olabileceği yerler var. Bu, o davalardan biri değil. Zaten karmaşık olan bir şube geçmişini basitleştirdiği ve paylaşılan depoya göre geçmişin bir sürümünü gösterdiği için yeniden taban kullanmayı tercih ediyoruz.

Branch.autosetuprebase = her zaman git'in uzak şubelerinizi ana yerine yeniden temel olarak otomatik olarak kurmasını sağlayabilirsiniz.

git config --global branch.autosetuprebase always

Bu ayar git'in her uzak dal için otomatik olarak bir yapılandırma ayarı oluşturmasına neden olur:

branch.<branchname>.rebase=true

Bunu, zaten kurulmuş olan uzak şubeleriniz için kendiniz ayarlayabilirsiniz.

git config branch.<branchname>.rebase true

@LaurensHolst'a önceki ifadelerimi sorgulayıp takip ettiği için teşekkür ederim. Git'in çekme ve birleştirme işlemleriyle nasıl çalıştığı hakkında kesinlikle daha fazla şey öğrendim.

Birleştirme taahhütleri hakkında daha fazla bilgi için , ProGit-Book'ta Bir Projeye Katkıda Bulunma bölümünü okuyabilirsiniz . Özel Küçük Takım bölüm gösterileri kaydedilmesini birleştirme.


7
"Bir çekmede birleştirme yerine yeniden taban kullanmak, paylaşılan havuza doğru geçmişi sağlar. Birleştirme kullanmak yanlış bir geçmiş sağlar. " - Bu oldukça cesur ifadeyi destekleyen mantık nedir? Birleşmeleri olan bir tarihin 'yanlış tarih' olmasına imkan yoktur. Olayların gerçekleştiği sıranın doğru bir tasviridir. Yeniden sıralayarak yaptığınız şey aslında geçmişi değiştirerek biraz daha doğrusal bir versiyonunu yaratmaktır. Estetik için doğruluktan ödün veriyorsunuz. Belki yapmayı tercih ettiğiniz bir şey, ama hiçbir şekilde daha doğru değil.
Laurens Holst

2
Birleştirme yerine yeniden taban kullanmak, estetik için doğruluktan ödün vermez. Birleşmeler için --no-ff kullanıyoruz, bu nedenle estetik bir gereklilik değil. Doğruluk bir arzudur. Rebase bu doğruluğu sağlar.
Bill Door

2
Yeniden hesaplanan geçmiş nasıl daha doğrudur? Bunu açıklığa kavuşturmuyorsun ve nasıl olacağını anlamıyorum.
Laurens Holst

1
Tarih, paylaşılan depoda işlemlerin gerçekleştiği zamanın bir yansımasıdır . Birinci gün, paylaşılan depo C2'yi gerçekleştirdi. 2. günde, paylaşılan depo C3 işlemini görür. C3, C2'den önce gelirse, zamanın yansıması doğru olmaz. C3, C2'den önce gelmedi. Bu yeniden temelin yaptığı tek şey , paylaşılan havuz tarafından gösterilen geçmişi doğru şekilde yansıtmak için yerel depodaki taahhütleri yeniden düzenlemektir .
Bill Door

6
Sorularınız, birleştirme taahhütleri konusundaki anlayışımı gözden geçirmeme neden oldu. Diyagramım yanlış. Tartışmayı gözden geçiriyorum. Vardığım sonuçlar da yanlış. Yeniden yapılandırma ve birleştirme geçmişi eşit derecede doğrudur. Kendi seçiminizi yapabilirsiniz.
Bill Door

11

Yapabilirsin:

git pull --rebase

Ancak, bu her zaman değişikliklerinizi ortak çalışanlarınızın üzerine koyacaktır. Ancak herhangi bir kirletici birleştirme mesajı almayacaksınız.


9

Aslında buna çok daha basit bir cevap var. Sadece geliştirici B'nin taahhüdünü vermeden ÖNCE çekmesini sağlayın. Bu, yerel deponuzda oluşturduğunuz geçmişin, uzak depodaki taahhütlerin geçmişi ile birleşmeye çalışan yerel taahhüdünüzden kaynaklandığından, bu birleştirme işlemlerini önleyecektir. Çekme yaparken 'değişikliklerin üzerine yazılacak' satırları boyunca bir şey söyleyen bir mesaj alırsanız, bu sadece ikinizin de aynı dosyaya dokunduğu anlamına gelir, öyleyse yapın:

git stash
git pull
git stash pop

o zaman varsa herhangi bir birleştirme çakışmasını çözebilirsiniz.


Çoğu sinir bozucu ve endişeli, tam olarak birleşik çatışmalardır. Bundan kaçınmayı tercih ederim
Green

1
@Green Birleştirme çatışmalarından endişeleniyorsanız, git pull bile farklı değil.
Zoso

Bu bir sefer sen unuttuğunuzda stashsenden önce pull. Ugh git, her zaman oyunumun zirvesinde olmamı gerektiriyor.
linuxNoob

git pull --rebaseUzak değişiklikleri yerel olanlardan önce entegre etmeniz gerekir.
vonbrand

7

Git çekme yapmak "Dalları birleştir" mesajlarını ekleyecektir, sadece yaptığı şey budur. Git çekme yaparak, uzak dalı yerel şubenizle birleştirmiş olursunuz.

Bir git çekme işlemi yaptığınızda ve çakışma olduğunda, git günlüğü çakışan dosyalara yapılan güncellemeleri, çakışmaları çözen kullanıcıdan geliyormuş gibi gösterecektir. Bunun, çatışmayı düzelten kişinin dosyayı yeniden işlediğini varsayıyorum.

Bildiğim kadarıyla git bu şekilde çalışıyor ve bunun etrafından dolaşmanın bir yolu yok.

Yeniden yapmak git geçmişini yok edecek, böylece birleşmelerin ne zaman gerçekleştiğini göremeyeceksiniz.

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.