Git-merge - kuru çalışma seçeneği var mı?


727

Çok fazla çatışmaya yol açabilecek uzak bir şubede birleşiyorum. Çatışmalar olup olmayacağını nasıl anlayabilirim?

Ben böyle bir şey görmüyorum --dry-runtarihinde adlı git-merge.


5
Git ile dallanma ucuz olduğundan, niçin bir kopyasını almıyorsunuz ve daha sonra kuru bir çalışma yapmanız gerekmiyor? Daha sonra kopyayı atabilirsiniz.
Alexander Mills

Yanıtlar:


813

Daha önce de belirtildiği gibi, --no-commitbayrağı geçirin, ancak hızlı bir taahhütten kaçınmak için, aşağıdakileri de yapın --no-ff:

$ git merge --no-commit --no-ff $BRANCH

Aşamalı değişiklikleri incelemek için:

$ git diff --cached

Ve hızlı ileri birleştirme olsa bile birleştirmeyi geri alabilirsiniz:

$ git merge --abort

51
Bu harika, ama yine de çalışan kopyanızı değiştirecek.
Reponuz

21
Çalışan kopyayı etkilemeden gerçekten birleştirme yapamazsınız.
mipadi

55
Doğru, ama bir şey gibi git merge --only-if-there-wont-be-any-conflictsya git diff --show-conflicts <commit>da gerçekten kullanışlı olurdu. Yazık ki henüz mümkün değil, yoksa bir şey mi kaçırıyorum?
dave1010

344
@ dave1010 Hiçbir zaman canlı bir web sunucusunda birleştirme işlemek gerekir !!! Geliştirme kutunuz bunun için! "Ürün" dalını düzeltin ve ardından gerçek web sunucusuna itin.
jpswain

52
Eğer canlı / prodüksiyon sunucusu üzerinde çalışıyorsanız hiçbir şey yapmak istemezsiniz git pull --ff-only!
ThiefMaster

237

Sadece otomatik olarak bir depo ile onun uzaktan kumandası arasındaki çakışmaları bulan bir yöntem uygulamak zorunda kaldım. Bu çözüm bellekteki birleştirmeyi yapar, böylece dizine veya çalışma ağacına dokunmaz. Bu sorunu çözmenin mümkün olan en güvenli yolu olduğunu düşünüyorum. Şöyle çalışır:

  1. Uzaktan kumandayı deponuza getirin. Örneğin: git fetch origin master
  2. Git merge-base komutunu çalıştırın: git merge-base FETCH_HEAD master
  3. Git merge-tree komutunu çalıştırın: git merge-tree mergebase master FETCH_HEAD( mergebase , birleştirme adımında önceki adımda yazdırılan onaltılık )

Şimdi uzak ustayı yerel ustanızla birleştirmek istediğinizi varsayalım, ancak herhangi bir dalı kullanabilirsiniz. git merge-treebellekte birleştirmeyi gerçekleştirir ve sonucu standart çıktıya yazdırır. Desen için Grep <<veya >>. Veya çıktıyı bir dosyaya yazdırabilir ve kontrol edebilirsiniz. 'Her ikisinde de değişti' ile başlayan bir çizgi bulursanız, büyük olasılıkla bir çatışma olacaktır.


41
Bu yanıt, hafife alınmış IMHO'dur, çünkü çalışan kopyaya veya dizine dokunmadan temiz bir çözümdür.
sschuberth

23
BTW, adım 2 ve 3, içeriğini yerinde değerlendiren Linux konsolunun backtick operatörü kullanılarak tek bir adımda birleştirilebilir:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g

15
.Gitconfig: [takma ad] 'a ekleyin: dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "# geliştiricinin master'a nasıl birleştirileceğini kontrol edin: git dry dev master
Noel

8
Yeni favorim GIT serisi: git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"Tek kelimeyle harika! +100
Rudie

4
Bunu test ederken, birleştirme çatışmasıyla sonuçlanmasalar bile, her iki dalın da aynı dosyayı değiştirdiği 'her iki dalda da değişti' bayrakları birleşmeleri için selamlamayı buldum. Sadece gerçek çatışmaları tanımlamak için şöyle başlayan çakışma işaretlemesi için grep'i gerekli buldum:, bu +<<<<<<< .ouryüzden şöyle bir grep ifadesi kullanıyorumgrep -q '^+<* \.our$'
Guy

55

Bu basit kaba kuvvet çözümüm:

  1. Bir "master öncesi" dal oluşturun (tabii ki master'dan)

  2. İstediğiniz her şeyi bu master öncesi ile birleştirin.
    Ardından, master'a dokunmadan birleştirmenin nasıl olduğunu görebilirsiniz.

    • Master öncesi master ile master'ı birleştir VEYA
    • Wannabe tarafından yayınlanan tüm şubeleri ustalıkla birleştirin

Her neyse, @ orange80'in tavsiyelerini takip ederim.


5
@Akostajti çözümünü seviyorum, ama bu henüz yetersiz kalan bir seçenek. Aslında savunmacı olmayı ve yeni bir geçici dal oluşturmayı tercih ediyorum (elbette sadece çatışma beklediğimde, aksi takdirde aşırıya kaçacak) ve bir şeyler ters giderse, basitçe silin.
jakub.g

1
bu "kirli" bir çözüm olup olmadığını bilmiyorum, ama gerçekten iş yapıyor. Bunu sevdim! (Y)
sara

3
Bu kabul edilen çözüm olmalı, imo. Hızlı, kolay, güvenli, geri dönüşümlü, sezgisel ve başlamadan önce değişmeden değişiklik olmadığı sürece, yan etkisi olmayacaktır.
Bob Ray

3
Bu çözüm git'in nasıl çalıştığını anlamadığınızı söyler. Dal sadece işaretçilerdir ve yalnızca gereksiz bir işaretçi oluşturursunuz. Şube birleştirmenize bir şekilde zarar verebileceğinize dair kötü bir his var ama yapamazsınız. Her zaman yapabileceği git merge --abortçatışması yoksa, git reset --hard HEAD~1veya birleştirme olsaydı git reset --hard origin/master. Başka bir şube oluşturmak size bir güvenlik hissi verir, ancak git'in nasıl çalıştığını öğrenirseniz, bunun yanlış yerleştirilmiş korku olduğunu anlayacaksınız. Endişe, çalışan kopyayı değiştirmemekle ilgili olduğunda, bu hiçbir çözüm sunmaz.
Thibault

@ thibault-d Temiz bir dalla başlamadığınızda çözümün ne kadar karmaşık olduğunu düşünün. git merge --no-commithızlı bir şekilde iletilebiliyorsa birleştirme işlemini iptal etmez. git merge --abortbirleştirilirse çalışmaz. Bunu bir komut dosyası olarak yazmak istiyorsanız, gariptir, çünkü git mergefarklı çakışma türlerini açıklamak için yeterince iyi hata kodlarıyla yanıt vermez. Yeni bir dalla çalışmak, bozuk bir komut dosyasının repo'nuzu el ile müdahale gerektiren bir durumda bırakmasını önler. Tabii ki hiçbir şey kaybedemezsiniz. Ancak başka türlü inşa etmek daha kolaydır.
Erik Aronesty

47

Git ile birleştirmeyi geri almak o kadar kolaydır ki kuru çalışma konusunda endişelenmemelisiniz:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

DÜZENLEME: Aşağıdaki yorumlarda belirtildiği gibi, çalışma dizininizde veya hazırlama alanınızda değişiklik varsa, muhtemelen yukarıdakileri yapmadan önce bunları saklamak isteyeceksiniz (aksi takdirde git resetyukarıdakileri takiben kaybolacaktır )


7
Bir birleştirme işleminin hızlı ilerletilip yönlendirilmeyeceğini kontrol etmek (FF), listeyi kontrol etmek git branch --contains HEADveya daha da doğrudan bir konudur , sadece kullanıngit merge --ff-only
Brian Phillips

7
git reset --hard, git'in sahip olduğu birkaç geri bilgisiz silme komutundan biridir, bu yüzden çok dikkatli kullanılmalıdır. Bu şekilde, -1
Kzqai

8
@Tchalvak hala reflog var.
Kissaki

3
--dry-run"bir birleştirme işleminin hızlı ilerlemesini isteyip istemediğini kontrol etmez". Bir birleştirme olacağını kesin çıktı dönecekti: dosyalar, çatışmalar vb. Ff olacak mı gerçekten ilginç değil, değil mi?
Rudie

3
nasıl git stash; git reset --hard? @BrianPhillips
Code Whisperer

41

Bunu yapmak için bir takma ad yaptım ve bir cazibe gibi çalışır, bunu yaparım:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

Şimdi sadece ararım

git mergetest <branchname>

Çatışma olup olmadığını öğrenmek için.


Parlak! Bunu saklıyorum.
qbert65536

28

Geçerli dalınızı uzak dala göre ayırın, bu bir çekme / birleştirme yaptığınızda neyin değişeceğini size söyleyecektir.

#see diff between current master and remote branch
git diff master origin/master

1
İlginç fikir. Bu çıktıya nasıl bakabilirim ve birleştirmenin işe yarayıp yaramayacağını nasıl belirleyebilirim?
MatrixFrog

6
Bu, herhangi bir çatışma olup olmayacağını söylemeyecektir ... ancak bir çekme / birleştirme yaptığınızda ne olacağına dair genel bir fikir verecektir.
timh

10
Bu sadece iki dal arasındaki farkı söyleyecektir, birleştirme sonucunun ne olacağını size söylemeyecektir. Bu önemli bir ayrımdır çünkü birleştirme bazı durumlarda otomatik olarak işlendikleri zamana bağlı olarak farklı dallardan değişiklik alacaktır. Bu nedenle, bir fark yaratmanız, bazı değişikliklerinizin gerçekte geri alınacağını düşünmenizi sağlayabilir, birleştirme işlemi otomatik olarak eski değişikliklere göre daha yeni değişiklikler alacaktır. Umarım mantıklıdır.
markquezada

3
@ Mirthlab'ın yorumuna dayanmak için, daha önce "bizimki" birleştirme stratejisi (veya başka bir manuel birleştirme düzeltmeleri) ile birleştirme yaptığında fark ve birleştirme arasında önemli bir fark olacaktır; fark, zaten "birleştirilmiş" olarak sayılan farkları da gösterir.
Tao

22

Bunu yapmak için request-pull git komutunu kullanıyorum. Yerel veya uzak depolarınızda hiçbir şey yapmadan birleştirme sırasında gerçekleşecek her değişikliği görmenizi sağlar .

Örneğin, "özellik-x" adlı bir dalı ana dalınızla birleştirmek istediğinizi düşünün

git request-pull master origin feature-x

size ne olacağının bir özetini gösterecektir (hiçbir şey yapmadan):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

-pParametreyi eklerseniz, tam yama metnini de alırsınız, tıpkı değiştirilen her dosyaya git farkını yaptığınız gibi.


3
Komut satırı seçeneklerine ne masterve ne ekleyerek originbunu biraz daha açık hale getirebilirsiniz ve örneğin bir yerelde olduğum branch1ve request-pullyerel bir özellik dalında bir yapmak istiyorsam ne olacak branch2? Hala ihtiyacım var originmı? Tabii ki, her zaman belgeleri okuyabilirsiniz.
Ela782

Ne yazık ki bu komut sadece Rev # 2 bir dal adı ise işe yarar, hashes için çalışmaz: /
Jared Grubb

20

Henüz kimsenin yama kullanmasını önermediğine şaşırdım.

Eğer bir birleştirme test etmek isterim Say your_branchiçine master(Ben varsayarak yaşıyorum masterteslim):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

Hile yapmalı.

Gibi hatalar alırsanız

error: patch failed: test.txt:1
error: test.txt: patch does not apply

bu, yamanın başarılı olmadığı ve birleşmenin çatışmalara yol açacağı anlamına gelir. Çıktı yok, yamanın temiz olduğu ve dalı kolayca birleştirebileceğiniz anlamına gelir


Not Bu edeceğini değil aslında (tabii yama dosyası oluşturma kenara ama güvenle sonradan o silebilirsiniz) sizin çalışma ağacı değiştirin. Git-Apply belgelerinden:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

Git ile benden daha akıllı / daha deneyimli olan herkese dikkat edin: Lütfen burada yanlış olup olmadığımı bana bildirin ve bu yöntem normal bir birleşmeden farklı davranışlar gösteriyor. 8 yıldan fazla bir süredir bu sorunun kimsenin bulunmadığı garip görünen bu çözümü önermeyecektir.


Bu yöntem bu soru için kabul edilen yanıttır ve yorumlarda "git 'özyinelemeli' birleştirme stratejisini kullanamadı" ve "yama dosyası yeni dosyalar için hata veriyor" gibi bazı uyarılar vardır. Aksi halde harika görünüyor.
neno

1
Geçici yama dosyası oluşturmadan Daha kısa yol: git diff master your_branch | git apply --check.
ks1322

9

Bu ilginç olabilir: Belgelerden:

Karmaşık çakışmalarla sonuçlanan ve yeniden başlamak istiyorsanız, git merge --abort ile kurtarabilirsiniz .

Ama bunu naif (ama yavaş) bir şekilde de yapabilirsiniz:

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(Not: Taahhüt edilmeyen değişikliklerin çakışmayacağından emin olmak için / tmp'ye klonlama işe yaramaz, bir kopyasına ihtiyacınız olacaktır).


2
Tek ihtiyacınız olan bir çekiçse ... :) +1
kaiser

Temiz kopya ile elde edilebilir cp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(iyi ölçmek için), git status(temiz olduğunu kontrol etmek için).
ADTC

8

Bunun eski bir soru olduğunun farkındayım, ancak bir Google aramasında ilk ortaya çıkan soru.

Git birleştirilirken yalnızca --ff seçeneği kullandı.

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


--ff okunur

Geçerli HEAD zaten güncel değilse veya birleştirme bir hızlı ileri sarma olarak çözülmedikçe birleştirme ve sıfır dışında bir durumla çıkmayı reddetme.

Bunu yapmak birleştirmeyi ve hızlı ileri sarmayı dener ve eğer yapamazsa hızlı ileri alma işleminin gerçekleştirilemeyeceğini, ancak çalışma dalınızı dokunmadan bırakmanızı ister. Hızlı ileri alabilirse, çalışma dalınızda birleştirme gerçekleştirir. Bu seçenek ayrıca mevcuttur git pull. Böylece, aşağıdakileri yapabilirsiniz:

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
Bu, orijinal soruda istediğim şey değil, hızlı ileri ile yapılabiliyorsa birleştirmeyi yapacak. Kabul edilen cevabın bunu düzelten diğer yarısı olduğunu düşünüyorum.
Otto

Gerçekten de, fantezi git istemleri bu tür bir şey için ihtiyacım ortadan kaldırır.
Otto

2
Gerçekten aynı değil. Hızlı ileri sarma nedeniyle birleştirme çözümlenemediğinden sıfır olmayan bir durumdan çıkmak , çakışma olduğu anlamına gelmez . Bu sadece tarihin ayrıştığı ve birleştirme taahhüdünün gerekli olduğu anlamına gelir.
ADTC

7

Ana daldan bir özellik dalında nelerin değiştiğini görmek için git günlüğünü kullanıyorum

git log does_this_branch..contain_this_branch_changes

ör. - master ile birleştirilen / birleştirilmeyen bir özellik dalında hangi taahhütlerin olduğunu görmek için:

git log master..feature_branch

3

B'den A'ya hızlı ileri sarmak istiyorsanız, git log B'nin size hiçbir şey göstermediğinden emin olmalısınız, yani A'nın B'de olmayan bir şeyi yoktur. Ancak B..A'da bir şey olsa bile, yine de çatışmalar olmadan birleşebilirsiniz, bu nedenle yukarıdakiler iki şeyi gösterir: bir hızlı ileri olacak ve böylece bir çatışma yaşamayacaksınız.


2

Benim çözümüm geriye doğru birleşmek.

Şubenizi uzak "hedef" şubeye birleştirmek yerine, şubeyi kendinize birleştirin.

git checkout my-branch
git merge origin/target-branch

Herhangi bir çatışma olup olmadığını göreceksiniz ve bunları nasıl çözeceğinizi planlayabilirsiniz.

Bundan sonra birleştirme git üzerinden iptal edilebilir merge --abortveya (herhangi bir çakışma ve birleşme olmadıysa) üzerinden önceki taahhüdüne geri dönebilirsiniz.git reset --hard HEAD~1


-2

Çalışan kopyanızın geçici bir kopyasını oluşturun, daha sonra bu kopyayla birleştirin ve ikisini birbirinden ayırın.

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.