Git kuvvet üzerine yazma ile birleştirme


110

Dal demoile birleştirmem gereken bir şubem var master. İstenilen sonucu aşağıdaki komutlarla alabilirim:

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

Tek endişem, herhangi bir birleştirme sorunu varsa , bana birleştirme istemi vermeden daldaki gitdeğişikliklerin üzerine yazmamı söylemek istiyorum master. Dolayısıyla, temelde demodaldaki değişiklikler, masterdaldaki değişikliklerin üzerine otomatik olarak yazılmalıdır .

Etrafa baktım birden fazla seçenek var ama birleştirme konusunda risk almak istemiyorum.


git push -f origin master
MD XF

4
@MDXF: Yanılıyor olabilirim ama komutla değil, komutla -fseçeneği kullanmamalıyımmergepush
OpenStack

İkisini de deneyebilir ve sizin için neyin işe yaradığını görebilirsiniz
MD XF

Kuvvet üzerine yazma çözümü için aşağıdaki bağlantıya bakın: stackoverflow.com/a/42454737/984471
Manohar Reddy Poreddy

Yanıtlar:


114

Bu cevapla pek ilgili değil, ama git pullsadece git fetchonu takip eden hendek atardım git merge. Üç birleştirme yapıyorsunuz, bu da Git'inizin tek ihtiyacınız olan getirme olduğunda üç getirme işlemini çalıştırmasını sağlayacak. Dolayısıyla:

git fetch origin   # update all our origin/* remote-tracking branches

git checkout demo         # if needed -- your example assumes you're on it
git merge origin/demo     # if needed -- see below

git checkout master
git merge origin/master

git merge -X theirs demo   # but see below

git push origin master     # again, see below

En zorlu birleştirmeyi kontrol etme

Buradaki en ilginç kısım git merge -X theirs. Gibi root545 belirtildiği , -Xseçenekler birleştirme stratejiye geçti ve varsayılan hem edilir recursivestrateji ve alternatif resolvestrateji almak -X oursveya -X theirs(bir veya diğer, ancak ikisini). Ne yaptıklarını anlamak için Git'in çatışmaları nasıl bulduğunu ve ele aldığını bilmeniz gerekir .

Bir birleştirme çakışması bir dosya içinde oluşabilir 1 olduğunda taban hem sürüm farklıdır akım (aynı zamanda, yerel, KAFA veya adı --oursversiyonu) ve (aynı zamanda uzak veya adı verilen diğer --theirsaynı dosyanın) versiyonu. Yani, birleştirme üç revizyonu (üç taahhüt) belirlemiştir: temel, bizimki ve onlarınki. "Temel" sürüm, commit grafiğinde (bununla ilgili daha fazla bilgi için, diğer StackOverflow gönderilerine bakın) görüldüğü gibi commit ve commit arasındaki birleştirme tabanından gelir . Git daha sonra iki takım değişiklik buldu: "ne yaptık" ve "ne yaptılar". Bu değişiklikler (genel olarak) satır satır, tamamen metinsel olarak bulunur.temeli. Git, dosya içeriği konusunda gerçek bir anlayışa sahip değildir; sadece her metin satırını karşılaştırmaktır.

Bu değişiklikler git diffçıktıda gördüğünüz şeylerdir ve her zaman olduğu gibi bağlamları da vardır. Değiştirdiğimiz şeylerin, değiştirdikleri şeylerden farklı satırlarda olması mümkündür, bu nedenle değişiklikler çakışmayacakmış gibi görünür, ancak bağlam da değişmiştir (örneğin, değişikliğimizin dosyanın üstüne veya altına yakın olması nedeniyle, böylece dosya bizim sürümümüzde biter, ancak onların sürümünde, üste veya alta daha fazla metin eklediler).

Değişiklikler üzerinde olursa farklı hatlar -örneğin, biz değiştirmek coloriçin colour17. satırdaki ve değiştirmek frediçin barneyon line 71-o zaman hiçbir çatışma var: Git basitçe alır hem değişiklikleri. Değişiklikler aynı satırlarda meydana gelirse ancak aynı değişikliklerse Git, değişikliğin bir kopyasını alır . Yalnızca değişiklikler aynı satırlarda, ancak farklı değişikliklerse veya içeriğe müdahale eden özel bir durum söz konusuysa, bir değiştirme / değiştirme çakışması alırsınız.

-X oursVe -X theirsbizim veya onların: Seçenekler sadece iki değişikliklerden birini seçerek, bu çatışmayı nasıl çözüleceği Git söyle. Eğer birleşiyor söyledi yana demoiçine (onların) master(bizim) ve değişiklikleri istiyorum demo, istediğiniz olur -X theirs.

-XAncak körü körüne başvurmak tehlikelidir. Değişikliklerimizin satır bazında çelişmemesi, değişikliklerimizin aslında çatışmadığı anlamına gelmez! Klasik bir örnek, değişken bildirimli dillerde görülür. Temel sürüm kullanılmayan bir değişken bildirebilir:

int i;

Bizim versiyonunda, bir derleyici uyarı uzakta-ve go yapmak için kullanılmayan değişkeni silmek onların sürümü, kullandıkları bazı satır sonra bir döngü eklemek idöngü sayacı olarak. İki değişikliği birleştirirsek, ortaya çıkan kod artık derlenmez. -XSeçeneği değişiklikleri üzerinde olduğundan burada hiçbir yardım olduğunu farklı çizgileri .

Otomatik bir test paketiniz varsa, yapmanız gereken en önemli şey, birleştirmeden sonra testleri çalıştırmaktır. Bunu taahhüt ettikten sonra yapabilir ve gerekirse işleri daha sonra düzeltebilirsiniz; ya bunu yapabilirsiniz önce ekleyerek, işlediği --no-commitiçin git mergekomuta. Tüm bunların ayrıntılarını diğer ilanlara bırakacağız.


1 Ayrıca "dosya çapında" işlemlerle ilgili olarak da çelişkiler yaşayabilirsiniz, örneğin, belki bir dosyadaki bir kelimenin yazımını düzeltiriz (böylece bir değişikliğe sahip oluruz) ve tüm dosyayı siler (böylece bir sil). Git, -Xargümanlardan bağımsız olarak bu çatışmaları kendi başına çözmeyecektir .


Daha az birleştirme ve / veya daha akıllı birleştirme ve / veya yeniden ödeme kullanma

Her iki komut dizimizde de üç birleşme var. Birincisi origin/demo, yerel demoolana getirmektir (sizinki git pull, Git'iniz çok eskiyse, güncellenemeyecek origin/demoancak aynı sonucu üretecektir). İkincisi, origin/masteriçeri sokmaktır master.

Kimin güncellediği demove / veya bana göre net değil master. Kendi demoşubenize kendi kodunuzu yazarsanız ve diğerleri kod yazıp onu demoşubeye iterse origin, bu ilk adım birleştirmede çakışmalar olabilir veya gerçek bir birleştirme oluşturabilir. Çoğu zaman, işi birleştirmek için birleştirmek yerine yeniden taban kullanmak daha iyidir (kuşkusuz, bu bir zevk ve fikir meselesidir). Eğer öyleyse, git rebasebunun yerine kullanmak isteyebilirsiniz . Kendi kaydedilmesini hiçbirinde asla Öte yandan, demo, hatta yok gerek bir demodalı. Alternatif olarak, bunu otomatikleştirmek istiyorsanız, ancak hem sizin hem de başkalarının yaptığı taahhütler olduğunda dikkatlice kontrol edebiliyorsanız, kullanmak isteyebilirsiniz.git merge --ff-only origin/demo: Bu, mümkünse demogüncellenenle eşleştirmek için hızlı ileri origin/demosarar ve değilse, tamamen başarısız olur (bu noktada, iki değişiklik grubunu inceleyebilir ve uygun şekilde gerçek bir birleştirme veya yeniden ödeme seçebilirsiniz).

Bu, aynı mantık geçerlidir masterbirleştirme işlemini yapıyoruz rağmen üzerinde master kesinlikle bir ihtiyacın var, bu yüzden master. Bununla birlikte, hızlı ileri birleştirme olmayan birleştirme olarak yapılamazsa, birleştirmenin başarısız olmasını istemeniz daha olasıdır, bu nedenle bu muhtemelen de olmalıdır git merge --ff-only origin/master.

Diyelim ki asla kendi taahhütlerinizi yapmıyorsunuz demo. Bu durumda adı demotamamen terk edebiliriz :

git fetch origin   # update origin/*

git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"

git merge -X theirs origin/demo || die "complex merge conflict"

git push origin master

Eğer varsa vardır kendi yapıyor demoşube kaydedilmesini, bu yararlı değildir; Mevcut birleştirmeyi de koruyabilir (ancak belki --ff-onlyistediğiniz davranışa bağlı olarak ekleyebilirsiniz ) veya bir geri ödeme yapmaya geçebilirsiniz. Üç yöntemin de başarısız olabileceğini unutmayın: birleştirme bir çakışma ile başarısız olabilir, ile birleştirme --ff-onlyhızlı ileri gidemeyebilir ve yeniden ödeme bir çatışmayla başarısız olabilir (yeniden ödeme, özünde, birleştirmeyi kullanan kiraz toplama taahhütleri ile çalışır. makine ve dolayısıyla bir birleşme çatışması olabilir).


Bu, SO'daki herhangi bir şeyin en iyi açıklamalarından biridir . Özellikle, " -X oursvs." ile ilgili arıza ve örnek sorunu -X theirsfazlasıyla yardımcı oldu. Teşekkürler!
Jason R Stevens CFA

31

Değişikliklere / çakışmalara sahip herhangi bir dosyayı farklı bir dalla etkin bir şekilde değiştirmem gereken benzer bir sorun yaşadım.

Bulduğum çözüm kullanmaktı git merge -s ours branch.

Seçenek olduğunu -sve olmadığını unutmayın -X. üst düzey bir birleştirme stratejisi olarak -skullanımını belirtir, bu seçeneği birleştirme stratejisine uygulamaktır, bu durumda istediğim (veya bizim) bu değildir.ours-Xoursrecursive

Adımlar, oldbranchüzerine yazmak istediğiniz dal nerede newbranch.

  • git checkout newbranch tutmak istediğiniz şubeyi kontrol eder
  • git merge -s ours oldbranch eski şubede birleşir, ancak tüm dosyalarımızı saklar.
  • git checkout oldbranch üzerine yazmak istediğiniz dalı kontrol eder
  • get merge newbranch eski şubenin üzerine yazarak yeni şubede birleşir

Not: Buradaki diğer çözümlerden hiçbiri benim için işe yaramadı, bu yüzden cevabımı gönderiyorum.
Niall Mccormack

1
Benim için işe yaramadı. Çatışmayı çözdü (çakışan dosyaları çözdü) ancak dosya birleştirilmedi. Ve ikisi de birleştirilemez.
c-an

Herhangi biri "Lütfen bu birleştirmenin neden gerekli olduğunu açıklamak için bir işlem mesajı girin" uyarısı ile takılıp kalırsa: Mesajınızı girin, ardından klavyenizdeki ESC tuşuna basın, wq yazın ve komut isteminden çıkmak için ENTER tuşuna basın.
topherPedersen

Bu cevabı gönderdiğiniz için teşekkür ederim @NiallMccormack, bize çok yardımcı oldu!
Raphael_S

21

Bu birleştirme yaklaşımı, çatışmalardan veya diğer saçmalıklardan şikayet etmeden, masterher ne varsa içine yapıştırılan üzerine bir taahhüt ekleyecektir feature.

görüntü açıklamasını buraya girin

Bir şeye dokunmadan önce

git stash
git status # if anything shows up here, move it to your desktop

Şimdi usta hazırla

git checkout master
git pull # if there is a problem in this step, it is outside the scope of this answer

Get featuretüm giyinmiş

git checkout feature
git merge --strategy=ours master

Öldürmek için git

git checkout master
git merge --no-ff feature

1
git bitirmek için itin
Kochchy

git-scm.com/docs/git-merge#Documentation/git-merge.txt-ours. İşlemler net bir şekilde birleştirilmediğinde işe yaradı. Ancak bu yaklaşım her zaman işe yaramayacaktır Changes from the other tree that do not conflict with our side are reflected in the merge result. Şubemde üzerine yazılan temiz bir şekilde birleştirme taahhütlerim olduğu için bu benim için işe yaramadı. Başka bir yolu var mı?
NiharGht

11

Git birleştirmede "bizim" seçeneğini deneyebilirsiniz,

git birleştirme dalı -X bizimki

Bu seçenek, bizim sürümümüzü tercih ederek, çatışan hunks'ların otomatik olarak temiz bir şekilde çözülmesini zorlar. Bizim tarafımızla çelişmeyen diğer ağaçtaki değişiklikler birleştirme sonucuna yansıtılır. İkili bir dosya için tüm içerik bizim tarafımızdan alınır.


3
OP demo, birleşirken bile versiyonun tercih edilmesini istediğini söylediği için bu geriye doğru olacaktır master. Bir -X theirsde var, ancak OP'nin gerçekten istediği şeyin bu olduğu açık değil.
torek

Bütün yolu okumadın. Notunuz ours, -sseçenekle arka uçta kullanıldığında ne yapılacağını açıklar . Kullanırken oursile -X: Diğer ağaç, tarihimizi bildirerek içinde meydana gelen bütün olayların içeren vermedi herşeyi atar. kaynak
jimasun

2

-X theirsVe diğer ilgili komut anahtarlarını kullanmayı denediğimde birleştirme kaydı almaya devam ettim. Muhtemelen doğru anlamıyordum. Anlaşılması kolay bir alternatif, şubeyi silip tekrar takip etmektir.

git branch -D <branch-name>
git branch --track <branch-name> origin/<branch-name>

Bu tam olarak bir "birleştirme" değil, ama bu soruyla karşılaştığımda aradığım şey buydu. Benim durumumda, zorla itilen uzak bir daldan değişiklikleri almak istedim.


0

Bu komutlar, demoşube kodunun üzerine yazılmasına yardımcı olacaktır .master

git fetch --all

Şubenizi demoyerelden çekin

git pull origin demo

Şimdi masterşubeye gidin. Bu şube, demoşubedeki kod ile tamamen değiştirilecektir.

git checkout master

Dalda kalın masterve bu komutu çalıştırın.

git reset --hard origin/demo

reset mevcut şubeyi sıfırlayacağınız anlamına gelir

--hard herhangi bir birleştirme çakışması olmadan sıfırlanacağı anlamına gelen bir bayraktır

origin/demomevcut masterşubenin üzerine zorla yazacak kod olarak kabul edilecek şube olacaktır

Yukarıdaki komutun çıktısı size üzerinde son tamamlama mesaj gösterecektir origin/demoveya demoşube görüntü açıklamasını buraya girin

Ardından, sonunda, masterşubedeki kodu uzak deponuza itmeye zorlayın .

git push --force
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.