Strategie per la fusione di 1 anno di sviluppo in Visual Studio


32

Ho un cliente che ha insistito per mantenere il nostro nuovo sviluppo separato dalle filiali principali per tutto il 2016. Avevano 3-4 altri team che lavoravano sull'applicazione a varie capacità. Sono state apportate numerose e grandi modifiche (cambiando il modo in cui viene fatta l'iniezione di dipendenza, ripulendo il codice con ReSharper, ecc.). Ora è toccato a me fondere main nel nostro nuovo ramo di sviluppo per prepararci a spingere i nostri cambiamenti nella catena.

Sul mio pull di unione iniziale, TFS ha riportato ~ 6500 file con risoluzione dei conflitti. Alcuni di questi saranno facili, ma alcuni saranno molto più difficili (in particolare alcuni dei javascript, dei controller api e dei servizi che supportano questi controller).

C'è un approccio che posso adottare che mi semplificherà questo?

Per chiarire, ho espresso molte preoccupazioni con questo approccio più volte lungo la strada. Il cliente era ed è consapevole delle difficoltà con questo. Poiché hanno scelto di cortocircuitare il personale addetto al controllo qualità (1 tester per 4 sviluppatori, nessun test automatizzato, test di regressione piccoli), hanno insistito sul fatto che il nostro ramo fosse isolato dai cambiamenti nel ramo principale con la pretesa che ciò avrebbe ridotto la necessità del nostro tester per conoscere le modifiche apportate altrove.

Uno dei maggiori problemi qui è un aggiornamento alla versione angolare e ad alcuni altri software di terze parti - sfortunatamente non abbiamo trovato un buon modo per costruire questa soluzione fino a quando tutti i pezzi non saranno rimessi a posto.


63
No. Hai due rami separati che sono stati sviluppati attivamente per un anno. La fusione farà schifo.
17 del 26

2
Qual è l'entità delle modifiche apportate dal tuo team? Potrebbe essere più efficiente identificare tali modifiche e quindi riapplicarle manualmente alla base di codice principale corrente.
kdgregory,

2
È l'intero 2015 o 2016? Se è il 2015 ha 2 anni, il che significa che farà schifo doppio.
David dice di reintegrare Monica il

1
Perché il cliente si preoccupa se il lavoro che stai facendo per loro è su un ramo separato nel tuo sistema di controllo versione?
Ixrec

17
Qualunque cosa tu faccia, assicurati di fatturare ogni ora.
Sean McSomething il

Risposte:


37

Ci sarebbe stato un modo semplice che avrebbe tenuto separato il tuo nuovo sviluppo dal ramo principale senza portarti in questa sfortunata situazione: qualsiasi cambiamento dal tronco avrebbe dovuto essere unito al tuo ramo di sviluppo su base giornaliera . (Il tuo cliente era davvero così miope che non poteva prevedere che un giorno la tua filiale avrebbe dovuto essere rimessa sulla linea principale?)

Ad ogni modo, l'approccio migliore è l'IMHO che cerca di ripetere ciò che sarebbe dovuto accadere in prima persona:

  • identificare la semantica delle modifiche sulla riga principale per il giorno 1 dopo la creazione del ramo. Applicali alla tua base di codice attuale così come puoi. Se fosse un "cambiamento locale", dovrebbe essere semplice, se si trattasse di un "refactoring trasversale" come la ridenominazione di una classe ampiamente utilizzata, applicarlo in modo semanticamente equivalente all'attuale base di codice. Spero che durante quell'anno non siano state apportate modifiche contraddittorie trasversali alla base di codice sul "tuo" ramo, altrimenti questo può diventare un vero rompicapo
  • testare il risultato (ho già detto che hai bisogno di una buona suite di test per questa attività)? Correggi tutti i bug rilevati dal test
  • ora ripeti questo processo per le modifiche sulla riga principale per il giorno 2, quindi il giorno 3 e così via.

Ciò potrebbe funzionare quando i team obbedivano rigorosamente alle regole classiche del controllo della versione ("commetti solo stati compilabili, testati" e "controlla in anticipo e spesso").

Dopo 365 ripetizioni (o 250, se sei fortunato e puoi raggruppare il lavoro per i cambiamenti del fine settimana), avrai quasi finito (quasi, perché devi aggiungere il numero di cambiamenti che accadranno alla linea principale durante il periodo di integrazione ). Il passaggio finale sarà quello di unire nuovamente il ramo di sviluppo aggiornato nel trunk (in modo da non perdere la cronologia del trunk). Questo dovrebbe essere facile, perché tecnicamente dovrebbe essere solo una sostituzione dei file interessati.

E sì, sono serio, probabilmente non c'è scorciatoia per questo. Si potrebbe scoprire che le "porzioni quotidiane" a volte potrebbero essere troppo piccole, ma non me lo aspetto, immagino sia più probabile che le porzioni quotidiane possano rivelarsi troppo grandi. Spero che il tuo cliente ti paghi davvero bene per questo, e che questo è così costoso per lui che imparerà dal suo fallimento.

Vorrei aggiungere che puoi provarlo anche con i lati cambiati - reintegrando le modifiche dal tuo ramo in piccole porzioni alla linea principale. Questo potrebbe essere più semplice quando sul tuo ramo di sviluppo ci sono state molte meno modifiche rispetto al trunk, o la maggior parte delle modifiche sono avvenute in nuovi file di origine che attualmente non fanno parte del trunk. Si può vedere come un "porting" di una funzione da un prodotto A (il ramo di sviluppo) a un prodotto B leggermente diverso (stato attuale del trunk). Ma se la maggior parte delle rifatturazioni trasversali sono state eseguite sulla linea principale e influenzano il tuo nuovo codice (le 6500 collisioni di unione sembrano essere una prova per questo), potrebbe essere più semplice il modo in cui l'ho descritto per primo.


9
Se stai continuando lo sviluppo sul tronco durante la reintegrazione, ti suggerisco di ramificare prima la punta del tronco e sviluppare da quello. Altrimenti stai fondendo efficacemente passato e futuro contemporaneamente. Ma rimando a Doc Brown su qualsiasi discontinuità spazio-temporale, naturalmente.
radarbob,

1
@radarbob: ciò che suggerisci ha senso solo se l'OP si integra da dev a trunk, ma non quando decide di unire da trunk a Dev, come ho descritto prima. Se l'OP trasferisce le modifiche dal trunk al suo ramo di sviluppo giorno per giorno (a partire dalle modifiche 365 giorni fa), non importa se lo sviluppo sul trunk continua. Dovrà solo continuare questa tattica fino a raggiungere il presente (supponendo che possa integrare e testare i cambiamenti di quelle 3-4 squadre in un giorno in meno di un giorno).
Doc Brown,

Citazione: "Vorrei aggiungere che puoi provarlo anche con i lati scambiati - reintegrando le modifiche dal tuo ramo in fasci giornalieri alla linea principale. " Il mio senso spidey sta bruciando una miccia. Percepisco una potenziale cascata di "distorsione di risonanza armonica" con integrazioni di cambiamenti contrastanti.
radarbob,

Questo è un buon consiglio Vedi modifica per affrontare un paio di cose qui.
user258451

1
@ user258451: quindi c'erano diversi team di controllo qualità per il trunk e il nuovo ramo di sviluppo sul posto che non volevano parlare tra loro? Great Scott: - ((
Doc Brown

14

In quella fase della fusione direi che la fusione automatizzata può solo complicare il processo. Ho avuto problemi simili con le filiali che si sono discostate per oltre un anno e il metodo più efficace che ho è quello di fare quanto segue:

  • Prendi una copia dello stato originale non unito
  • Diff tra il non fuso e l'ultimo
  • Abbattere tutti gli elementi comuni
    • Ad esempio, fare tutte le modifiche al nome della funzione, quindi le modifiche ai parametri, ecc
    • Ignora gli spazi bianchi su diff se gli standard sono cambiati, altrimenti perderai molto tempo a contare gli spazi
  • Concentrati prima sulla funzionalità principale

Alla fine gli avvisi del compilatore e le differenze saranno i tuoi migliori amici, continua a utilizzare la differenza non unita per vedere esattamente cosa era diverso e continua ad andare avanti. Potrebbero esserci vari strumenti che potresti utilizzare per aiutarti, ma dipenderà da te scoprire quale sia il migliore.

La chiave è continuare.

Modificare:

Un avvertimento, questo approccio significherà che la cronologia del controllo versione verrebbe "corrotta", poiché si perderebbero le prove della fusione da ramo a ramo, così come la storia del ramo non unito.

Grazie ai commenti di "Jack Aidley" e "17 di 26"


1
Il problema principale con questo approccio è che distruggerà la registrazione delle modifiche rimaste nel sistema di controllo della versione.
Jack Aidley il

Essenzialmente, apportando tutte le stesse modifiche una seconda volta durante l'unione, avresti comunque un registro delle modifiche, sarebbe solo nell'ordine fatto nell'unione anziché nell'ordine in cui sono state fatte durante lo sviluppo. Non ideale, ma meglio di niente. Inoltre, avresti comunque lo stato originale non unito, se mantenuto nel controllo della versione.
Erdrik Ironrose,

Avresti un registro delle modifiche, ma non avresti prove storiche che le modifiche sono state unite da un ramo all'altro. Questo sarebbe un grosso problema in TFS, che offre solo i changeset non uniti tra cui scegliere quando si uniscono da un ramo all'altro.
17 del 26

@ 17of26 Anche se concordo sul fatto che è possibile ripristinare alcuni record di modifiche, 17 su 26 ha ragione sul fatto che questo record non sarà completo o accurato. Può darsi che questo approccio sia sufficientemente più semplice da rendere questa perdita di record un compromesso accettabile data la brutta situazione in cui si trovano ora. Tuttavia, penso che sia un importante svantaggio riconoscere indipendentemente da ciò che decidono.
Jack Aidley il

1
@Jack Aidley Sono assolutamente d'accordo sul fatto che sia piuttosto un problema, quindi ho aggiunto un po 'alla mia risposta per riflettere. Spero vada bene?
Erdrik Ironrose,

8

Qualche anno fa avevamo un cliente con gli stessi requisiti di separazione delle filiali. Così abbiamo fatto.

Non abbiamo mai unito il loro ramo indietro. Avevano una propria versione unica. Li abbiamo addebitati extra per le modifiche poiché essenzialmente avevamo due tronchi principali invece di 1 tronco principale e rami.

Abbiamo tentato di ricollegarci al bagagliaio ma dopo 2 settimane abbiamo deciso di abbandonare quello sforzo perché bruciava ore di tempo senza benefici tangibili.

Quindi, non ricollegarlo. In futuro, unire le correzioni critiche a quel ramo client in base alle esigenze e ogni miglioramento sarebbe una tantum specificamente addebitato a quel client.


Questa strategia è possibile solo se le diverse linee di sviluppo sono rivolte a clienti diversi. Oppure, se i casi d'uso in cui è coinvolto il prodotto consentono di utilizzare le due diverse linee di prodotti in parallelo, in modo non integrato. A mio avviso, l'OP descrive una situazione in cui la nuova linea di sviluppo è rivolta allo stesso cliente di quello che sta utilizzando il trunk, ed è poco chiaro se l'uso parallelo di due linee di prodotti potrebbe avere un senso per il suo caso.
Doc Brown,

1

Non sarà divertente, ma quanto sarà doloroso dipenderà dalla natura dei cambiamenti e da quanto siano isolati.

Ti suggerisco di provare a convergere i rami attraverso il refactoring il più possibile prima di effettuare una fusione effettiva.

Lo strumento di unione è un po 'stupido perché esamina solo le differenze testuali e non capisce il codice in alcun modo. Se il ramo principale ha cambiato il nome di una classe utilizzata in tutta l'applicazione e il ramo della funzione utilizza il vecchio nome in un nuovo codice, lo strumento di unione non capirà che anche il nome della classe dovrebbe essere modificato nel nuovo codice. Ma se si esegue un refactoring nel ramo B per rinominare la classe come nel ramo A funzionerà sia nel vecchio che nel nuovo codice e l'unione andrà senza intoppi.

In secondo luogo, è necessario verificare la localizzazione delle modifiche nel ramo di sviluppo. Se le modifiche nel ramo della funzione sono localizzate in alcune aree, non è necessario convergere il codice non interessato, è sufficiente copiare e sovrascrivere dal ramo principale.

Nelle aree di codice in cui ci sono state modifiche non banali su entrambi i rami, è necessario ispezionare attentamente il codice e decidere come riscrivere.

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.