Git birleştirme çakışmasını çözmek için vimdiff'i nasıl kullanabilirim?


159

Sadece GIT'de efendime içine bir dal birleşti ve ben aldım Automatic merge failed; fix conflicts and then commit the result.Şimdi ran git mergetoolve vimdiff aşağıdaki resimde açıldı. Vimdiff'i nasıl kullanacağımı bilmiyorum. Buradaki her panel ne anlama geliyor ve birleştirme çakışmasını nasıl düzeltmem gerekiyor?

resim açıklamasını buraya girin


3
Bu sayfaya bakınız . "Doğru" ile kastettiğin buysa, kodunuzun geçerli durumu sol üsttedir.
romainl

@romainl Bunu okuduktan sonra hala kafam karıştı, kısayollar nelerdir ve ana şube olarak kullanılacak dosyayı nasıl seçerim?
Cool Guy Yo


Ayrıca bakınız: this
skelliam 21:16

Yanıtlar:


142

Dört arabellek de aynı dosyanın farklı bir görünümünü sağlar. Sol üst arabellek (LOCAL), dosyanın hedef dalınıza nasıl baktığıdır (birleştirdiğiniz şey). Sağ üst arabellek (UZAKTAN), dosyanın kaynak dalınıza (birleştirme yaptığınız yer) nasıl baktığıdır. Orta tampon (BASE), ikisinin ortak atasıdır (böylece sol ve sağ sürümlerin birbirinden nasıl ayrıldığını karşılaştırabilirsiniz).

Aşağıdaki noktada yanılmış olabilirim. Birleştirme çakışmasının kaynağı, her iki dosyanın da BASE'ten beri dosyanın aynı bölümünü değiştirmiş olduğunu düşünüyorum; LOCAL, tırnak işaretlerini çiftten teke değiştirdi ve REMOTE aynı değişikliği yaptı, ancak arka plan değerini bir renkten bir URL'ye değiştirdi. (Birleşmenin LOCAL'daki tüm değişikliklerin UZAKTAN da bulunduğunu fark edecek kadar akıllı olmadığını düşünüyorum; LOCAL'in UZAKTAN ile aynı yerlerde BASE'ten bu yana değişiklik yaptığını biliyor).

Her durumda, alt arabellek aslında düzenleyebileceğiniz dosyayı (çalışma dizininizde oturan dosyayı) içerir. İstediğiniz değişiklikleri yapabilirsiniz; vimotomatik birleştirmenin işleyemediği alanlar olan üst görünümlerin her birinden nasıl farklı olduğunu gösteriyor. UZAKTAN değişikliklerin yapılmasını istemiyorsanız değişiklikleri YEREL'den alın. Bunları YEREL değişikliklere tercih ediyorsanız UZAKTAN değişiklikleri çekin. Hem UZAKTAN hem de YEREL'in yanlış olduğunu düşünüyorsanız BASE'ten çekin. Daha iyi bir fikriniz varsa tamamen farklı bir şey yapın! Sonunda, burada yaptığınız değişiklikler gerçekten yapılacaktır.


4
Hızlı soru vim'e nasıl kaydedebilirim?
Cool Guy Yo

6
:xveya :w( :xçıkışlar da) artı 'dönüş'.
Jonathan Leffler

4
Anders: Nasıl kullanacağınızı bilmiyorsanız kullanabileceğiniz başka birleştirme araçları da var vim.
chepner

3
@AndersKitson, Mac OS X'te olduğunuz için FileMerge mükemmel, ücretsiz ve XCode ile birlikte geliyor.
romainl

8
Neden inişli çıkışlı? Aslında yanlış bir şey varsa, lütfen düzeltin veya en azından işaret edin.
chepner

91

@ chepner'ın cevabı harika, sorunun birleştirme çakışmasını nasıl düzeltmeliyim diye bazı detaylar eklemek istiyorum. Bu durumda vimdiff'i nasıl kullanacağınıza bakarsanız, aşağıya gider.


İlk olarak, "her şeyi iptal et" seçeneğini ele almak için - "vimdiff" kullanmak istemiyorsanız ve birleştirmeyi iptal etmek istiyorsanız: tuşuna basın Esc, sonra yazın :qa!ve basın Enter. (ayrıca bkz . Vim düzenleyicisinden nasıl çıkarım? ). Git, birleştirmenin tamamlanıp tamamlanmadığını soracak, ile yanıt verecektir n.


Vimdiff kullanmak istiyorsanız, işte bazı yararlı kısayollar. Bu, Vim'in temel bilgilerini bildiğinizi varsayar (gezinme ve ekleme / normal mod):

  • alt arabelleğe git (sonucu birleştir): Ctrl-W j
  • j/ ile sonraki farka git k; veya daha iyi, kullanın ] cve[ c sonraki ve önceki fark gitmek için sırasıyla
  • kullanım z o daha fazla bağlam görmek istiyorsanız bir süre, açmak için kat
  • her fark için, @ chepner'ın cevabına göre, kodu yerel, uzak veya temel bir sürümden alabilir veya düzenleyebilir ve uygun gördüğünüz şekilde yeniden yapabilirsiniz
    • yerel sürümden almak için şunu kullanın: :diffget LO
    • uzaktan: :diffget RE
    • tabandan: :diffget BA
    • veya kodu kendiniz düzenlemek istiyorsanız, önce yerel / uzak / tabandan bir sürüm alın ve ardından ekleme moduna gidin ve geri kalanını düzenleyin
  • tamamlandığında, birleştirme sonucunu kaydedin ve tüm pencerelerden çıkın :wqa
  • git normalde birleştirmenin yapıldığını algılar ve birleştirme taahhüdü oluşturur

Kopya yapıştırma veya özel kısayollar olmadan hem yerel hem de uzak çakışma parçalarını eklemek mümkün görünmüyor: /vi/10534/is-there-a-way-to-take-both- add-add -vim-as-merge-tool eklenti ekleme beri utanç verici gibi yaygın bir çatışma türüdür.

Vimdiff'in her başladığında enter tuşuna basmanızı istemesini önlemek için şunu ekleyin .vimrc:

set shortmess=Ot

belirtildiği gibi: /vi/771/how-can-i-suppress-the-press-enter-prompt-when-opening-files-in-diff-mode

İnternette diğer vimdiff kısayollarını arayabilirsiniz. Bunu yararlı buldum: https://gist.github.com/hyamamoto/7783966


10
Bu x1000 kez yükseltilmeli ve daha iyi bir cevap olarak kabul edilmelidir.
Andrey Portnoy

bir sonraki çatışmaya hızlı bir şekilde atlamak için === için arama yapmanız yeterlidir. "/ ===" yapın ve girin
Apit John Ismail

Birden fazla eşleşme kullanılıyorsa bu gönderiye ( stackoverflow.com/questions/51520705/… ) bakın :diffget.
Jason

7

Vimdiff'in yerini alacak nihai birleştirme aracı

Bu bir tür yanak dilidir, ama vimdiff'i denedikten sonra bir vimmer olarak dönüştüm.

Birleştirme çatışmasını çözmek için, neredeyse her zaman ihtiyacım olan şey:

  • UZAKTAN
  • YEREL
  • iki fark:
    • diff BAZ UZAKTAN
    • diff BAZ YEREL

sonra ikisini de bir araya getirmeye çalışın.

Vimdiff ekranda BASE, LOCAL ve REMOTE gösterirken:

    +--------------------------------+
    | LOCAL  |     BASE     | REMOTE |
    +--------------------------------+
    |             MERGED             |
    +--------------------------------+

İhtiyaç duyduğum bu iki farkı açıkça göstermeyi bilmiyorum, ayrıca sağ sola sağ sola birkaç kez bakarak.

Ayrıca, LOCAL ve REMOTE zaten git birleştirme çakışma belirteçlerinde görünür, bu yüzden onları tekrar gösteren bir araçtan bu kadar çok kazanamıyorum.

Bu nedenle, aslında eksik olduğumu farkları gösteren kendi küçük "difftool" oluşturdum:

~ / Bin / cirosantilli-mergetool

#!/usr/bin/env bash
BASE="$1"
LOCAL="$2"
REMOTE="$3"
diff --color -u "$BASE" "$LOCAL"
diff --color -u "$BASE" "$REMOTE"
exit 1

GitHub akış yukarı .

Ve şu şekilde yükleyin:

git config --global mergetool.cirosantilli-mergetool.cmd 'cirosantilli-mergetool $BASE $LOCAL $REMOTE'
git config --global mergetool.cirosantilli-mergetool.trustExitCode true
# If you want this to become your default mergetool.
#git config --global merge.tool 'cirosantilli-mergetool'

Şimdi, yaptığınız zaman:

git mergetool -t cirosantilli-mergetool

Terminalde istediğim iki farkı gösterir, örn.

--- ./src/dev/arm/RealView_BASE_15560.py        2019-12-27 13:46:41.967021591 +0000
+++ ./src/dev/arm/RealView_LOCAL_15560.py       2019-12-27 13:46:41.979021479 +0000
@@ -994,7 +994,7 @@                                                              

     def setupBootLoader(self, cur_sys, loc):
         if not cur_sys.boot_loader:                           
-            cur_sys.boot_loader = [ loc('boot_emm.arm64'), loc('boot_emm.arm') ]
+            cur_sys.boot_loader = [ loc('boot.arm64'), loc('boot.arm') ]
         cur_sys.atags_addr = 0x8000000                  
         cur_sys.load_offset = 0x80000000                    

@@ -1054,7 +1054,7 @@                                           
             ]                                                     

     def setupBootLoader(self, cur_sys, loc):
-        cur_sys.boot_loader = [ loc('boot_emm_v2.arm64') ]
+        cur_sys.boot_loader = [ loc('boot_v2.arm64') ]
         super(VExpress_GEM5_V2_Base,self).setupBootLoader(
                 cur_sys, loc)                             

--- ./src/dev/arm/RealView_BASE_15560.py        2019-12-27 13:46:41.967021591 +0000
+++ ./src/dev/arm/RealView_REMOTE_15560.py      2019-12-27 13:46:41.991021366 +0000
@@ -610,10 +610,10 @@           
     def attachIO(self, *args, **kwargs):              
         self._attach_io(self._off_chip_devices(), *args, **kwargs)

-    def setupBootLoader(self, cur_sys, loc):
-        cur_sys.boot_loader = loc('boot.arm') 
-        cur_sys.atags_addr = 0x100                           
-        cur_sys.load_offset = 0       
+    def setupBootLoader(self, cur_sys, boot_loader, atags_addr, load_offset):
+        cur_sys.boot_loader = boot_loader      
+        cur_sys.atags_addr = atags_addr     
+        cur_sys.load_offset = load_offset

Burada terminalin içine atılan iki farkı görebilirsiniz:

  • RealView_BASE_15560.py vs RealView_LOCAL_15560.py
  • RealView_BASE_15560.py vs RealView_REMOTE_15560.py

Farklar büyükse, sadece tmux süper güçlerimi arayacağım .

Evet, vimdiff'in sağladığı bazı kısayolları kaybedersiniz, ancak genel olarak çakışmaları çözmek, her iki sürümden de dikkatli bir şekilde kopyala yapıştır gerektirir, bu da git çakışma işaretçileriyle normal bir vim oturumunda iyi yapabilirim.

İken Gözlem ve dosyaları diffing vimdiffçalıştıran

Oturup mükemmel kurulumumu otomatikleştirmeden önce cirosantilli-mergetool , ihtiyacım olan iki farkı almak için yapıyordum.

İken git mergetoolçalışıyor vimdiffadlı bir dosya üzerinde bir çelişki varsa, diyelim ki, main.py, git olarak adlandırılan versiyonları, her biri için dosyaları oluşturur:

main_BASE_1367.py
main_LOCAL_1367.py
main_REMOTE_1367.py

git mergetool'un PID'si ve bu nedenle "rastgele" bir tamsayı main.pynerede 1367olduğu ile aynı dizinde : Git birleştirme çakışmasında, oluşturulan BACKUP, BASE, LOCAL ve REMOTE dosyaları nelerdir?

Yani, istediğim diffs görmek için, önce oluşturulan dosyaları bulmak git statusve sonra yeni terminaller açmak ve umurumda dosyaları çiftleri arasında bir vimdiff yapmak:

vim -d main_BASE_1367.py main_LOCAL_1367.py
vim -d main_BASE_1367.py main_REMOTE_1367.py

Birlikte git mergetool, bu bilgi bir LOT hızlı bir şekilde neler olduğunu anlamak için yardımcı olur!

Ayrıca, birleştirme aracı çalışırken bile dosyayı açabilirsiniz:

vim main.py

daha büyük bir düzenleyici penceresiyle daha kolay olacağını düşünüyorsanız doğrudan orada düzenleyin.

Çatışmaları birleştirmek için doğrudan atla

Süre ]c vimdiff içeride sonraki fark noktasına atlar, bir birleştirme ihtilâf söz yoktur.

Bu konuda yardımcı olmak için, benim var ~/.vimrc:

# Git Merge conflict
nnoremap <leader>gm /\v^\<\<\<\<\<\<\< \|\=\=\=\=\=\=\=$\|\>\>\>\>\>\>\> /<cr>

bu da çatışmaları doğrudan bulur.

git imerge

Belki de en iyi seçenek sadece vimdiff'i kullanmaktan vazgeçmek ve şu adreste belirtilen düzenli vim + git imerge'ye güvenmektir : Hangi Git'in çakışmaya neden olduğunu nasıl öğrenebilirim? çünkü vimdiff'in öğrenme eğrisi can sıkıcıdır ve en çok ihtiyaç duyduğumuz işlevleri yapmaz.


1
Upvoted. Sanırım 9 yıl önce stackoverflow.com/a/3052118/6309 adresinde bahsetmiştim . (cevabın son kısmına bakınız)
VonC

@VonC evet, sanırım bunu kazandınız! XD
Ciro Santilli,
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.