Articles

Perché dovresti smettere di usare Git rebase

Posted by admin

Dopo aver usato Git per diversi anni, mi sono ritrovato a usare gradualmente comandi Git sempre più avanzati come parte del mio flusso di lavoro quotidiano. Subito dopo aver scoperto Git rebase, l’ho rapidamente incorporato nel mio flusso di lavoro quotidiano. Coloro che hanno familiarità con il rebasing sanno quanto sia potente uno strumento e quanto sia allettante usarlo tutto il tempo. Tuttavia, ho presto scoperto che rebasing presenta alcune sfide che non sono evidenti quando si inizia a farlo. Prima di presentarli, ricapitolerò rapidamente le differenze tra fusione e rebasing.,

Consideriamo prima l’esempio di base in cui si desidera integrare un ramo di funzionalità con master. Con l’unione, creiamo un nuovo commit g che rappresenta l’unione tra i due rami. Il grafico di commit mostra chiaramente cosa è successo e possiamo vedere i contorni del grafico “traccia del treno” familiare da Git-repos più grandi.,

Example of merging

Alternatively, we could rebase before merging. The commits are removed and the feature branch is reset to master, after which the commits are re-applied on top of feature., Le differenze di questi commit riapplicati sono solitamente identiche alle loro controparti originali, ma hanno commit genitore diversi, e quindi chiavi SHA-1 diverse.

Esempio di riassegnazione

Ora abbiamo cambiato la base di commettere feature da b c, letteralmente ri-fondarlo., Merging feature to masteris now a fast-forward merge, because all commits on feature are direct descendants of master.

Example of fast-forward merging

Compared to the merge approach, the resulting history is linear with no divergent branches., La leggibilità migliorata è stata la ragione per cui preferivo rebasing rami prima della fusione, e mi aspetto che questo sia il caso anche per altri sviluppatori.

Tuttavia, questo approccio presenta alcune sfide che potrebbero non essere ovvie.

Considera il caso in cui una dipendenza ancora in uso sufeature è stata rimossa sumaster. Quandofeatureviene rebasato sumaster, il primo commit riapplicato interromperà la build, ma finché non ci sono conflitti di unione, il processo di rebase continuerà ininterrotto., L’errore dal primo commit rimarrà presente in tutti i commit successivi, risultando in una catena di commit interrotti.

Questo errore viene rilevato solo al termine del processo di rebase, e di solito viene risolto applicando un nuovo commit bugfix g in cima.,

Esempio di mancata riassegnazione

Se si ottiene conflitti durante la riassegnazione tuttavia, Git pausa sul conflitto di commit, che consente di risolvere il conflitto prima di procedere. Risolvere i conflitti nel mezzo del rebasing di una lunga catena di commit è spesso confuso, difficile da ottenere e un’altra fonte di potenziali errori.

L’introduzione di errori è più problematica quando accade durante il rebasing., In questo modo, vengono introdotti nuovi errori quando si riscrive la cronologia e possono mascherare bug originali introdotti quando la cronologia è stata scritta per la prima volta. In particolare, questo renderà più difficile l’uso di Git bisect, probabilmente lo strumento di debug più potente nella casella degli strumenti Git. Ad esempio, considera il seguente ramo di funzionalità. Diciamo che abbiamo introdotto un bug verso la fine del ramo.,

Un ramo con bug introdotti verso la fine

Si può non scoprire questo bug finché settimane dopo la diramazione è stata fusa per master. Per trovare il commit che ha introdotto il bug, potrebbe essere necessario cercare tra decine o centinaia di commit., Questo processo può essere automatizzato scrivendo uno script che verifica la presenza del bug ed eseguendolo automaticamente tramite Git bisect, usando il comando git bisect run <yourtest.sh>.

Bisect eseguirà una ricerca di bisezione attraverso la cronologia, identificando il commit che ha introdotto il bug. Nell’esempio mostrato di seguito, riesce a trovare il primo commit difettoso, poiché tutti i commit interrotti contengono il bug effettivo che stiamo cercando.,

Example of successfull Git bisect

On the other hand, if we’ve introduced additional broken commits during rebasing (here, d and e), bisect will run into trouble., In questo caso, speriamo che Git identifichi commitf come quello cattivo, ma identifica erroneamentedinvece, poiché contiene qualche altro errore che interrompe il test.

Esempio di un errore di Git bisect

Questo problema è più grande di quanto possa sembrare a prima vista.

Perché usiamo Git?, Perché è il nostro strumento più importante per rintracciare la fonte di bug nel nostro codice. Git è la nostra rete di sicurezza. Ridiscutendo, diamo a questa meno priorità, a favore del desiderio di realizzare una storia lineare.

Qualche tempo fa, ho dovuto bisect attraverso diverse centinaia di commit per rintracciare un bug nel nostro sistema. Il commit difettoso si trovava nel mezzo di una lunga catena di commit che non venivano compilati, a causa di un rebase difettoso eseguito da un collega. Questo errore inutile e totalmente evitabile mi ha portato a spendere quasi un giorno in più nel rintracciare il commit.,

Quindi, come possiamo evitare queste catene di commit interrotti durante il rebasing? Un approccio potrebbe essere quello di lasciare che il processo di rebase finisca, testare il codice per identificare eventuali bug e tornare indietro nella storia per correggere i bug in cui sono stati introdotti. A tal fine, potremmo usare rebasing interattivo.

Un altro approccio sarebbe quello di mettere in pausa Git durante ogni fase del processo di rebase, testare eventuali bug e correggerli immediatamente prima di procedere.

Questo è un processo ingombrante e soggetto a errori, e l’unica ragione per farlo sarebbe ottenere una cronologia lineare. C’è un modo più semplice e migliore?,

C’è; Git merge. È un processo semplice e in una sola fase, in cui tutti i conflitti vengono risolti in un singolo commit. Il commit di fusione risultante segna chiaramente il punto di integrazione tra le nostre filiali e la nostra storia descrive ciò che è realmente accaduto e quando è accaduto.

L’importanza di mantenere la vostra storia vera non deve essere sottovalutata. Con rebasing, stai mentendo a te stesso e alla tua squadra. Fingi che i commit siano stati scritti oggi, quando in realtà sono stati scritti ieri, sulla base di un altro commit., Hai preso i commit dal loro contesto originale, mascherando ciò che è realmente accaduto. Puoi essere sicuro che il codice si costruisce? Puoi essere sicuro che i messaggi di commit abbiano ancora senso? Si può credere che si sta pulendo e chiarire la vostra storia, ma il risultato può benissimo essere il contrario.

È impossibile dire quali errori e sfide il futuro comporta per la tua base di codice. Tuttavia, puoi essere certo che una storia vera sarà più utile di una riscritta (o falsa).

Leave A Comment