Risolvi Git unisci i conflitti a favore delle loro modifiche durante un pull


1227

Come posso risolvere un conflitto di unione git a favore delle modifiche apportate?

Fondamentalmente ho bisogno di rimuovere tutte le modifiche in conflitto da un albero di lavoro senza dover attraversare tutti i conflitti con un git mergetoolpo 'mantenendo tutte le modifiche senza conflitti. Preferibilmente farlo mentre si tira, non in seguito.




3
@DanDascalescu Risposta accettata non risponde a queste domande, quindi chiaramente non è un duplicato. Inoltre, quell'altra domanda è abbastanza ambigua: è molto difficile dire cosa viene chiesto. Tutto sommato non posso essere d'accordo con te. Cosa punti in questo?
sanmai,

2
@sanmai Hai due risposte e ne hai accettata una. Puoi spiegare meglio cosa ti aspetti da una risposta e quanti dettagli vuoi qui?
Edward Thomson,

2
@EdwardThomson bene, in realtà stavo pensando di dare a questa reputazione la prima risposta, ma se mi chiedi, potrei aspettare e vedere se arriva una risposta migliore
sanmai,

Risposte:


1220
git pull -s recursive -X theirs <remoterepo or other repo>

O, semplicemente, per il repository predefinito:

git pull -X theirs

Se sei già in stato di conflitto ...

git checkout --theirs path/to/file

40
Nota che -s recursivequi è ridondante, poiché questa è la strategia di unione predefinita. Quindi potresti semplificarlo git pull -X theirs, che è sostanzialmente equivalente a git pull --strategy-option theirs.

5
Se lo faccio, finisco di nuovo nello MERGINGstato. Posso quindi git merge --aborte riprovare, ma ogni volta che si verifica un'unione. ... So che però un rebase è stato spinto verso il mio monte, quindi forse questo lo sta causando?
Benjohn,

22
Stai attento con git checkout --theirs path/to/file. Lo ha usato durante rebase e ha ottenuto risultati inaspettati. Spiegazione trovata nel documento: Notare che durante git rebase e git pull --rebase, i nostri e i loro possono apparire scambiati; --ours fornisce la versione dal ramo su cui vengono modificate le modifiche, mentre --the dà la versione dal ramo che contiene il tuo lavoro che viene modificato.
Vuk Djapic,

10
Si noti che la git checkout --theirs/--ours pathpagina man afferma che funziona per percorsi non uniti . Quindi se non ci sono stati conflitti nel percorso, è già unito questo comando non farà nulla. Ciò potrebbe causare problemi quando si desidera, ad esempio, la versione "loro" di un'intera sottocartella. Quindi in tal caso sarebbe più sicuro fare git checkout MERGE_HEAD patho usare l'hash di commit.
fsw,

4
git pull -X theirscrea un commit di unione in caso di conflitti (ad es. se un altro committer è stato eseguito git push -fsul telecomando). Se non desideri unire i commit, esegui invece git fetch && git reset --hard origin/master.
Dan Dascalescu,

985

È possibile utilizzare l' opzione di strategia "loro" ricorsiva :

git merge --strategy-option theirs

Dal uomo :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Nota: come dice la pagina man, l' opzione di strategia di unione "nostro" è molto diversa dalla strategia di unione "nostro" .


Ecco una spiegazione più dettagliata: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC

227
Anche git checkout --theirsper operare su un singolo file in conflitto
dvd

48
Questo non funziona se ci si trova già nello stato di risoluzione dei conflitti. In quel caso credo che il modo migliore per risolvere sia git checkout <ref to theirs> -- the/conflicted.file; e poi i git addloro cambiamenti.
ThorSummoner,

54
@ThorSummoner In quel caso, c'è il checkout git - il loro percorso / di / file. In questo modo, non è necessario cercare manualmente l'hash corretto.
Ikke,

8
@Ikke Questa dovrebbe fondamentalmente essere la sua stessa risposta (e la risposta accettata) se me lo chiedi.
ThorSummoner,

473

Se sei già in uno stato di conflitto e vuoi semplicemente accettare tutti i loro:

git checkout --theirs .
git add .

Se vuoi fare il contrario:

git checkout --ours .
git add .

Questo è piuttosto drastico, quindi assicurati di voler davvero cancellare tutto in questo modo prima di farlo.


47
oppure, non utilizzare .e specificare i file al posto del punto che si desidera verificare. meno "drastico" ed esattamente quello che vuoi fare, presumibilmente.
Manroe,

10
questo non funziona se il file è stato rimosso dall'altro ramo: '<file>' non ha la sua versione
Japster24

3
Voterei di più se potessi, continuando a tornare a questa risposta di tanto in tanto.
Tarikki,

6
Utilizzare git add -uinvece per saltare i file che non sono sotto il controllo della versione.
Sudipta Basak,

3
Caso ipotetico, tre modifiche in un file, una in conflitto, due senza conflitto, questa soluzione applicherà le modifiche non in conflitto e risolverà la modifica in conflitto con la nostra? O ci vorrebbe solo la nostra versione ignorando le modifiche non contrastanti dalla loro?
pedromarce,

222

OK, immagina lo scenario in cui mi trovavo:

Cerchi un merge, o forse un cherry-pick, e ti fermi con

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Ora, visualizzi il file in conflitto e non vuoi davvero conservare le tue modifiche. Nel mio caso sopra, il file era in conflitto solo su una nuova riga che il mio IDE aveva aggiunto automaticamente. Per annullare le modifiche e accettarne le, il modo più semplice è:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Il contrario di questo (per sovrascrivere la versione in arrivo con la tua versione) è

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Sorprendentemente, non sono riuscito a trovare questa risposta molto facilmente sulla rete.


15
Si noti che, se si esegue una git statustra checkoute add, il file viene comunque visualizzato come "entrambi modificati".
vescovo

Sai se esiste un modo per farlo per tutti i file che si trovano in uno stato di conflitto? Se è così sarebbe una bella estensione alla tua risposta.
Ha disegnato Noakes il

2
Faccio questo: git reset --hard e poi git pull [remote server name] [branch name] -Xtheirs(annulla l'unione e poi tira le nuove cose sopra le mie cose) - non sono sicuro se questo è quello che vuoi.
ssaltman,

38

Le git pull -X theirsrisposte possono creare un brutto commit di unione o emettere un

errore: le modifiche locali ai seguenti file verrebbero sovrascritte dall'unione:

Se si desidera semplicemente ignorare eventuali modifiche locali ai file dal repository, ad esempio su un client che dovrebbe sempre essere un mirror di un'origine, eseguire questo (sostituire mastercon il ramo desiderato):

git fetch && git reset --hard origin/master

Come funziona? git fetchfa git pullma senza fondersi . Quindi git reset --hardrende l'albero di lavoro corrispondente all'ultimo commit. Tutte le modifiche locali ai file nel repository verranno eliminate , ma i nuovi file locali verranno lasciati soli.


1
+1 - è git fetch && git reset --hard {remote}/{branch}stato ciò che ha risolto il mio problema. Avevo bisogno di abbandonare completamente le mie modifiche a favore dello stato "loro" di un ramo, ma il git pull -X theirssoffocato su alcuni file spostati / rinominati. Grazie!
Ivaylo Slavov il

23

Dopo git merge, se ottieni conflitti e vuoi il tuo o il loro

git checkout --theirs .
git checkout --ours .

Come lo farei su base per pezzo in conflitto? Quanto sopra funziona a livello di file, eliminando eventuali blocchi non in conflitto che un file in conflitto potrebbe avere.
Jani il

21

Per risolvere tutti i conflitti con la versione in un determinato ramo:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Pertanto, se si è già nello stato di unione e si desidera mantenere la versione principale dei file in conflitto:

git diff --name-only --diff-filter=U | xargs git checkout master

E per le persone su Windows senza accesso a xargs pipe, come si traduce?
Tsemer,

Non salterebbe completamente le modifiche? Anche quelli che non sono in conflitto?
Valentin Heinitz,

Questo è quello che ho finito per fare. Sfortunatamente in seguito richiede un comando git cherry-pick --continue o un git commit --allow-emptycomando per eseguire il commit di queste modifiche e non sembra esserci alcun sistema dietro il quale è richiesto il comando, il che rende l'automazione un problema. Attualmente sto risolvendo questo test verificando l'esistenza di un .git/COMMIT_EDITMSGfile, ma questo sembra confuso e fragile, e non sono ancora convinto che funzioni sempre.
Konrad Rudolph,

Questo è buono, significa che se risolvi alcuni manualmente (e lo fai git add), puoi risolvere il resto in blocco tramite questo. git checkout --ours/ git checkout --theirsè anche utile.
raccoup

18

Si prega di non che a volte questo non funzionerà :

git checkout: percorso / file /

o

git checkout - il loro percorso / in / file

L'ho fatto invece, supponendo che HEAD sia nostro e MERGE_HEAD sia il loro

git checkout HEAD -- path/to/file

o:

git checkout MERGE_HEAD -- path/to/file

Dopo aver fatto questo e siamo bravi:

git add .

Se vuoi saperne di più, vedi il meraviglioso post di torek qui: git checkout --ours non rimuove i file dall'elenco dei file non uniti


12

Utenti IDE VS Code (Git integrato):

Se si desidera accettare tutte le modifiche in entrata nel file di conflitto, procedere come segue.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Allo stesso modo puoi fare per altre opzioni come Accetta tutto entrambi, Accetta tutto corrente ecc.,


2
Ciò sembra funzionare solo per un singolo file, non per tutti i file con conflitti.
Yoryo,

1

Ho avuto un next-versionramo di lunga data con tonnellate di eliminazioni di file che erano stati modificati develop, file che erano stati aggiunti in punti diversi su entrambi i rami, ecc.

Volevo prendere l'intero contenuto del next-versionramo develop, tutto in un unico commit di merge merge.

La combinazione dei comandi sopra che ha funzionato per me è stata:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Non una nuova risposta, che combina solo bit di molte risposte, in parte per rassicurare che potresti aver bisogno di tutte queste risposte.


1

Se sei già in stato di conflitto e non vuoi controllare il percorso uno per uno. Puoi provare

git merge --abort
git pull -X theirs

-1

da https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Questo fondamentalmente farà una falsa fusione. Registrerà un nuovo commit di unione con entrambi i rami come genitori, ma non guarderà nemmeno il ramo in cui ti stai unendo. Registrerà semplicemente come risultato dell'unione il codice esatto nel tuo ramo corrente.

$ git merge -s ours mundo

Unisci la strategia "nostra".

$ git diff HEAD HEAD~

Puoi vedere che non c'è differenza tra il ramo in cui ci trovavamo e il risultato dell'unione.

Questo può spesso essere utile per indurre Git a pensare che un ramo è già unito quando si fa un'unione in seguito. Ad esempio, supponiamo che tu abbia ramificato un ramo di rilascio e hai fatto del lavoro su di esso che vorresti ricollegare nel tuo ramo principale ad un certo punto. Nel frattempo, è necessario eseguire il backport di alcuni bug sul master nel ramo di rilascio. È possibile unire il ramo bugfix nel ramo di rilascio e unire -s il nostro stesso ramo nel ramo principale (anche se la correzione è già presente), quindi quando unisci nuovamente il ramo di rilascio, non ci sono conflitti dal bugfix.

Una situazione che ho trovato utile se volevo che il master riflettesse le modifiche di un nuovo argomento. Ho notato che -Xtheirs non si fonde senza conflitti in alcune circostanze ... ad es

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

In questo caso la soluzione che ho trovato è stata

$ git checkout topicFoo

da topicFoo, prima unisci in master usando la nostra strategia -s, questo creerà il falso commit che è solo lo stato di topicFoo. $ git merge -s il nostro maestro

controlla il commit di unione creato

$ git log

ora controlla il ramo principale

$ git checkout master

fondere il ramo argomento ma questa volta utilizzare la strategia ricorsiva -Xtheirs, questo ora ti presenterà un ramo master con lo stato di topicFoo.

$ git merge -X theirs topicFoo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.