Domanda Come risolvere i conflitti di fusione in Git


C'è un buon modo per spiegare come risolvere i conflitti di merge in Git?


4121
2017-10-02 11:31


origine


risposte:


Provare: git mergetool

Apre una GUI che ti guida attraverso ogni conflitto e puoi scegliere come unire. A volte richiede un po 'di modifica manuale, ma di solito è sufficiente da solo. È molto meglio che fare il tutto a mano certamente.

Come da commento @JoshGlover:

Il comando non apre necessariamente una GUI a meno che non ne installi una. In esecuzione git mergetool per me risultato vimdiff in uso. Puoi invece installare uno dei seguenti strumenti per utilizzarlo: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

Di seguito è riportata la procedura di esempio da utilizzare vimdiff per risolvere conflitti di unione. Basato su questo link

Passo 1 : Esegui i seguenti comandi nel tuo terminale

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

Questo imposterà vimdiff come strumento di unione predefinito.

Passo 2 : Esegui il seguente comando nel terminale

git mergetool

Passaggio 3 : Verrà visualizzato un display Vimdiff nel seguente formato

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

Queste 4 viste sono

LOCALE: questo è il file dal ramo corrente

BASE - antenato comune, come il file guardava prima di entrambe le modifiche

REMOTE: file che si sta unendo al ramo

MERGED - Unisci risultato, questo è ciò che viene salvato nel repository

Puoi navigare tra queste viste usando ctrl+w. È possibile raggiungere direttamente la vista MERGED utilizzando ctrl+w seguito da j.

Maggiori informazioni sulla navigazione di vimdiff Qui  e Qui

Passaggio 4 . È possibile modificare la vista MERGED nel seguente modo

Se si desidera ottenere modifiche da REMOTE

:diffg RE  

Se si desidera ottenere modifiche da BASE

:diffg BA  

Se si desidera ottenere modifiche da LOCAL

:diffg LO 

Passaggio 5 . Salva, esci, conferma e ripulisci

:wqa salva e esci da vi

git commit -m "message"

git clean Rimuovi i file aggiuntivi (ad esempio * .orig) creati dallo strumento diff.


2412
2017-10-02 17:50



Ecco un probabile caso d'uso, dall'alto:

Stai per apportare alcune modifiche, ma oops, non sei aggiornato:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Quindi ti aggiorni e prova di nuovo, ma hai un conflitto:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

Quindi decidi di dare un'occhiata alle modifiche:

git mergetool

Oh mio, oh mio, a monte ho cambiato alcune cose, ma solo per usare i miei cambiamenti ... no ... i loro cambiamenti ...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

E poi proviamo un'ultima volta

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!


1607
2017-08-04 17:04



Trovo che gli strumenti di unione raramente mi aiutano a capire il conflitto o la risoluzione. Di solito riesco a guardare gli indicatori di conflitto in un editor di testo e ad usare git log come supplemento.

Ecco alcuni suggerimenti:

Suggerimento uno

La cosa migliore che ho trovato è usare lo stile di conflitto di unione "diff3":

git config merge.conflictstyle diff3

Questo produce indicatori di conflitto come questo:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

La sezione centrale è ciò che sembrava l'antenato comune. Ciò è utile perché è possibile confrontarlo con le versioni superiore e inferiore per avere un migliore senso di ciò che è stato cambiato su ciascun ramo, cosa che ti dà un'idea migliore per quale fosse lo scopo di ogni cambiamento.

Se il conflitto è solo di poche righe, questo generalmente rende il conflitto molto ovvio. (Sapere come risolvere un conflitto è molto diverso, devi essere consapevole di ciò su cui stanno lavorando gli altri. Se sei confuso, probabilmente è meglio chiamare quella persona nella tua stanza in modo che possano vedere cosa stai cercando a.)

Se il conflitto è più lungo, allora taglierò e incollerò ognuna delle tre sezioni in tre file separati, come "mio", "comune" e "loro".

Quindi posso eseguire i seguenti comandi per vedere i due hunk diff che hanno causato il conflitto:

diff common mine
diff common theirs

Questo non è lo stesso che usare uno strumento di fusione, poiché uno strumento di unione includerà anche tutti i hunk diff non conflittuali. Trovo che sia fonte di distrazione.

Suggerimento due

Qualcuno ha già menzionato questo, ma la comprensione dell'intenzione dietro ogni diff hunk è generalmente molto utile per capire da dove viene un conflitto e come gestirlo.

git log --merge -p <name of file>

Questo mostra tutti i commit che hanno toccato quel file tra l'antenato comune e le due teste che si stanno unendo. (Quindi non include commit che già esistono in entrambi i rami prima della fusione.) Questo ti aiuta a ignorare i hunk diff che chiaramente non sono un fattore del tuo attuale conflitto.

Suggerimento tre

Verifica le tue modifiche con strumenti automatici.

Se hai test automatici, esegui quelli. Se hai un garza , eseguilo. Se si tratta di un progetto costruibile, quindi costruirlo prima di eseguire il commit, ecc. In tutti i casi, è necessario eseguire un po 'di test per assicurarsi che le modifiche non abbiano infranto nulla. (Diamine, anche una fusione senza conflitti può rompere il codice di lavoro.)

Suggerimento quattro

Pianificare in anticipo; comunicare con i colleghi di lavoro.

Pianificare in anticipo e essere consapevoli di ciò su cui gli altri stanno lavorando può aiutare a prevenire conflitti di fusione e / o aiutare a risolverli prima - mentre i dettagli sono ancora in mente.

Ad esempio, se sai che tu e un'altra persona lavorate entrambi su refactoring differenti che influenzeranno entrambi lo stesso insieme di file, dovreste parlarci prima del tempo e avere un senso migliore per quali tipi di modifiche ognuno di voi è fabbricazione. Potresti risparmiare tempo e sforzi considerevoli se conduci i cambiamenti pianificati in serie piuttosto che in parallelo.

Per i principali refactoring che attraversano una grande quantità di codice, dovresti considerare seriamente di lavorare in serie: tutti smettono di lavorare su quell'area del codice mentre una persona esegue il refactoring completo.

Se non puoi lavorare in serie (a causa della pressione del tempo, forse), comunicare i conflitti di fusione attesi ti aiuta almeno a risolvere i problemi prima, mentre i dettagli sono ancora in mente. Ad esempio, se un collega di lavoro sta effettuando una serie di commit disruptive nel corso di un periodo di una settimana, è possibile scegliere di unire / rebase su quella branca dei collaboratori una o due volte al giorno durante quella settimana. In questo modo, se trovi conflitti di fusione / rebase, puoi risolverli più rapidamente rispetto a quando attendi qualche settimana per unire tutto in un unico grumo.

Suggerimento cinque

Se non sei sicuro di un'unione, non forzarla.

La fusione può sembrare travolgente, soprattutto quando ci sono molti file in conflitto e gli indicatori di conflitto coprono centinaia di righe. Spesso, quando valutiamo progetti software, non includiamo abbastanza tempo per gli articoli generali come la gestione di un'unione nodale, quindi sembra una vera e propria trascina per dedicare diverse ore alla dissezione di ciascun conflitto.

A lungo termine, pianificare in anticipo e essere consapevoli di ciò su cui gli altri stanno lavorando sono i migliori strumenti per anticipare i conflitti di fusione e prepararsi a risolverli correttamente in meno tempo.


683
2017-09-28 21:08



  1. Identifica quali file sono in conflitto (Git dovrebbe dirti questo).

  2. Apri ogni file ed esamina le differenze; Git li demarca. Speriamo che sia ovvio quale versione di ciascun blocco mantenere. Potrebbe essere necessario discuterne con altri sviluppatori che hanno commesso il codice.

  3. Una volta risolto il conflitto in un file git add the_file.

  4. Una volta risolto tutti  conflitti, fallo git rebase --continue o qualunque comando Git ha detto di fare quando hai completato.


320
2017-10-02 12:41



Controlla le risposte nella domanda Stack Overflow Annullare un'unione in Git , particolarmente La risposta di Charles Bailey  che mostra come visualizzare le diverse versioni del file con problemi, ad esempio

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

97
2017-10-03 15:15



I conflitti di unione si verificano quando le modifiche vengono apportate a un file contemporaneamente. Ecco come risolverlo.

git CLI

Ecco alcuni semplici passaggi su cosa fare quando si entra in uno stato conflittuale:

  1. Annota l'elenco di file in conflitto con: git status (sotto Unmerged paths sezione).
  2. Risolvi i conflitti separatamente per ogni file con uno dei seguenti approcci:

    • Usa la GUI per risolvere i conflitti: git mergetool (la via più facile).

    • Per accettare la versione remota / altra, utilizzare: git checkout --theirs path/file. Questo rifiuterà qualsiasi modifica locale che hai fatto per quel file.

    • Per accettare la versione locale / nostra, utilizzare: git checkout --ours path/file

      Tuttavia devi stare attento, in quanto modifiche remote che i conflitti sono stati fatti per qualche motivo.

      Relazionato: Qual è il significato preciso di "nostro" e "loro" in git?

    • Modifica manualmente i file in conflitto e cerca il blocco di codice tra <<<<</ >>>>> quindi scegli la versione dall'alto o dal basso =====. Vedere: Come vengono presentati i conflitti .

    • I conflitti tra percorso e nome file possono essere risolti da git add/ git rm.

  3. Infine, rivedi i file pronti per il commit usando: git status.

    Se hai ancora qualche file sotto Unmerged pathse hai risolto il conflitto manualmente, quindi fai sapere a Git che l'hai risolto con: git add path/file.

  4. Se tutti i conflitti sono stati risolti correttamente, commetti le modifiche: git commit -a e spingere al telecomando come al solito.

Guarda anche: Risolvere un conflitto di unione dalla riga di comando  a GitHub

DiffMerge

Ho usato con successo DiffMerge  che può confrontare visivamente e unire file su Windows, macOS e Linux / Unix.

Può mostrare graficamente le modifiche tra 3 file e consente l'unione automatica (quando è sicuro farlo) e il pieno controllo sulla modifica del file risultante.

DiffMerge

Fonte immagine: DiffMerge  (Screenshot di Linux)

Basta scaricare ed eseguire in pronti contro termine come:

git mergetool -t diffmerge .

Mac OS

Su macOS puoi installare tramite:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

E probabilmente (se non previsto) è necessario il seguente wrapper extra semplice inserito nel PERCORSO (ad es. /usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Quindi puoi utilizzare le seguenti scorciatoie da tastiera:

  • - alt - Su / Giù  per saltare alle modifiche precedenti / successive.
  • - alt - Sinistra / Destra  accettare il cambiamento da sinistra o destra

In alternativa puoi usare opendiff  (parte di Xcode Tools) che consente di unire due file o directory insieme per creare un terzo file o directory.


88
2017-08-05 14:29



Se esegui frequenti piccoli commit, inizia guardando i commenti di commit con git log --merge. Poi git diff ti mostrerà i conflitti.

Per i conflitti che coinvolgono più di poche righe, è più facile vedere cosa sta succedendo in uno strumento GUI esterno. Mi piace l'opendiff - Git supporta anche vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, emerge out of the box e puoi installarne altri: git config merge.tool "your.tool" imposterà lo strumento scelto e poi git mergetool dopo una fusione fallita ti mostrerà le differenze nel contesto.

Ogni volta che si modifica un file per risolvere un conflitto, git add filename aggiornerà l'indice e il tuo diff non lo mostrerà più. Quando tutti i conflitti sono gestiti e i loro file sono stati git add-ed, git commit completerà la fusione.


73
2017-10-02 16:11



Vedere In che modo vengono presentati i conflitti  o, in Git, il git merge documentazione per capire cosa sono gli indicatori di conflitto.

Anche il Come risolvere i conflitti  la sezione spiega come risolvere i conflitti:

Dopo aver visto un conflitto, puoi fare due cose:

  • Decidi di non unire. Gli unici cleanup di cui hai bisogno sono di resettare il file di indice sul file HEAD impegnarsi a invertire 2. e pulire le modifiche dell'albero di lavoro fatte da 2. e 3; git merge --abort può essere usato per questo.

  • Risolvi i conflitti. Git segnerà i conflitti nell'albero di lavoro. Modifica i file in forma e git add loro all'indice. Uso git commit per sigillare l'affare.

Puoi lavorare attraverso il conflitto con una serie di strumenti:

  • Usa un mergetool. git mergetool per avviare un mergetool grafico che ti consentirà di completare l'unione.

  • Guarda le differenze. git diff mostrerà un differenziale a tre vie, evidenziando i cambiamenti da entrambi HEAD e MERGE_HEAD versioni.

  • Guarda le differenze da ogni ramo. git log --merge -p <path> mostrerà diffs prima per il HEAD versione e poi il MERGE_HEAD versione.

  • Guarda gli originali. git show :1:filename mostra l'antenato comune, git show :2:filename mostra il HEAD versione, e git show :3:filename mostra il MERGE_HEAD versione.

Puoi anche leggere informazioni su come unire i contrassegni di conflitto e su come risolverli in Pro Git  sezione del libro Conflitti di fusione di base .


43
2017-07-14 18:34



Per Emacs  utenti che desiderano risolvere conflitti di unione in modo semiautomatico:

git diff --name-status --diff-filter=U

mostra tutti i file che richiedono la risoluzione dei conflitti.

Apri ciascuno di questi file uno alla volta o tutti contemporaneamente:

emacs $(git diff --name-only --diff-filter=U)

Quando si visita un buffer che richiede modifiche in Emacs, digitare

ALT+x vc-resolve-conflicts

Questo aprirà tre buffer (il mio, il loro e il buffer di output). Navigare premendo 'n' (area successiva), 'p' (area di previsione). Premi "a" e "b" per copiare rispettivamente la mia o la loro regione nel buffer di output. E / o modificare direttamente il buffer di output.

Al termine: premere "q". Emacs ti chiede se vuoi salvare questo buffer: sì. Dopo aver terminato un buffer, contrassegnalo come risolto eseguendo dal teriminale:

git add FILENAME

Al termine con tutti i tipi di buffer

git commit

per finire l'unione.


36
2018-02-22 23:04



Si prega di seguire i seguenti passi per risolvere i conflitti di fusione in Git:

  1. Controlla lo stato di Git: stato git

  2. Ottieni la patchset: git fetch  (controlla la patch corretta dal tuo commit Git)

  3. Acquista un ramo locale (temp1 nel mio esempio qui): git checkout -b temp1

  4. Estrai i contenuti recenti dal master: git pull --rebase master d'origine

  5. Avvia il mergetool e controlla i conflitti e risolvili ... e controlla le modifiche nel ramo remoto con il tuo attuale ramo: git mergetool

  6. Controlla di nuovo lo stato:   stato git

  7. Elimina i file indesiderati creati localmente da mergetool, solitamente mergetool crea file extra con estensione * .orig. Per favore cancella quel file dato che è solo il duplicato e correggi le modifiche localmente e aggiungi la versione corretta dei tuoi file. git aggiungi #your_changed_correct_files

  8. Controlla di nuovo lo stato: stato git

  9. Applica le modifiche allo stesso ID commit (questo evita un nuovo set di patch separato): git commit --amend

  10. Spingere al ramo principale: spingere  (al tuo repository Git)


28
2018-04-16 07:02