Come approccio a un'unione complicata

24

Ecco l'accordo, ho aderito a una nuova società e mi è stato chiesto di terminare il lavoro su una filiale che non è stata toccata da quasi un anno. Nel frattempo, il master branch è cresciuto con un ritmo costante. Idealmente vorrei unire tutte le modifiche dal ramo principale al ramo delle funzionalità e continuare il lavoro da lì, ma non sono troppo sicuro di come affrontarlo.

Come faccio a eseguire questa fusione in modo sicuro conservando le modifiche importanti su entrambi i lati del ramo?

    
posta Vlad Spreys 11.11.2015 - 05:06
fonte

6 risposte

27

Al centro, come combinare due (probabilmente non compatibili) parti di codice è un problema di sviluppo , non un controllo di versione . Il comando Git merge può aiutare in questo processo, ma dipende dalla forma del problema.

Confrontare prima entrambe le versioni con la base ha più senso. Questo ti darà un'idea della migliore strategia per portarlo avanti. Il tuo approccio potrebbe essere diverso in base alla natura e alla sovrapposizione delle modifiche in ciascun ramo.

Immagina lo scenario ideale: scopriresti che il ramo principale e il ramo di funzionalità modificano ciascuna solo parti del codice che si escludono a vicenda, in modo che tu possa solo impegnare tutte le modifiche ed essere buono per andare.

Naturalmente, questo non sarà quasi certamente il caso, ma la domanda è: quanto sarà lontano da questo scenario ideale? cioè quanto sono mescolati i cambiamenti?

Inoltre, quanto era maturo il vecchio ramo delle funzionalità? Era in buono stato di funzionamento o no (o sconosciuto)? Quanto è stata completata la funzione?

Se il codice rilevante nel ramo principale è cambiato molto nell'ultimo anno, o la funzionalità non è in uno stato molto maturo, potrei prendere in considerazione la creazione di un nuovo fork più recente e incorporare manualmente la vecchia funzione di nuovo. Ciò ti consentirà di adottare un approccio incrementale per farlo funzionare.

Se fai una confusa fusione di un sacco di codice e non funziona, sarà piuttosto difficile eseguire il debug. Se il ramo principale è cambiato molto nell'ultimo anno, il design principale potrebbero essere necessarie modifiche alla funzionalità per farlo funzionare. Non sarebbe opportuno apportare queste modifiche tramite "risolvere i conflitti", poiché ciò richiederebbe apportare tutte le modifiche contemporaneamente e sperare che funzioni. Questo problema sarebbe aggravato dalla possibilità di bug nel vecchio ramo parzialmente finito.

    
risposta data 11.11.2015 - 07:07
fonte
17

Nella mia esperienza git limitata posso dire che a volte è più veloce riavviare nuovamente il ramo di funzione se il master è andato troppo lontano dal punto di stacco.

L'unione di due rami senza conoscere la storia del codice (dato che hai appena aderito al progetto) è davvero difficile, e scommetto che anche uno sviluppatore che ha seguito il progetto fin dall'inizio avrebbe probabilmente commesso degli errori nella fusione .

Questo ha ovviamente senso se il ramo della funzione non è enorme, ma potresti semplicemente mantenere il vecchio ramo della funzione aperto, di nuovo ramo da master e manualmente reintrodurre le modifiche che compongono questa funzione. So che è l'approccio più manuale, ma ti consente di avere il controllo completo in caso di codice mancante o spostato.

Associare la programmazione con un senior in questo caso sarebbe il migliore dei casi, aiutandoti a conoscere meglio il codice.
Potrebbe anche rivelarsi più veloce, se si tiene conto dei conflitti di fusione e del tempo di test!

Suppongo che almeno provare a fare un'unione sia ovviamente la cosa migliore da fare. Se fallisce o risulta essere troppo difficile, prova a selezionare la ciliegia, se ciò va storto vai nel modo manuale.

    
risposta data 11.11.2015 - 09:36
fonte
16

git-imerge è progettato esattamente per questo scopo. È uno strumento git che fornisce un metodo per l'unione incrementale . Unendo in modo incrementale, devi solo gestire le collisioni tra due versioni, mai più. Inoltre, un numero molto maggiore di unioni può essere eseguito automaticamente in quanto i singoli changeset sono più piccoli.

    
risposta data 11.11.2015 - 14:23
fonte
6

Cercare di unire la testata principale su un ramo vecchio di un anno può essere un esercizio di frustrazioni e approfondire l'ammaccatura sulla scrivania con la fronte.

La linea principale non è arrivata dove è in un colpo solo nel corso dei mesi. Anch'esso ha avuto sviluppo e rilasci. Cercare di aggiornare tutto in una fusione monolitica può essere travolgente.

Al contrario, iniziare dalla fusione dalla prima feature riattaccare alla linea principale dopo la divisione del ramo non aggiornato. Ottieni che unisci lavorando. Quindi la prossima funzionalità si unisce. E così via. Molte di queste funzioni si uniranno senza conflitti. È comunque importante assicurarsi che la funzionalità corrente del ramo non aggiornato rimanga compatibile con la direzione in cui la linea principale è andata.

Potresti voler diramarti dal capo del ramo inattivo per il ruolo di fusione in altre modifiche. Questo è più che altro per assicurarsi che il commit e la cronologia quando qualcuno lo guarda indietro è chiaro e comunica quale sia il ruolo e la politica di ogni ramo. Il ramo obsoleto era un ramo di funzionalità. Quello da cui stai lavorando è un ramo di accumulazione e riconciliazione.

Molto di questo sarà più facile se le vecchie funzionalità o rami di rilascio esistono ancora là fuori e sono facilmente accessibili (alcuni luoghi hanno una politica di ripulire i nomi dei rami più vecchi di qualche data in modo che l'elenco dei rami non sia 'travolgente).

La cosa importante in tutto questo è assicurarsi di testare e correggere dopo aver unito con successo ciascuna parte della cronologia principale. Anche se qualcosa potrebbe fondersi senza conflitti, ciò significa semplicemente che il codice non è in conflitto. Se il modo in cui è stata eseguita l'accesso alla funzione obsoleta è stato deprecato o rimosso, potrebbe essere necessario apportare delle correzioni dopo l'unione riuscita.

Per inciso, questo vale anche per altri sistemi di controllo delle versioni. Occasionalmente ho avuto bisogno di unire un gruppo specifico di commit svn in un ramo (cherry picking) per una funzione, correggere il ramo per lavorare con quella funzionalità, e quindi unire il prossimo gruppo di commit svn piuttosto che fare solo un svn all'ingrosso unire.

Mentre un può fare un git cherry-pick qui, e permette di inserire commit specifici , questo ha alcuni svantaggi che possono complicare il processo. Il cherry pick non mostrerà informazioni sul commit scelto (puoi aggiungerlo al messaggio di commit). Ciò rende più efficace il monitoraggio dei commit nella cronologia.

Inoltre, significa che non si sta riproducendo in modo efficace il master sul ramo stantio: si selezioneranno funzionalità eventualmente incomplete e tali funzionalità potrebbero non essere riprodotte correttamente.

Il motivo principale per cui unire dai commit storici al master sul branch stantio è essere in grado di mantenere il, chiamiamolo "history history" del branch stantio in uno stato che tu può ragionare. È possibile vedere chiaramente le unioni dalla cronologia sul ramo obsoleto e le correzioni per reintegrare la funzionalità. Le funzionalità vengono aggiunte nello stesso ordine in cui erano da padroneggiare. E quando hai finito, e finalmente fai la fusione dal capo del master sul ramo stantio, sai che tutto è stato unito e non ti manca nessuna commit .

    
risposta data 11.11.2015 - 17:15
fonte
1

Passaggio 1. Informazioni sul codice, analisi della sua architettura e delle modifiche apportate su entrambi i rami dall'ultimo antenato comune.

Passaggio 2. Se la funzione appare ampiamente indipendente e tocca principalmente aree di codice diverse, unire, correggere conflitti, testare, correggere ecc. Il percorso è felice, sei praticamente pronto. Altrimenti vai al passaggio 3

Passaggio 3. Analizzare le aree di conflitto, comprendere l'impatto funzionale e le ragioni in dettaglio. Ci potrebbero facilmente essere conflitti nelle esigenze aziendali che vengono alla luce qui. Discutere con BA, altri sviluppatori come appropriato. Dai un'occhiata alla complessità che comporta la risoluzione dell'interferenza.

Passaggio 4. Alla luce di quanto sopra, decidi se puntare a unire / selezionare in modo selettivo / anche tagliare solo le parti che non sono in conflitto e riscrivere i pezzi in conflitto, OPPURE se riscrivere l'intero funzionalità da zero.

    
risposta data 18.11.2015 - 23:59
fonte
0

1. Passa al ramo che viene utilizzato come principale ramo di sviluppo / rilascio.

Questo è il ramo che contiene le ultime modifiche al sistema. Può essere master , core , dev , dipende dalla società. Nel tuo caso è probabilmente master direttamente.

git checkout master
git pull

Apri per assicurarti di avere l'ultima versione del ramo di sviluppo principale acquisita.

2. Esegui il checkout e tira il ramo che contiene il lavoro che dovresti terminare.

Fai in modo di assicurarti di avere gli ultimi contenuti del ramo. Controllandolo direttamente, senza prima crearlo localmente, assicurati di non avere i nuovi contenuti da master (o il ramo dev principale rispettivamente).

git checkout <name of the obsolete branch>
git pull origin <name of the obsolete branch>

3. Unisci il ramo di sviluppo principale al ramo obsoleto.

Before running the following command, make sure, either by typing git branch or git status that you are on the obsolete branch.

git merge master

Il comando git merge proverà a unire i contenuti dal ramo specificato, in questo caso master , al ramo al quale sei attualmente.

L'enfasi su proverà a . Potrebbero esserci conflitti di fusione, che dovranno essere risolti solo da te e da te.

4. Risolvi i conflitti di unione, esegui il commit e esegui la correzione del conflitto

Dopo aver risolto il conflitto di unione in tutti i file in cui ci sono, stage, commit e spingere la risoluzione del conflitto a origin .

git add .
git commit -m "fixed the merge conflict from the past year to update the branch"
git push

Generalmente puoi chiamare git add . per mettere in scena tutti i file per il commit. Quando si affrontano conflitti di unione, si desidera aggiornare tutti i file necessari.

Nota aggiuntiva

Risolvere un conflitto di unione può essere un lavoro noioso. Soprattutto se sei nuovo in un'azienda. Potresti anche non avere le conoscenze adeguate per risolvere tutti i conflitti di merge da solo, ancora.

Prenditi il tuo tempo per esaminare attentamente tutti i conflitti che si sono verificati e correggerli in modo appropriato, prima di continuare il tuo lavoro.

Può succedere così, si inizia a lavorare su un ramo vecchio di un anno, si fondono lo stato di sviluppo attuale e non si verificano affatto conflitti di fusione.

Questo accade quando anche il sistema è cambiato molto nell'anno, nessuno ha toccato i file che sono stati effettivamente modificati nel ramo di un anno.

    
risposta data 11.11.2015 - 09:28
fonte

Leggi altre domande sui tag