Condividi tramite


Risolvere i conflitti di unione

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Visual Studio 2019 | Visual Studio 2022

Quando si unisce o si esegue la ribase, git sta dicendo a Git di integrare le modifiche apportate in un ramo con le modifiche apportate in un altro. Spesso Git completa automaticamente un'operazione di merge o ribase senza assistenza. Tuttavia, se Git rileva che una modifica apportata in un ramo è in conflitto con una modifica apportata a un'altra, richiede di risolvere il conflitto. Un conflitto di merge può verificarsi quando i rami uniti modificano la stessa riga di file in modo diverso o quando un ramo modifica un file e un altro ramo lo elimina. Il processo per la risoluzione dei conflitti di merge è applicabile sia all'unione git che alla rebase.

È possibile risolvere i conflitti di unione in Visual Studio oppure usando la riga di comando e qualsiasi editor di testo.

Per una panoramica del flusso di lavoro Git, vedere Esercitazione su Git di Azure Repos.

Questo articolo illustra le procedure per le attività seguenti:

  • Informazioni sui conflitti di unione
  • Risolvere i conflitti di unione

Informazioni sui conflitti di unione

L'unione git o la rebase integra i commit da un ramo di origine nel ramo locale corrente (ramo di destinazione). L'unione Git esegue un'operazione di merge fast forward o no-fast-forward. L'unione senza inoltro rapido è nota anche come unione a tre vie o vera unione. La rebase Git è un altro tipo di merge. Questi tipi di unione sono illustrati nel diagramma seguente.

Diagramma che mostra i commit prima e dopo quando si usa git merge e git rebase.

Per l'unione Git, se il suggerimento del ramo di destinazione esiste all'interno del ramo di origine, il tipo di unione predefinito sarà un merge con inoltro rapido. In caso contrario, il tipo di unione predefinito sarà un'unione senza inoltro rapido.

Un'unione con avanzamento rapido non può mai avere un conflitto di merge perché Git non applicherà un merge rapido se la punta del ramo di destinazione si è discosta dal ramo di origine. Per impostazione predefinita, Git usa un'unione rapida ogni volta che possibile. Ad esempio, Git applicherà un merge fast forward in un ramo locale che viene aggiornato solo eseguendo il pull dal ramo controparte remota.

Un'unione no-fast-forward genera un nuovo ramo di destinazione "commit di merge" che integra le modifiche del ramo di origine con le modifiche del ramo di destinazione. Le modifiche applicabili sono quelle apportate dopo l'ultimo commit comune a entrambi i rami. Nel diagramma precedente il commit C è l'ultimo commit comune in entrambi i rami. Se una modifica del ramo di origine è in conflitto con qualsiasi modifica del ramo di destinazione, Git chiederà di risolvere il conflitto di merge. Il commit di merge (L) contiene le modifiche del ramo di origine integrato e del ramo di destinazione. I suggerimenti per il ramo di origine e di destinazione (K e E) sono gli elementi padre del commit di merge. Nella cronologia dei commit del ramo, un commit di merge è un indicatore utile per un'operazione di merge e mostra chiaramente quali rami sono stati uniti.

Git esegue nuovamente la ribase della cronologia dei commit del ramo di destinazione in modo che contenga tutti i commit del ramo di origine, seguiti da tutti i commit del ramo di destinazione dall'ultimo commit comune. Nel diagramma precedente il commit C è l'ultimo commit comune in entrambi i rami. Un altro modo per visualizzare è che una ribase riproduce le modifiche nel ramo di destinazione sopra la cronologia dei rami di origine. Se una modifica del ramo di origine è in conflitto con qualsiasi modifica del ramo di destinazione, Git chiederà di risolvere il conflitto di merge. Come per l'unione a inoltro rapido, una rebase non crea un commit di merge. In particolare, una rebase modifica la sequenza dei commit del ramo di destinazione esistente, che non è il caso per le altre strategie di merge. Nel diagramma precedente, commit K' contiene le stesse modifiche di K, ma ha un nuovo ID commit perché si collega di nuovo al commit E invece di C.

L'unione e la ribase git modificano solo il ramo di destinazione. Il ramo di origine rimane invariato. Quando si verificano uno o più conflitti di unione, è necessario risolverli per completare l'unione o la rebase. In alternativa, è possibile annullare l'operazione di merge/ribase e restituire il ramo di destinazione allo stato precedente.

Per altre informazioni sulle opzioni e sulle strategie di merge, vedere le strategie di riferimento git manuali e Git merge.

Quando risolvere i conflitti di merge

L'unione git e la rebase Git vengono ampiamente usate nel flusso di lavoro Git. Quando si lavora su una funzionalità locale o un ramo di correzione di bug, è pratica comune:

  1. Mantenere aggiornato il ramo locale main con la controparte remota eseguendo periodicamente il pull per recuperare e unire i commit remoti.
  2. Integrare gli aggiornamenti del ramo locale main nel ramo di funzionalità locale usando una ribase o unisci.
  3. Eseguire il backup del lavoro nel ramo di funzionalità locale eseguendo il push nel ramo remoto corrispondente.
  4. Al termine della funzionalità, creare una richiesta pull per unire il ramo di funzionalità remoto nel ramo remoto main .

Integrando spesso le modifiche remote nel repository locale, è possibile rimanere a conoscenza del lavoro recente da parte di altri utenti e risolvere tempestivamente eventuali conflitti di merge che si verificano.

Risolvere i conflitti di unione

Il processo per la risoluzione dei conflitti di merge è applicabile sia all'unione Git che alla rebase Git. Anche se i passaggi seguenti descrivono come risolvere i conflitti di unione durante un'unione, è possibile risolvere in modo analogo i conflitti di merge durante una ribase.

Suggerimento

Se il ramo di origine è un ramo di rilevamento remoto, assicurarsi che il ramo sia aggiornato eseguendo un recupero Git prima di un merge. In alternativa, eseguire il comando git pull , che combina un recupero Git con un'unione Git.

Visual Studio 2022 offre un'esperienza di controllo della versione Git usando il menu Git, Le modifiche Git e tramite i menu di scelta rapida in Esplora soluzioni. Visual Studio 2019 versione 16.8 offre anche l'interfaccia utente Git di Team Explorer . Per altre informazioni, vedere la scheda Visual Studio 2019 - Team Explorer .

  1. Nel riquadro Rami della finestra Repository Git eseguire il checkout del ramo di destinazione. Fare quindi clic con il pulsante destro del mouse sul ramo di origine e scegliere Merge source-branch into target-branch .Then right-click the source branch and choose Merge source-branch into <target-branch>>.<

    Screenshot dell'opzione Merge nel menu di scelta rapida del ramo nella finestra Repository Git di Visual Studio.

  2. Visual Studio invierà una notifica se Git ha interrotto l'unione a causa di conflitti. In tal caso, è possibile risolvere i conflitti oppure annullare l'unione e tornare allo stato di pre-unione. La sezione Modifiche non salvate della finestra Modifiche Git elenca i file con conflitti di unione. Per un file con conflitti di unione nel relativo contenuto, fare doppio clic sul file per aprirlo nell'editor di merge.

    Screenshot dei file con conflitti di unione nella finestra Modifiche Git di Visual Studio.

  3. Nell'editor di merge il riquadro In ingresso mostra la versione del file del ramo di origine, il riquadro Corrente mostra la versione del file del ramo di destinazione e il riquadro Risultato mostra il file di unione risultante. Per applicare modifiche specifiche al ramo di origine o di destinazione, selezionare la casella di controllo accanto alle righe in conflitto che si desidera mantenere. È anche possibile modificare direttamente il file di unione nel riquadro Risultati . Scegliere Accetta unione dopo aver risolto tutti i conflitti di unione nel file corrente. Ripetere questo passaggio per ogni file con conflitti di contenuto.

    Screenshot dell'editor di merge in Visual Studio.

  4. Per un file modificato in un ramo ed eliminato nell'altro, fare clic con il pulsante destro del mouse sul file e selezionare l'azione di ramo desiderata.

    Screenshot del menu di scelta rapida per un file in conflitto nella finestra Modifiche Git di Visual Studio.

  5. Nella finestra Modifiche Git immettere un messaggio di commit e scegliere Commit staged per completare l'unione, dopo aver risolto tutti i conflitti di unione per tutti i file.

    Screenshot del messaggio di commit e del pulsante Commit stagingd nella finestra Modifiche Git di Visual Studio.

Passaggi successivi