Come posso risolvere i conflitti di unione in Git?
git
installazione predefinita . Sono riuscito a raggiungere la pagina iniziale di SE oggi per me, 2017, con 1,3 milioni di visualizzazioni e migliaia di voti in entrambi i modi. Affascinante.
Come posso risolvere i conflitti di unione in Git?
git
installazione predefinita . Sono riuscito a raggiungere la pagina iniziale di SE oggi per me, 2017, con 1,3 milioni di visualizzazioni e migliaia di voti in entrambi i modi. Affascinante.
Risposte:
Provare: git mergetool
Apre una GUI che ti guida attraverso ogni conflitto e puoi scegliere come unirti. A volte richiede un po 'di modifica manuale in seguito, ma di solito è sufficiente da solo. È molto meglio che fare tutto a mano certamente.
Secondo il commento di @JoshGlover:
Il comando
non apre necessariamente una GUI a meno che non ne installi una. Correre
git mergetool
per me ha portatovimdiff
all'utilizzo. È possibile installare uno dei seguenti strumenti per usarlo al posto: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 i conflitti di unione. Sulla base di questo link
Passaggio 1 : eseguire i seguenti comandi nel proprio terminale
git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false
Questo imposterà vimdiff come strumento di unione predefinito.
Passaggio 2 : eseguire il comando seguente nel terminale
git mergetool
Passaggio 3 : vedrai un display vimdiff nel seguente formato
╔═══════╦══════╦════════╗
║ ║ ║ ║
║ LOCAL ║ BASE ║ REMOTE ║
║ ║ ║ ║
╠═══════╩══════╩════════╣
║ ║
║ MERGED ║
║ ║
╚═══════════════════════╝
Queste 4 visualizzazioni sono
LOCALE: si tratta del file dal ramo corrente
BASE: antenato comune, aspetto del file prima di entrambe le modifiche
REMOTO: file che si sta unendo nel proprio ramo
UNITO - unisci il risultato, questo è ciò che viene salvato nel repository
Puoi navigare tra queste viste usando ctrl+ w. Puoi raggiungere direttamente la vista MERGED usando ctrl+ wseguito da j.
Maggiori informazioni sulla navigazione di Vimdiff qui e qui
Passaggio 4 . È possibile modificare la vista MERGED nel modo seguente
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, esegui il commit e pulisci
:wqa
salva ed esci da vi
git commit -m "message"
git clean
Rimuovi file extra (es. * .Orig) creati dallo strumento diff.
git mergetool -y
per salvare alcune sequenze di tasti se si uniscono molti file contemporaneamente.
git mergetool
per me ha portato vimdiff
all'utilizzo. È possibile installare uno dei seguenti strumenti per usarlo al posto: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge
.
git mergetool -t bc3
).
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 riprova, 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 ha 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!
git merge --help
this question
Trovo che gli strumenti di unione raramente mi aiutino a comprendere il conflitto o la risoluzione. Di solito ho più successo guardando gli indicatori di conflitto in un editor di testo e usando git log come supplemento.
Ecco alcuni consigli:
La cosa migliore che ho trovato è usare lo stile di conflitto di unione "diff3":
git config merge.conflictstyle diff3
Questo produce marcatori 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 è l'aspetto dell'antenato comune. Questo è utile perché puoi confrontarlo con le versioni top e bottom per avere un'idea migliore di ciò che è stato modificato su ciascun ramo, il che ti dà un'idea migliore di quale fosse lo scopo di ogni cambiamento.
Se il conflitto è solo di poche righe, ciò rende il conflitto molto evidente. (Sapere come risolvere un conflitto è molto diverso; devi essere consapevole di ciò su cui altre persone stanno lavorando. Se sei confuso, probabilmente è meglio chiamare quella persona nella tua stanza in modo che possano vedere quello che stai guardando a.)
Se il conflitto è più lungo, taglierò e incollerò ciascuna 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
Ciò non equivale a utilizzare uno strumento di unione, poiché uno strumento di fusione includerà anche tutti gli hunk differenziali non in conflitto. Trovo che sia fonte di distrazione.
Qualcuno lo ha già menzionato, ma comprendere l'intenzione dietro ogni pezzo diff è generalmente molto utile per capire da dove proviene 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 stai unendo. (Quindi non include i commit che esistono già in entrambi i rami prima della fusione.) Questo ti aiuta a ignorare diff hunk che chiaramente non sono un fattore nel tuo conflitto attuale.
Verifica le modifiche con strumenti automatizzati.
Se si dispone di test automatici, eseguirli. Se hai un pelucchi , eseguilo . Se è un progetto costruibile, crealo prima di impegnarti, ecc. In tutti i casi, devi fare un po 'di test per assicurarti che le tue modifiche non abbiano interrotto nulla. (Diamine, anche un'unione senza conflitti può rompere il codice di lavoro.)
Pianificare in anticipo; comunicare con i colleghi.
Pianificare in anticipo ed essere consapevoli di ciò su cui gli altri stanno lavorando può aiutare a prevenire l'unione dei conflitti e / o aiutare a risolverli prima, mentre i dettagli sono ancora in mente.
Ad esempio, se sai che tu e un'altra persona state entrambi lavorando su refactoring diversi che influiranno entrambi sullo stesso set di file, dovreste parlarvi in anticipo e avere un senso migliore per quali tipi di modifiche ognuno di voi è fabbricazione. Potresti risparmiare considerevolmente tempo e sforzi se conduci le modifiche pianificate in serie piuttosto che in parallelo.
Per i principali refactoring che attraversano una vasta porzione di codice, dovresti considerare fortemente di lavorare in serie: tutti smettono di lavorare su quell'area del codice mentre una persona esegue il refactoring completo.
Se non riesci a lavorare in serie (a causa della pressione del tempo, forse), allora comunicare sui conflitti di fusione previsti ti aiuta almeno a risolvere i problemi prima, mentre i dettagli sono ancora in mente. Ad esempio, se un collega sta effettuando una serie dirompente di commit nel corso di un periodo di una settimana, è possibile scegliere di unire / rifilare su quel ramo di collaboratori una o due volte al giorno durante quella settimana. In questo modo, se trovi conflitti di unione / rebase, puoi risolverli più rapidamente che se aspetti qualche settimana per unire tutto insieme in un unico grande nodulo.
Se non sei sicuro di unire, non forzarlo.
La fusione può sembrare schiacciante, specialmente quando ci sono molti file in conflitto e gli indicatori di conflitto coprono centinaia di righe. Spesso durante la stima dei progetti software non includiamo abbastanza tempo per gli elementi generali come la gestione di un'unione nodosa, quindi è come un vero e proprio trascinamento passare diverse ore a dissezionare ogni conflitto.
A lungo termine, pianificare in anticipo ed essere consapevoli di ciò su cui gli altri stanno lavorando sono gli strumenti migliori per anticipare i conflitti di unione e prepararsi a risolverli correttamente in meno tempo.
p4merge
, che può essere installato e utilizzato separatamente dagli altri strumenti di Perforce (che non ho usato, ma di cui ho sentito lamentele).
git config merge.conflictstyle diff3
- grazie Signore. Questo è fantastico e mi ha liberato dal tentativo di trovare (e pagare $$) per una buona interfaccia grafica a 3 vie. IMO questo è meglio perché mostra l'antenato comune nonché locale / remoto e mostra le ultime righe del registro di commit che (AFAIK) nessuna GUI fa. I commit sicuramente ti aiuteranno a identificare quale codice appartiene a quale ramo.
Identifica quali file sono in conflitto (Git dovrebbe dirti questo).
Apri ogni file ed esamina le differenze; Git li delimita. Speriamo che sia ovvio quale versione di ciascun blocco conservare. Potrebbe essere necessario discuterne con altri sviluppatori che hanno commesso il codice.
Dopo aver risolto il conflitto in un file git add the_file
.
Dopo aver risolto tutti i conflitti, esegui git rebase --continue
o qualsiasi altro comando Git abbia detto di eseguire al termine.
git add
scena i file nell'indice; essa non aggiunge nulla al repository. git commit
aggiunge cose al repository. Questo utilizzo ha senso per le fusioni: l'unione mette automaticamente in scena tutte le modifiche che possono essere unite automaticamente; è tua responsabilità unire il resto delle modifiche e aggiungerle all'indice quando hai finito.
Controlla le risposte nella domanda Stack Overflow Interruzione di un'unione in Git , in particolare 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
I conflitti di unione si verificano quando vengono apportate modifiche a un file contemporaneamente. Ecco come risolverlo.
git
CLIEcco alcuni semplici passaggi da eseguire quando si entra in uno stato di conflitto:
git status
(nella Unmerged paths
sezione).Risolvi i conflitti separatamente per ogni file con uno dei seguenti approcci:
Utilizzare la GUI per risolvere i conflitti: git mergetool
(il modo più semplice).
Per accettare remote / altra versione, uso: git checkout --theirs path/file
. Ciò rifiuterà qualsiasi modifica locale effettuata per quel file.
Per accettare local / la nostra versione, utilizzare: git checkout --ours path/file
Tuttavia devi stare attento, poiché i cambiamenti remoti che i conflitti sono stati fatti per qualche motivo.
Correlati: 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 =====
. Vedi: Come vengono presentati i conflitti .
I conflitti di percorso e nome file possono essere risolti con git add
/ git rm
.
Infine, rivedere i file pronti per commettere utilizzando: git status
.
Se avete ancora tutti i file sotto Unmerged paths
, ed hanno consentito di risolvere il conflitto manualmente, poi lasciare Git sapere che risolto da: git add path/file
.
Se tutti i conflitti sono stati risolti correttamente, eseguire il commit delle modifiche tramite: git commit -a
e premere su remoto come al solito.
Vedi anche: Risoluzione di un conflitto di unione dalla riga di comando su GitHub
Per esercitazioni pratiche, consultare: Scenario 5 - Correzione dei conflitti di unione di Katacoda .
Ho usato con successo DiffMerge che può confrontare visivamente e unire i 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.
Fonte immagine: DiffMerge (screenshot di Linux)
Basta scaricarlo ed eseguirlo in repository come:
git mergetool -t diffmerge .
Su macOS è possibile installare tramite:
brew install caskroom/cask/brew-cask
brew cask install diffmerge
E probabilmente (se non fornito) è 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 è possibile utilizzare le seguenti scorciatoie da tastiera:
In alternativa puoi usare opendiff (parte di Xcode Tools) che ti permette di unire due file o directory per creare un terzo file o directory.
Se stai effettuando piccoli commit frequenti, inizia guardando i commenti di commit con git log --merge
. Quindi 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 fuori dalla scatola e puoi installarne altri: git config merge.tool "your.tool"
imposterai lo strumento scelto e poigit mergetool
dopo una fusione fallita ti mostrerà le differenze nel contesto.
Ogni volta che modifichi un file per risolvere un conflitto, git add filename
aggiornerà l'indice e il tuo diff non lo mostrerà più. Quando tutti i conflitti vengono gestiti e i loro file sono stati modificati git add
, git commit
completerà la tua unione.
Guarda come sono presentati i conflitti o, in Git, ilgit merge
documentazione per capire quali sono i marker di conflitto di unione.
Inoltre, la sezione Come risolvere i conflitti spiega come risolvere i conflitti:
Dopo aver visto un conflitto, puoi fare due cose:
Decidi di non unirti. Le uniche pulizie necessarie sono reimpostare il file di indice sul
HEAD
commit per invertire 2. e ripulire le modifiche dell'albero di lavoro apportate 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
li all'indice. Utilizzaregit commit
per sigillare l'affare.Puoi risolvere il conflitto con una serie di strumenti:
Usa una fusione.
git mergetool
per lanciare una fusione grafica che ti guiderà attraverso l'unione.Guarda le differenze.
git diff
mostrerà un diff a tre vie, mettendo in evidenza i cambiamenti sia dalHEAD
eMERGE_HEAD
versioni.Guarda le differenze da ogni ramo.
git log --merge -p <path>
mostrerà prima le differenze per laHEAD
versione e poi per laMERGE_HEAD
versione.Guarda gli originali.
git show :1:filename
mostra l'antenato comune,git show :2:filename
mostra laHEAD
versione egit show :3:filename
mostra laMERGE_HEAD
versione.
Puoi anche leggere informazioni su come unire gli indicatori di conflitto e come risolverli nella sezione del libro Pro Git Conflitti di unione di base .
Voglio la mia o la loro versione per intero, o voglio rivedere le singole modifiche e decidere per ognuna di esse.
Accetta completamente la mia o la loro versione :
Accetta la mia versione (locale, la nostra):
git checkout --ours -- <filename>
git add <filename> # Marks conflict as resolved
git commit -m "merged bla bla" # An "empty" commit
Accetta la loro versione (remota, loro):
git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"
Se si desidera eseguire l' esecuzione di tutti i file di conflitto :
git merge --strategy-option ours
o
git merge --strategy-option theirs
Rivedi tutte le modifiche e accettale singolarmente
git mergetool
git add <filename>
git commit -m "merged bla bla"
L'impostazione predefinita mergetool
funziona nella riga di comando . Come utilizzare un mergetool da riga di comando dovrebbe essere una domanda separata.
È inoltre possibile installare lo strumento visivo per questo, ad esempio meld
ed eseguire
git mergetool -t meld
Aprirà la versione locale (la nostra), la "base" o la versione "unita" (il risultato attuale della fusione) e la versione remota (la loro). Salva la versione unita quando hai finito, esegui git mergetool -t meld
nuovamente fino a quando non ottieni "Nessun file deve essere unito", quindi vai ai passaggi 3. e 4.
Per gli utenti Emacs che desiderano risolvere i conflitti di unione semi-manualmente:
git diff --name-status --diff-filter=U
mostra tutti i file che richiedono la risoluzione dei conflitti.
Apri uno di questi file uno per uno o tutti in una volta:
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' (regione successiva), 'p' (regione di previsione). Premere 'a' e 'b' per copiare rispettivamente la mia o la loro regione nel buffer di output. E / o modifica direttamente il buffer di output.
Al termine: premere 'q'. Emacs ti chiede se vuoi salvare questo buffer: sì. Dopo aver terminato un buffer contrassegnarlo come risolto eseguendo dal teriminale:
git add FILENAME
Al termine, digitare tutti i buffer
git commit
per finire l'unione.
Parlando di pull / fetch / merge nelle risposte sopra, vorrei condividere un trucco interessante e produttivo,
git pull --rebase
Questo comando sopra è il comando più utile nella mia vita git che ha fatto risparmiare un sacco di tempo.
Prima di inviare la modifica appena impegnata al server remoto, provare git pull --rebase
piuttosto git pull
e manualemerge
e sincronizzerà automaticamente le ultime modifiche del server remoto (con un fetch + merge) e metterà il tuo ultimo commit locale nella parte superiore nel registro git. Non è necessario preoccuparsi di estrazione / unione manuale.
In caso di conflitto, basta usare
git mergetool
git add conflict_file
git rebase --continue
Per i dettagli, consultare: http://gitolite.com/git-pull--rebase
Semplicemente, se sai bene che i cambiamenti in uno dei repository non sono importanti e vuoi risolvere tutti i cambiamenti a favore dell'altro, usa:
git checkout . --ours
per risolvere le modifiche a favore del tuo repository , o
git checkout . --theirs
per risolvere le modifiche a favore dell'altro o del repository principale .
Altrimenti dovrai utilizzare uno strumento di unione della GUI per scorrere i file uno alla volta, ad esempio lo strumento di unione p4merge
o scrivere il nome di qualcuno che hai già installato
git mergetool -t p4merge
e dopo aver finito un file, dovrai salvare e chiudere, quindi si aprirà quello successivo.
Seguire i passaggi seguenti per correggere i conflitti di unione in Git:
Controlla lo stato Git: stato git
Ottieni il patchset: git fetch (controlla la patch giusta dal tuo commit Git)
Acquista un ramo locale (temp1 nel mio esempio qui): git checkout -b temp1
Estrai i contenuti recenti dal master: git pull --rebase origin master
Avvia il mergetool e controlla i conflitti e correggili ... e controlla le modifiche nel ramo remoto con il tuo ramo corrente: git mergetool
Controlla di nuovo lo stato: stato git
Elimina i file indesiderati creati localmente da mergetool, di solito mergetool crea file extra con estensione * .orig. Si prega di eliminare quel file in quanto è solo il duplicato e correggere le modifiche localmente e aggiungere la versione corretta dei file. aggiungi #your_changed_correct_files
Controlla di nuovo lo stato: stato git
Conferma le modifiche sullo stesso ID commit (questo evita un nuovo set di patch separato): git commit --amend
Invia al ramo principale: git push (nel tuo repository Git)
Ci sono 3 passaggi:
Trova quali file causano conflitti tramite comando
git status
Controlla i file, in cui troverai i conflitti contrassegnati come
<<<<<<<<head
blablabla
Modificalo nel modo desiderato, quindi esegui il commit con i comandi
git add solved_conflicts_files
git commit -m 'merge msg'
È possibile correggere i conflitti di unione in diversi modi, come altri hanno spiegato in dettaglio.
Penso che la vera chiave sia sapere come fluiscono i cambiamenti con i repository locali e remoti. La chiave di ciò è capire i rami di tracciamento. Ho scoperto che penso al ramo di tracciamento come al 'pezzo mancante nel mezzo' tra me la mia directory locale, i file effettivi e il telecomando definito come origine.
Personalmente ho preso l'abitudine di 2 cose per evitare questo.
Invece di:
git add .
git commit -m"some msg"
Che ha due inconvenienti:
a) Vengono aggiunti tutti i file nuovi / modificati e ciò potrebbe includere alcune modifiche indesiderate.
b) Non riesci a rivedere prima l'elenco dei file.
Quindi invece faccio:
git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.
In questo modo sei più deliberato su quali file vengono aggiunti e puoi anche rivedere l'elenco e pensare un po 'di più mentre usi l'editor per il messaggio. Trovo che migliora anche i miei messaggi di commit quando uso un editor a schermo intero anziché l' -m
opzione.
[Aggiornamento - con il passare del tempo sono passato di più a:
git status # Make sure I know whats going on
git add .
git commit # Then use the editor
]
Inoltre (e più rilevante per la tua situazione), provo ad evitare:
git pull
o
git pull origin master.
perché pull implica un'unione e se hai modifiche locali che non volevi unire, puoi facilmente finire con un codice unito e / o unire conflitti per codice che non avrebbe dovuto essere unito.
Invece provo a fare
git checkout master
git fetch
git rebase --hard origin/master # or whatever branch I want.
Potresti anche trovare utile questo:
git branch, fork, fetch, merge, rebase e clone, quali sono le differenze?
git checkout master
e git fetch
e git rebase --hard origin/master
git add .
, salverà le nostre modifiche locali in modo che possiamo seguire git checkout master
? o sono due diversi scenari?
$ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option
hard 'utilizzo: git rebase [-i] [opzioni] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] o: git rebase [-i] [ opzioni] [--exec <cmd>] [--onto <newbase>] --root [<branch>] o: git rebase --continue | --abort | --skip | --edit-todo `
La risposta di CoolAJ86 riassume praticamente tutto. Nel caso in cui tu abbia cambiamenti in entrambi i rami nello stesso pezzo di codice dovrai fare un'unione manuale. Apri il file in conflitto in qualsiasi editor di testo e dovresti vedere la seguente struttura.
(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too
<<<<<<<<<<<
(Code not in conflict here)
Scegli una delle alternative o una combinazione di entrambi nel modo in cui vuoi che sia il nuovo codice, rimuovendo allo stesso tempo segni e parentesi angolari uguali.
git commit -a -m "commit message"
git push origin master
git log --merge -p [[--] path]
Non sembra funzionare sempre per me e di solito finisce per mostrare ogni commit che era diverso tra i due rami, questo succede anche quando si usa --
per separare il percorso dal comando.
Quello che faccio per aggirare questo problema è aprire due righe di comando e in una corsa
git log ..$MERGED_IN_BRANCH --pretty=full -p [path]
e nell'altro
git log $MERGED_IN_BRANCH.. --pretty=full -p [path]
Sostituendo $MERGED_IN_BRANCH
con il ramo in cui mi sono unito e [path]
con il file in conflitto. Questo comando registra tutti i commit, in forma di patch, tra ( ..
) due commit. Se lasci un lato vuoto come nei comandi sopra, git userà automaticamente HEAD
(il ramo in cui ti stai unendo in questo caso).
Ciò ti consentirà di vedere quali commit sono stati inseriti nel file nei due rami dopo che sono stati divergenti. Di solito rende molto più facile risolvere i conflitti.
patience
Sono sorpreso che nessun altro abbia parlato della risoluzione dei conflitti utilizzando patience
la strategia ricorsiva di tipo merge. Per un conflitto di grande unione, usandopatience
fornito buoni risultati per me. L'idea è che proverà ad abbinare i blocchi piuttosto che le singole linee.
Se ad esempio si modifica il rientro del programma, la strategia di unione Git predefinita a volte corrisponde a parentesi singole {
che appartengono a funzioni diverse. Questo è evitato con patience
:
git merge -s recursive -X patience other-branch
Dalla documentazione:
With this option, merge-recursive spends a little extra time to avoid
mismerges that sometimes occur due to unimportant matching lines
(e.g., braces from distinct functions). Use this when the branches to
be merged have diverged wildly.
Se hai un conflitto di unione e vuoi vedere ciò che gli altri avevano in mente durante la modifica del loro ramo, a volte è più facile confrontare il loro ramo direttamente con l'antenato comune (invece del nostro ramo). Per questo puoi usare merge-base
:
git diff $(git merge-base <our-branch> <their-branch>) <their-branch>
Di solito, vuoi solo vedere le modifiche per un determinato file:
git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>
A partire dal 12 dicembre 2016, puoi unire le filiali e risolvere i conflitti su github.com
Pertanto, se non si desidera utilizzare la riga di comando o altri strumenti di terze parti offerti qui dalle risposte precedenti , utilizzare lo strumento nativo di GitHub.
Questo post sul blog spiega in dettaglio, ma le basi sono che quando si uniscono due rami tramite l'interfaccia utente, ora vedrai un'opzione di "risoluzione dei conflitti" che ti porterà a un editor che ti consente di affrontare questi conflitti di unione.
Se desideri unire dal ramo (test) al master, puoi seguire questi passaggi:
Passaggio 1 : vai al ramo
git checkout test
Passaggio 2 :
git pull --rebase origin master
Passaggio 3 : se ci sono alcuni conflitti, vai a questi file per modificarlo.
Passaggio 4 : aggiungere queste modifiche
git add #your_changes_files
Passaggio 5 :
git rebase --continue
Passaggio 6 : se il conflitto persiste, tornare nuovamente al passaggio 3. Se non si verificano conflitti, attenersi alla seguente procedura:
git push origin +test
Step 7 : E poi non c'è conflitto tra test e master. Puoi usare la fusione direttamente.
Seguo sempre i passaggi seguenti per evitare conflitti.
Ora puoi fare lo stesso e mantenere il numero di filiali locali che desideri e lavorare simultaneamente mentre eseguo un checkout git alla tua filiale quando è necessario.
I conflitti di unione potrebbero verificarsi in diverse situazioni:
È necessario installare uno strumento di unione compatibile con Git per risolvere i conflitti. Personalmente uso KDiff3 e l'ho trovato utile e utile. Puoi scaricare la sua versione di Windows qui:
https://sourceforge.net/projects/kdiff3/files/
A proposito, se installi Git Extensions c'è un'opzione nella sua procedura guidata di installazione per installare Kdiff3.
Quindi installa git configs per usare Kdiff come suo mergetool:
$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false
$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false
(Ricorda di sostituire il percorso con il percorso effettivo del file exe di Kdiff.)
Quindi ogni volta che incontri un conflitto di unione devi solo eseguire questo comando:
$git mergetool
Quindi apre Kdiff3 e cerca innanzitutto di risolvere automaticamente i conflitti di unione. La maggior parte dei conflitti verrebbe risolta spontaneamente e sarà necessario correggere il resto manualmente.
Ecco come appare Kdiff3:
Quindi, una volta terminato, salva il file e passa al file successivo con conflitto e fai di nuovo la stessa cosa fino a quando tutti i conflitti non vengono risolti.
Per verificare se tutto è stato unito correttamente, esegui nuovamente il comando mergetool, dovresti ottenere questo risultato:
$git mergetool
No files need merging
Questa risposta è aggiungere un'alternativa per quegli utenti VIM come me che preferiscono fare tutto all'interno dell'editor.
Tpope ha ideato questo fantastico plugin per VIM chiamato fuggitivo . Una volta installato, è possibile eseguire :Gstatus
per verificare i file in conflitto e :Gdiff
per aprire Git in un'unione di 3 modi.
Una volta nella fusione a 3 vie, il fuggitivo ti permetterà di ottenere i cambiamenti di uno dei rami che stai unendo nel modo seguente:
:diffget //2
, ottieni le modifiche dal ramo originale ( HEAD )::diffget //3
, ottieni le modifiche dalla fusione del ramo: Una volta terminata l'unione del file, digitare :Gwrite
il buffer unito. Vimcasts ha pubblicato un ottimo video che spiega in dettaglio questi passaggi.
Puoi provare Gitlense per VS Code, sono le caratteristiche principali:
Mi piace già questa funzione:
E ci sono molte funzionalità che puoi controllare qui .
git fetch
git verifica il tuo
master git rebase master
In questo passaggio proverai a risolvere il conflitto usando il tuo IDE preferito
Puoi seguire questo link per controllare ho per risolvere il conflitto nel file
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/
git aggiungi
git rebase --continua
git commit - modifica
git push origine TESTA: refs / bozze / master (premi come una bozza)
Ora tutto va bene e troverai il tuo impegno in Gerrit
Spero che questo possa aiutare tutti riguardo a questo problema.
Prova Visual Studio Code per la modifica se non lo sei già. Quello che fa è dopo aver provato a fondere (e finire in conflitti di unione). Il codice SV rileva automaticamente i conflitti di unione.
Può aiutarti molto bene mostrando quali sono le modifiche apportate a quella originale e se dovresti accettare incoming
o
current change
(intendendo quello originale prima della fusione) '?.
Mi ha aiutato e può funzionare anche per te!
PS: Funzionerà solo se hai configurato git con il tuo codice e Visual Studio Code.
Un modo più sicuro per risolvere i conflitti è usare git-mediate (le soluzioni comuni suggerite qui sono piuttosto soggette a errori).
Vedi questo post per una rapida introduzione su come usarlo.
Per coloro che usano Visual Studio (2015 nel mio caso)
Chiudi il tuo progetto in VS. Soprattutto nei grandi progetti VS tende a impazzire quando si fonde con l'interfaccia utente.
Esegui l'unione nel prompt dei comandi.
git checkout target_branch
git merge source_branch
Quindi apri il progetto in VS e vai a Team Explorer -> Branch. Ora c'è un messaggio che dice che Merge è in sospeso e i file in conflitto sono elencati proprio sotto il messaggio.
Fai clic sul file in conflitto e avrai la possibilità di unire, confrontare, prendere la fonte, prendere la destinazione. Lo strumento di unione in VS è molto facile da usare.
Se stai usando intelliJ come IDE Prova a unire parent al tuo ramo di
git checkout <localbranch>
git merge origin/<remotebranch>
Mostrerà tutti i conflitti come questo
A_MBPro: test anu $ git merge origin / Auto-merging src / test / java / com /.../ TestClass.java CONFLICT (contenuto): unisci conflitto in src / test / java / com /.../ TestClass.java
Ora nota che il file TestClass.java è mostrato in rosso in intelliJ. Verrà mostrato anche lo stato git
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/test/java/com/.../TestClass.java
Apri il file in intelliJ, avrà sezioni con
<<<<<<< HEAD
public void testMethod() {
}
=======
public void testMethod() { ...
}
>>>>>>> origin/<remotebranch>
dove HEAD sono le modifiche sulla filiale locale e l'origine / sono le modifiche dalla filiale remota. Qui tieni le cose che ti servono e rimuovi quelle che non ti servono, dopodiché i normali passaggi dovrebbero fare. Questo è
git add TestClass.java
git commit -m "commit message"
git push