Git dalını master ile birleştirmenin en iyi (ve en güvenli) yolu nedir?


2103

'Dan yeni bir dal masteroluşturulur, biz buna diyoruz test.

masterBaşka şubeler vaat eden veya oluşturan ve daha sonra bir araya gelen birkaç geliştirici vardır master.

Diyelim ki çalışmalarımız testbirkaç gün testsürüyor ve içerideki taahhütlerle sürekli güncel kalmak istiyorsunuz master.

Ben yapacağını git pull origin masterdan test.

Soru 1: Bu doğru yaklaşım mı? Diğer geliştiriciler btw'de çalıştığım dosyalarla kolayca çalışabilirdi.


Çalışmam testbitti ve yeniden birleştirmeye hazırım master. İşte aklıma gelen iki yol:

A:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

Ben kullanmıyorum --rebaseçünkü anlayışımdan, rebase değişiklikleri alacak masterve benimkini istifleyecek, bu yüzden diğer insanların yaptığı değişikliklerin üzerine yazabilir.

Soru 2: Bu iki yöntemden hangisi doğrudur? Aradaki fark nedir?

Tüm testburadaki amaç, şubelerimi olan şeylerle güncel tutmak masterve daha sonra masterzaman çizelgesini olabildiğince doğrusal tutma umuduyla yeniden birleştirebilmem .


18
hayır .. rebase asla üzerine yazmaz, sadece daha temiz bir tarih elde etmeye çalışır. tarihin ustanın geç noktasına yeniden takılması (veya sahte)
Junchen Liu

7
rebase taahhütlerinizin üzerine yazmaz. Taahhütlerinizi geri alır, ana daldaki taahhütleri test şubenize uygular, sonra taahhütlerinizi tekrar teste uygular.
zundi

Yanıtlar:


2992

Bunu nasıl yaparım

git checkout master
git pull origin master
git merge test
git push origin master

Uzak bir şubeden yerel bir şubem varsa, uzaktan kumandayla bu şubeden başka şubeleri birleştirmek konusunda rahat hissetmiyorum. Ayrıca, itmek istediğim şeyden memnun olana kadar ve sadece kendim ve yerel depom için olan şeyleri hiç itmeyeceğimde değişikliklerimi zorlamam. Açıklamanızda öyle görünüyor ki, bu testsadece sizin için mi? Yani yayınlamak için bir sebep yok.

git her zaman sizinkilere ve diğer değişikliklere saygı duymaya çalışır ve öyle de olur --rebase. Bunu uygun bir şekilde açıklayabileceğimi sanmıyorum, bu yüzden Git kitabına bir göz atın - Rebasing veya git-ready: Küçük bir açıklama için yeniden temel almaya giriş . Oldukça havalı bir özellik


2
git merge testverir fatal: 'test' does not point to a commit. git logTest branşındaki taahhüt noktasını aramam, master branşa geri dönmem ve yapmam gerekiyor git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Duncanmoo

17
@Duncanmoo Tabii ki şube var testolmalı. Tabii, bunun yerine kesin karmayı kullanabilirsiniz, ancak şube adını kullanmak genellikle daha kolaydır. Dahili olarak sadece HEADdalın karmasını alır .
KingCrunch

44
@shanyangqu Uzaktan kumandadan en son değişiklikleri almak için. Yalnız ve sadece tek bir sistemle çalışıyorsanız sorun yoktur. Ancak, farklı bir sistemden (muhtemelen farklı bir geliştiriciden) itilen değişiklikler olduğunda, birleşmenizi geri itmeye çalıştığınızda (4. adım) bir çakışma görürsünüz. Şimdi tek çözüm, yerel ustanızı, oldukça çirkin "birleştirilmiş ustanın orijini / ustası" birleştirme taahhüdü ile sonuçlanan uzaktan kumanda ustasına birleştirmektir. Bu nedenle, birleşmeden önce bir çekim yapmak her zaman iyi bir fikirdir
KingCrunch

7
"Açıklamanızda öyle görünüyor ki, bu test sadece sizin için mi? Yayınlamak için bir neden yok." Örneğin, bu sunucu yerel sürücünüze karşı bir yedekleme sağlıyorsa veya yedekleme yapmak için başka bir yolunuz yoksa, yerel şubenizi bir sunucuya doğru itmek isteyebilirsiniz.
Eric

5
"... Ayrıca, itmek istediğim şeyden memnun olana kadar değişiklikleri de itmeyeceğim ..." Yerel makinelerinizin ölmesi ve günlerce çaba göstermesi durumunda neden kodunuzun yedeklenmesi için zorlamıyorsunuz? Gittiler?
Rich Stone

400

Bu çok pratik bir soru, ancak yukarıdaki tüm cevaplar pratik değil.

Sevmek

git checkout master
git pull origin master
git merge test
git push origin master

Bu yaklaşımın iki sorunu vardır :

  1. Güvensizdir, çünkü test dalı ile ana dal arasında herhangi bir çatışma olup olmadığını bilmiyoruz.

  2. Tüm test taahhütlerini master üzerinde bir birleştirme taahhüdüne "sıkıştırır"; yani ana dalda, test dalının tüm değişiklik günlüklerini göremeyiz.

Dolayısıyla, bazı çatışmalar olduğundan şüphelendiğimizde, aşağıdaki git işlemlerine sahip olabiliriz:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Testi mergeönce commit, hızlı ileri tarafından taahhüt bir kaçının --no-ff,

Çakışma ile karşılaşılırsa, git statusanlaşmazlıklar hakkındaki ayrıntıları kontrol edip çözmeye çalışabiliriz

git status

Çatışmaları çözdükten sonra veya bir çatışma yoksa, biz commitve pushonlar

git commit -m 'merge test branch'
git push

Ancak bu şekilde test dalında oturum açmış olan değişiklik geçmişi kaybedilecek ve ana dalın diğer geliştiricilerin projenin geçmişini anlamasını zorlaştıracaktır.

Bu yüzden en iyi yöntem rebaseyerine kullanmak zorundayız merge(varsayalım, bu zamanda şube çatışmalarını çözdüğümüzde).

Aşağıda basit bir örnek, gelişmiş işlemler için lütfen http://git-scm.com/book/en/v2/Git-Branching-Rebasing adresine bakın.

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Evet, sayacı tamamladığınızda, Test dalının tüm taahhütleri Ana dalın başına taşınacaktır. Yeniden temellendirmenin en büyük yararı, doğrusal ve çok daha temiz bir proje geçmişine sahip olmanızdır.

Kaçınmanız gereken tek şey şudur: Asla rebaseşube gibi, ana şube gibi kullanmayın .

Asla aşağıdaki gibi işlemler yapmayın :

git checkout master
git rebase -i test

Https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing için ayrıntılar

apandis:


4
Daha sonra master ile birleşmek için test dalını yeniden basmanın katılıyorum. Diğer cevaplar bile doğru, bu, yazım denetim sisteminin amacı olan "bir astar ve çok daha temiz bir proje elde edersiniz" ifadesi ile şube testindeki değişikliklerin geçmişini master başkanında tutacaktır.
le0diaz

16
"Bu bir güvenlik yolu değil, çünkü test dalı ile ana dal arasında herhangi bir çatışma olduğunu bilmiyoruz" ifadesi doğru değil: birleştirme her zaman iptal edilebilir. Çatışma olmasa bile, itilmediği sürece her zaman son yerel taahhüdü geri alabilirsiniz. Git'in doğru anlaşılması olmadan bazı şeyler biraz korkutucu veya belirsiz görünebilir, ancak "güvensiz" herhangi bir şekilde yanlıştır. Lütfen başkalarını yanlış bilgilerle karıştırmamaya dikkat edin.
Paul van Leeuwen

4
@PaulvanLeeuwen ile anlaşın, test dalını master ile birleştirdiğinizde , çatışmalar hakkında bilgilendirilirsiniz ve bu da değişiklikleri gireceğiniz ve birleştireceğiniz yerdir. İşiniz bittiğinde, birleştirmeyi taahhüt edip geri iteceksiniz. Pişmanlık duyarsanız veya doğru bir şekilde birleştirilemez gibi görünüyorsa, işinizi her zaman atabilir ve master'dan tekrar çekebilirsiniz. Bu yüzden kesinlikle güvensiz değil ..
Juan

3
neden rebase -i?
MushyPeas

8
Yeniden inşası, birleştirmeden doğal olarak daha güvensizdir. Yeniden birleştirmeyi birleştirme için daha güvenli bir seçenek olarak önermek yanlıştır. Yeniden pazarlama geçerli bir stratejidir, ancak kullanıcının dikkat etmesi gereken daha fazla uyarıyla birlikte gelir.
Ikke

90

Ne bir rebase ne de birleştirme kimsenin değişikliklerinin üzerine yazmamalıdır (bir anlaşmazlığı çözerken bunu yapmayı seçmediğiniz sürece).

Gelişirken olağan yaklaşım

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Efendi ile tekrar birleşmeye hazır olduğunuzda,

git checkout master
git log ..test # if you're curious
git merge test
git push

Birleşmede bir şey kırmaktan endişe ediyorsanız, sizin için git merge --abortoradadır.

Birleştirme aracı olarak itme ve çekme işlemlerini kullanmak saçmadır. Testi neden başlangıç ​​noktasına ittiğinizden de emin değilim.


1
Bu işlem taahhüt sayısını artıracaktır, şubeler arasında her geçiş yaptığınızda şubenizi taahhüt etmelisiniz.
iBug

2
Ne? Şubeleri her değiştirdiğinizde taahhüt sayısını artıracağını mı söylüyorsunuz? Yoksa şubeleri her değiştirdiğinizde "şubenizi taahhüt etmeniz" gerektiğini mi söylüyorsunuz? Birincisi doğru değil ve ikincisinin ne anlama geldiğinden emin değilim.
raylu

Ödeme yapmadan önce şubeyi taahhüt etmelisiniz. söylediğim şey bu
iBug

11
Yapmazsın: bu (şeylerden biri) git stashiçindir.
msanford

1
Veya son taahhüdünüzü (yerel şubede) değiştirebilir ve itmeden önce onu mükemmel hale getirebilirsiniz.
16:22

42

İlk olarak birleştirilecek şubeyi olabildiğince temiz yapardım. Testlerinizi yapın, durumun istediğiniz gibi olduğundan emin olun. Yeni taahhütleri git squash ile temizleyin .

KingCrunches cevabının yanı sıra ,

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Ana dalda yalnızca bir taahhüt olması gereken diğer dalda birçok taahhütte bulunmuş olabilirsiniz. Taahhüt geçmişini olabildiğince temiz tutmak için, test dalındaki tüm taahhütlerinizi ana daldaki tek bir taahhütte ezmek isteyebilirsiniz (ayrıca bkz: Git: Ezmek mi yoksa ezmek mi? ). Ardından, tamamlama mesajını çok etkileyici bir şeye yeniden yazabilirsiniz. Kodun içine girmeden okunması ve anlaşılması kolay bir şey.

edit: İlginizi çekebilir

GitHub'da bir özellik dalı için aşağıdakileri yapıyorum mybranch:

En yeni menşei öğrenin

$ git checkout master
$ git pull origin master

Birleştirme tabanı karmasını bulun:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Şimdi sadece ilki olduğundan emin olun pick, gerisi s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Sonra çok iyi bir taahhüt mesajı seçin ve GitHub'a basın. Çekme talebinde bulunun.

Çekme isteğinin birleştirilmesinden sonra, yerel olarak silebilirsiniz:

$ git branch -d mybranch

ve GitHub'da

$ git push origin :mybranch

ana dalda sadece bir taahhüt olmalı ”, ille de değil; wekk tarih tutmak istiyorum
Cocowalla

Elbette. Ama sonra sadece taahhütleri ezmeyin
Martin Thoma

Bence - ilk-ebeveyn en iyi çözüm gibi görünüyor. davidchudzicki.com/posts/first-parent
bkribbs

7

Eski iplik, ama bunu yapmanın yolunu bulamadım . Rebase ile çalışan ve tüm taahhütleri master'ın üstündeki bir (özellik) dalından birleştirmek isteyen biri için değerli olabilir. Yolda bir çakışma varsa, her taahhüt için bunları çözebilirsiniz. İşlem sırasında tam kontrol sahibi olursunuz ve istediğiniz zaman durdurabilirsiniz.

Master ve Branch'ı güncel tutun:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Şube Master'ın üzerine Birleştir:

git checkout <branch_name>
git rebase master

İsteğe bağlı: Rebase sırasında Çakışmalarla karşılaşırsanız:

İlk olarak, dosyadaki çakışmayı giderin. Sonra:

git add .
git rebase --continue

Yeniden temsilen Şubenizi itin:

git push origin <branch_name>

Şimdi iki seçeneğiniz var:

  • A) Bir PR oluşturun (örneğin GitHub'da) ve UI aracılığıyla orada birleştirin
  • B) Komut satırına geri dönün ve dalı master'a birleştirin
git checkout master
git merge --no-ff <branch_name>
git push origin master

Bitti.


6

Bu, ekiple işimde kullandığım iş akışı. Senaryo anlattığınız gibidir. İlk olarak, üzerinde testçalıştığımda, testşube üzerinde çalıştığım süre boyunca ustaya eklenenleri çekmek için usta ile yeniden temellendiriyorum.

git pull -r upstream master

Bu, testşubeyi çatalladığınızdan ve uyguladığınızdan sonra master'a yapılan değişiklikleri çekecek ve daha sonra yaptığınız değişiklikleri master'ın mevcut durumunu test etmek için uygulayacaktır. Diğer kişiler testte düzenlediğiniz dosyalarda değişiklik yaptıysa, burada çakışmalar olabilir. Varsa, bunları manuel olarak düzeltmeniz ve taahhüt etmeniz gerekir. Bunu yaptıktan sonra, ana şubeye geçmek ve testsorunsuz bir şekilde birleşmek iyi olacak .


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Birleştirdikten sonra, dosya değiştirilirse, birleştirdiğinizde "Çakışmayı Çöz" hatasıyla olur

Bu yüzden önce tüm çatışmalarınızı çözmeniz gerekiyor, sonra tüm değişikliklerinizi tekrar yapmanız ve ardından

git push origin master

Bu test dalında kim değişiklik yaptıysa daha iyi olur, çünkü hangi değişiklikleri yaptığını biliyordu.


3

Rebase yöntemini kullanırdım. Çoğunlukla durumunuzu anlamsal olarak mükemmel bir şekilde yansıttığı için, yani. yapmak istediğiniz şey, mevcut dalınızın durumunu yenilemek ve en son sürümü temel alıyormuş gibi "rol yapmak" tır.

Yani, kontrol etmeden bile master:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Tabii ki, sadece başlangıç ​​noktasından getirme, masterbirleştirme gerçekleştirmediği için yerel durumunuzu yenilemez , ancak amacımız için mükemmel bir şekilde tamamlanmıştır - zaman kazanmak uğruna geçiş yapmaktan kaçınmak istiyoruz.


2

@ KingCrunch'ın cevabı birçok durumda çalışmalıdır. Ortaya çıkabilecek bir sorun, en son testten çekilmesi gereken farklı bir makinede olabilirsiniz. Bu yüzden, önce testi çekmenizi tavsiye ederim. Düzeltme şöyle görünür:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

0

Çekme ustasıyla birleşmek anlamına geldiğinden, dalın çekilmesi için kontrol edilmesi gerekir ve birleştirmek için bir çalışma ağacına ihtiyacınız vardır.

git checkout master
git pull

Önce kontrol etmeye gerek yok; rebase iki argümanla doğru olanı yapar

git rebase master test  

git checkout master
git merge test

git push varsayılan olarak burada ve uzaktan kumandada bulunan tüm dalları iter

git push
git checkout test

0

Başlık "En iyi yol" dediği gibi, sabır birleştirme stratejisini düşünmek iyi bir fikirdir .

Gönderen: https://git-scm.com/docs/merge-strategies

Bu seçenekle, 'birleştirme özyinelemeli', önemsiz eşleştirme çizgileri (örneğin, farklı işlevlerden ayraçlar) nedeniyle oluşan yanlış anlamaları önlemek için biraz fazla zaman harcar. Birleştirilecek dallar çılgınca saptığında bunu kullanın. Ayrıca bakınız git-diff [1] - sabır.

Kullanımı:

git fetch
git merge -s recursive -X patience origin/master

Git Takma Adı

Bunun için her zaman bir takma ad kullanırım, örneğin bir kez çalıştır:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Şimdi şunları yapabilirsiniz:

git fetch
git pmerge origin/master

0

Bu GitLab'dan: Sadece talimatları izleyin:

resim açıklamasını buraya girin


0

Geliştirme ve özellik dallarına göre cevap vereceğim,

özellik dalındaysanız ve aşağıdaki komutları kullanarak geliştirmeniz gerekiyorsa: git checkout geliştir git git pull git checkout özelliği / xyz git merge develop

Artık özellikleriniz geliştirilerek değişikliklerinizi zorlayabilirsiniz.

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.