Come posso annullare le modifiche remote e contrassegnare un file come "risolto"?


197

Ho alcuni file locali, estraggo dal ramo remoto e ci sono conflitti. So che vorrei mantenere le mie modifiche locali e ignorare le modifiche remote che causano conflitti. Esiste un comando che posso usare per dire "contrassegna tutti i conflitti come risolti, usa locale"?


1
La risposta che segue è stata super illuminante per me. Ci sono un paio di punti sottili che mi chiariscono davvero le cose, consiglio a tutti gli utenti GIT non esperti di leggere tutti i commenti sotto il post qui sotto e grazie Brian!
Tom DeMille,

Risposte:


332

git checkoutha la --ourspossibilità di verificare la versione del file che avevi localmente (al contrario --theirs, che è la versione che hai inserito). Puoi passare .a git checkoutper dirgli di controllare tutto nell'albero. Quindi devi contrassegnare i conflitti come risolti, cosa che puoi fare git adde impegnare il tuo lavoro una volta fatto:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

Nota .nel nel git checkoutcomando. È molto importante e facile da perdere. git checkoutha due modalità; uno in cui cambia i rami e uno in cui controlla i file dall'indice nella copia di lavoro (a volte estraendoli nell'indice da un'altra revisione prima). Il modo in cui si distingue è se hai passato un nome file; se non hai passato un nome di file, prova a cambiare i rami (anche se se non passi nemmeno un ramo, proverà a controllare di nuovo il ramo corrente), ma rifiuta di farlo se ci sono file modificati che avrebbe effetto. Quindi, se si desidera un comportamento che sovrascriverà i file esistenti, è necessario passare .o un nome file per ottenere il secondo comportamento git checkout.

È anche una buona abitudine avere, quando si passa un nome di file, con cui compensarlo --, come git checkout --ours -- <filename>. Se non lo fai, e il nome del file coincide con il nome di un ramo o tag, Git penserà che vuoi controllare quella revisione, invece di estrarre quel nome, e quindi usa la prima forma del checkoutcomando .

Espanderò un po 'su come funzionano i conflitti e la fusione in Git. Quando ti unisci nel codice di qualcun altro (che si verifica anche durante un pull; un pull è essenzialmente un recupero seguito da una fusione), ci sono poche possibili situazioni.

Il più semplice è che sei sulla stessa revisione. In questo caso, sei "già aggiornato" e non succede nulla.

Un'altra possibilità è che la loro revisione sia semplicemente una tua discendente, nel qual caso per impostazione predefinita avrai una "fusione rapida", in cui il tuo HEADè appena aggiornato al loro commit, senza che si verifichi fusione (questo può essere disabilitato se tu voglio davvero registrare un'unione, usando --no-ff).

Quindi entri nelle situazioni in cui devi effettivamente unire due revisioni. In questo caso, ci sono due possibili esiti. Uno è che l'unione avviene in modo pulito; tutte le modifiche si trovano in file diversi o si trovano negli stessi file ma abbastanza distanti da poter applicare senza problemi entrambi i gruppi di modifiche. Per impostazione predefinita, quando si verifica un'unione pulita, viene automaticamente impegnata, anche se è possibile disabilitarla --no-commitse è necessario modificarla in anticipo (ad esempio, se si rinomina la funzione fooin bar, e qualcun altro aggiunge un nuovo codice che chiama foo, si unirà in modo pulito , ma produci un albero spezzato, quindi potresti voler ripulirlo come parte del commit di unione per evitare di avere commit interrotti).

L'ultima possibilità è che ci sia una vera unione e che ci siano conflitti. In questo caso, Git farà la maggior quantità di fusione in quanto si può, e file di produrre con marcatori di conflitto ( <<<<<<<, =======, e >>>>>>>) nella copia di lavoro. Nell'indice (noto anche come "area di gestione temporanea", il luogo in cui vengono archiviati i file git addprima di eseguirne il commit), avrai 3 versioni di ciascun file con conflitti; c'è la versione originale del file dall'antenato dei due rami che stai unendo, la versione da HEAD(il tuo lato dell'unione) e la versione dal ramo remoto.

Per risolvere il conflitto, è possibile modificare il file presente nella copia di lavoro, rimuovendo gli indicatori di conflitto e correggendo il codice in modo che funzioni. Oppure, puoi controllare la versione da uno o l'altro lato dell'unione, usando git checkout --ourso git checkout --theirs. Una volta che hai messo il file nello stato desiderato, indichi che hai finito di unire il file ed è pronto per il commit utilizzando git add, quindi puoi eseguire il commit dell'unione git commit.


7
Dovresti probabilmente notare che git add --allaggiunge tutti i file al repository in modo che questo possa aggiungere più file del previsto a meno che i tuoi .gitignoremodelli non siano in uno stato perfetto.git add -uè probabilmente più adatto a questa situazione, è meno probabile che tu abbia modifiche ai file tracciati che non desideri aggiungere durante la risoluzione di un'unione.
CB Bailey,

Oops scusa. Ecco cosa intendevo. Corretto adesso.
Brian Campbell,

1
grazie per la tua risposta dettagliata. In realtà ho provato git checkout --ours e ho ricevuto un messaggio di errore (che non ricordo ora). I file in questione sono dll (ne abbiamo alcuni che facciamo stash, principalmente riferimenti di terze parti) e volevo solo dire 'ok la mia copia sono quelli che voglio ma l'errore era qualcosa come' impossibile effettuare il checkout durante l'unione ' ..... Terrò questo articolo come riferimento e la prossima volta che succede riprovare e vedere se funziona o se posso pubblicare quel messaggio. Grazie ancora
Tom DeMille

ma la tua spiegazione mi chiarisce molto sul processo, grazie ancora ... Domanda di follow-up: Qualche modo per ottenere git per eliminare i file .orig una volta che ho cancellato l'unione?
Tom DeMille,

2
Hai bisogno di fare git checkout --ours .. Il .è importante; passando un nome di file (in questo caso, l'intera directory) si seleziona tra due diverse modalità di funzionamento di checkout, uno che cambia i rami e uno che sposta i file dall'indice alla copia di lavoro. Sono d'accordo, è molto confuso. Puoi anche fare il git checkout --ours -- <filename>check-out di un singolo file alla volta.
Brian Campbell,

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.