Strategie di unione e merge con squash

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

Quando si completa una richiesta pull, si unisce il ramo dell'argomento nel ramo predefinito, in genere main. Questa unione aggiunge i commit del ramo argomento al ramo main e crea un commit di merge per riconciliare eventuali conflitti tra il ramo predefinito e quello dell'argomento. I commenti e le discussioni nella richiesta pull forniscono un contesto aggiuntivo per le modifiche apportate nel ramo dell'argomento.

Esempio di un'unione regolare da una richiesta pull.

La cronologia dei commit nel main ramo (o in un altro ramo predefinito) non segue una linea retta, a causa della cronologia dei rami dell'argomento correlata. Man mano che un progetto aumenta, il numero di rami di argomento lavorato contemporaneamente aumenta, rendendo sempre più difficile seguire la cronologia dei rami predefinita.

Il ramo predefinito è una rappresentazione accurata della cronologia di ogni ramo di argomento, ma è difficile usare per rispondere a domande più ampie sullo sviluppo del progetto.

Unione di squash

L'unione di squash è un'opzione di unione che consente di condensare la cronologia Git dei rami di argomento quando si completa una richiesta pull. Anziché ogni commit nel ramo dell'argomento aggiunto alla cronologia del ramo predefinito, un merge di squash aggiunge tutte le modifiche apportate al file a un singolo nuovo commit nel ramo predefinito. Il commit di merge di squash non ha un riferimento al ramo dell'argomento e genererà un nuovo commit che contiene tutte le modifiche dal ramo dell'argomento. È inoltre consigliabile eliminare il ramo dell'argomento per evitare confusione.

Diagramma dell'unione di squash nelle richieste pull in Azure Repos.

Un modo semplice per pensare a questo è che l'unione di squash offre solo le modifiche al file e un'unione regolare fornisce le modifiche del file e la cronologia dei commit.

Come è utile un merge di squash?

L'unione di squash mantiene le cronologie dei rami predefinite pulite e facili da seguire senza richiedere modifiche al flusso di lavoro nel team. I collaboratori al ramo dell'argomento funzionano nel modo desiderato nel ramo dell'argomento e i rami predefiniti mantengono una cronologia lineare tramite l'uso di merge di squash. La cronologia dei commit di un main ramo aggiornato con merge squash ha un commit per ogni ramo unito. È possibile esaminare questa cronologia per scoprire esattamente quando è stato fatto il lavoro.

Considerazioni relative all'unione di squash

L'unione di squash riduce la cronologia delle modifiche nel ramo predefinito, quindi è importante collaborare con il team per decidere quando eseguire il merge di squash o quando si vuole mantenere la cronologia completa del commit di un ramo di argomento. Quando si esegue l'unione di squash, è consigliabile eliminare il ramo di origine. L'eliminazione del ramo di origine impedisce confusione perché il ramo dell'argomento stesso non ha un commit che lo unisce al ramo predefinito.

Completare le richieste pull con l'unione di squash

È possibile scegliere di eseguire il merge quando si completa una richiesta pull in Azure Repos.

Scegliere Commit squash in Tipo di merge nella finestra di dialogo Completa richiesta pull per unire il ramo dell'argomento.

Screenshot della chiusura di una richiesta pull con un merge di squash in Azure Repos.

Più basi di merge

La scheda File in una richiesta pull rileva le differenze in base a un confronto a tre lati. L'algoritmo tiene conto dell'ultimo commit nel ramo di destinazione, dell'ultimo commit nel ramo di origine e della relativa base di merge comune (ad esempio il miglior predecessore comune). L'algoritmo è un metodo rapido, conveniente e affidabile per rilevare le modifiche. Purtroppo, in alcuni casi, c'è più di una vera base. Nella maggior parte dei repository questa situazione è rara, ma in repository di grandi dimensioni con molti utenti attivi può essere comune. È possibile controllare manualmente se esistono più basi di unione tra i rami. A tale scopo, eseguire il git merge-base --all feature master comando . Azure DevOps rileva l'esistenza di più basi di merge per ogni richiesta pull. Quando vengono rilevati, Azure DevOps visualizza il messaggio "Sono state rilevate più basi di merge. L'elenco dei commit visualizzati potrebbe essere incompleto" per la richiesta pull. Mentre Azure DevOps esegue il rilevamento di più basi di merge, non verifica se la potenziale base di merge è già stata unita o meno. Tale controllo viene eseguito da git merge-base. Ecco perché Azure DevOps può visualizzare il messaggio anche quando git merge-base segnala una sola base di merge.

Nota

In caso di perdita di modifiche durante una revisione della richiesta pull, assicurarsi che più basi di merge non siano la causa radice.

Gli scenari seguenti vengono rilevati da Azure DevOps come più basi (le basi di merge sono indicate dal numero 1 e 2):

  • Unioni incrociate (note anche come intersezioni) tra rami diversi (segnalati da Azure DevOps e git merge-base)
---1---o---A
    \ /
     X
    / \
---2---o---o---B
  • Merge di un ramo ad altri due (segnalato da Azure DevOps, ma non da git merge-base che elimina la base di merge 2)
---1---o---o---o---A
    \         /
     \-------2
      \       \
       \---o---o---o---B
  • Gestione delle conseguenze del ripristino del ramo principale, ad esempio modificare il commit di merge
*   42bb2d2 (HEAD, A) Amended merge commit
|\  
| | *   67c9bb8 (other) Merge branch 'A' into B
| | |\  
| |/ /  
|/| /   
| |/    
| * fa78e32 add second commit
* | 15845c9 add first commit
|/  
* 6a52130 add init
  • Riutilizzo attivo dei rami di funzionalità
  • Altre manipolazioni non intuitive e contorte con reverts, cherry picks e merge

Il rilevamento di più basi di merge fa parte della consapevolezza della sicurezza. Se sono presenti più basi di unione, l'algoritmo diff del file per l'interfaccia utente potrebbe non rilevare correttamente le modifiche ai file, a seconda della base di unione scelta. Se i file nella richiesta pull hanno versioni diverse tra le basi di merge, si verifica un avviso di base di merge multiplo.

Per altri dettagli, vedere la documentazione ufficiale di Git.

Potenziali rischi per la sicurezza dell'unione da più basi

  • Un utente malintenzionato potrebbe abusare dell'algoritmo dell'interfaccia utente per eseguire il commit di modifiche dannose che non sono presenti nella richiesta pull.
  • Se le modifiche proposte nella richiesta pull sono già presenti nel ramo di destinazione, vengono visualizzate nella scheda File , ma potrebbero non attivare criteri di ramo mappati alle modifiche alle cartelle.
  • Due set di modifiche apportate agli stessi file da più basi di merge potrebbero non essere presenti nella richiesta pull. Questo caso potrebbe creare lacune logiche insidie.

Come risolvere il problema di più basi di merge

La presenza di più basi di merge non è necessariamente negativa, ma è consigliabile verificare che tutto sia corretto. Per eliminare più basi di merge, collegare i rami a un singolo predecessore comune ribasando il ramo sulla destinazione o unendo la destinazione nel ramo. Queste azioni vengono eliminate dal messaggio di avviso e consentono di verificare se le modifiche effettive sono appropriate.

Un approccio consiste nel reimpostare leggero e sfalsare lo stato di avanzamento prima di eseguire il rebasing o l'unione. È quindi possibile creare un nuovo ramo o ribasere uno vuoto e applicare le modifiche da un punto chiaro. Questo processo potrebbe richiedere un push forzato in remoto se le modifiche sono già presenti.

Come evitare il problema di più basi di merge

Di seguito sono riportati suggerimenti generali per evitare il problema di base per l'unione multipla:

  • Quando si prepara una richiesta pull, creare rami di funzionalità dalle versioni più recenti del ramo principale o di rilascio.
  • Evitare di creare rami che non provengono direttamente da rami stabili del repository, a meno che non sia necessario.

Operazioni da eseguire se viene nuovamente visualizzato il problema di più basi di merge

In repository di grandi dimensioni con molti collaboratori attivi, questo problema può essere particolarmente scomodo. Anche se si eliminano più basi tramite unione, la situazione potrebbe riapparire. Se qualcuno chiude una richiesta pull di lunga durata, può ricreare la situazione. Anche se i criteri di compilazione e i test sono in esecuzione, non è possibile completare la richiesta pull. La reimpostazione e l'avvio di un nuovo ramo potrebbero risultare utili. Se non viene modificato nulla, è probabile che le modifiche siano chiare, anche se la situazione si ripete.

Passaggi successivi