Dividere i progressi della codifica in commit significativi senza troppe spese generali


23

Quando lavoro su una correzione o una funzionalità, a volte inciampo su altri piccoli problemi che possono essere migliorati al volo in pochi secondi. Quando li eseguo immediatamente e quindi eseguo il commit della funzione / correzione finita, il commit include più di una cosa. Ad esempio "add feature X and code clean up"o "fix bug X and improved logging". Sarebbe meglio dividerlo in due commit. Nel caso in cui le due modifiche fossero avvenute nello stesso file, non posso semplicemente aggiungere un file, eseguire il commit, aggiungere l'altro e quindi eseguire nuovamente il commit. Quindi vedo le seguenti tre opzioni:

  1. Trascurare deliberatamente cose non correlate mentre si lavora su qualcosa.

  2. Copia il file con due modifiche, ripristinalo, includi una modifica, esegui il commit, includi l'altra modifica, esegui nuovamente il commit.

  3. Non modificare piccole cose non correlate, ma aggiungerle a una lista di cose da fare e farlo in un secondo momento.

Non mi piacciono davvero tutte e tre le opzioni, per i seguenti motivi:

  1. La qualità del codice può soffrire se non si risolvono piccoli problemi. E mi sento male se mi manca consapevolmente la possibilità di migliorare qualcosa senza troppi sforzi.

  2. Ciò aumenta il lavoro manuale ed è soggetto a errori.

  3. Questo va bene per todos non così piccoli, ma l'aggiunta di un piccolo elemento a un elenco di cose da fare e la rivisitazione in un secondo momento spesso richiede molto più tempo rispetto alla semplice correzione immediata.

Come gestite tali situazioni?


7
Git non ti consente di archiviare singole righe anziché interi file?
Kilian Foth,


Ne uso git add -pmolto che mi consente di selezionare in modo interattivo le parti dei file che voglio impegnare. Se la pulizia è sufficientemente separata, questo è facile da fare. Se la separazione è più difficile, commetto lo stato su un ramo temporaneo, quindi aggiungo manualmente le modifiche al mio ramo effettivo fino a quando non ci sono differenze nel ramo temporaneo. Ciò richiede molto più lavoro, ma mi consente di verificare che ogni commit funzioni da solo.
am

1
@gnat: ovviamente non è un duplicato. OP non sta chiedendo la dimensione corretta di un commit - vuole fare piccoli commit. Sta solo cercando un modo più efficiente per farlo.
Doc Brown,

2
@gnat: la risposta superiore non dice nulla (!) su come gestire le diverse modifiche in un file e come suddividerle in commit separati.
Doc Brown,

Risposte:


11

Penso che devi essere molto pragmatico durante la programmazione. Anche se potrebbe essere possibile formulare lo schema, il flusso di lavoro o l'implementazione perfetti, a volte è sufficiente eseguire il lavoro. Ecco cosa faccio:

Uso la capacità di git di mettere in scena / impegnare singoli blocchi e linee, quando possibile, per separare i cambiamenti non correlati, sebbene, a volte, ciò possa introdurre problemi temporanei, se la separazione non è stata eseguita correttamente. Poiché le modifiche saranno adiacenti, di solito non è un grosso problema, a meno che tu non abbia una politica di test di ogni singola modifica nella tua pipeline CI.

Quando la modifica non correlata è troppo grande, la inserirò in una lista di cose da fare e di solito la prenderò subito dopo, mentre è fresca nella mia mente. A volte potrebbero volerci un paio di giorni prima che io possa riprenderlo, dipende dal mio compito attuale e dal treno di pensieri. Occasionalmente inserirò semplicemente un TODO: accanto al codice offensivo, se non ho una buona soluzione pronta.

Capita che non sia pratico separare le cose e commetterò l'adattamento minore insieme al lavoro originale.

La dimensione della modifica è di solito il fattore determinante quando scelgo la strada da percorrere, ma alla fine preferirei di gran lunga ignorare una regola del flusso di lavoro, piuttosto che lasciare un odore alle spalle.


7

Il mio editor ha un plugin che rende estremamente semplice la messa in scena di singole parti di un file. Immagino che altri editor di programmatori potrebbero avere plugin simili, anche se puoi sempre farlo manualmente git add --patch | -p. Quindi uso git stash per salvare le altre modifiche per testare il mio piccolo commit in isolamento. Quindi, dopo essermi impegnata, faccio solo una git stash pope continuo da dove avevo interrotto. Questo è esattamente ciò per cui sono state progettate quelle funzionalità.


2

Il trucco non è quello di apportare modifiche a meno che non si sia preparati a compiere tutti gli sforzi che il cambiamento merita.

Quello che tendo a fare è aggiungere a un elenco di cose da fare (a volte aggiungendo un commento al codice, a volte in una nota su un ticket bug, e talvolta aggiornando il codice in un ramo separato sapendo che la correzione alla fine verrà unita). Se non esiste un ticket bug per un rollup di problemi di qualità minori, ne sollevo uno appositamente per questo, quindi io e tutti gli altri possiamo dire quale sia stata la ragione di tali modifiche al codice quando il ramo viene unito. Non mi limito mai ad apportare modifiche per divertirmi, tutto ottiene la tracciabilità, quindi i miei colleghi non saranno troppo sorpresi quando il codice cambia.

Quindi in breve: sì, trascurateli durante la programmazione. Se stai aggiungendo una funzione, non essere tentato di aggiungere 2 funzionalità, non importa quanto piccole. Se qualcuno decide di ripristinare il tuo ramo (perché la tua funzionalità non è più richiesta, per esempio), perderai anche tutti i tuoi mini-bugfix. Allo stesso modo, non si desidera effettuare una piccola "correzione" in alcuni codici critici che funzionavano correttamente.


1
Il PO non ha suggerito di unire due modifiche in un unico commit, al contrario.
Doc Brown,

1
@DocBrown suggerisce di mescolare 2 modifiche in un singolo ramo, che può essere disordinato per essere rimosso in seguito, anche se ovviamente non è così disordinato come 2 modifiche in un singolo commit.
gbjbaanb,

Ok, vedo cosa hai in mente con il tuo ultimo paragrafo.
Doc Brown,

2

Un'opzione che uso parecchio è quella di aggiungere TODOcommenti, quindi eseguire molti commit "parziali" frequenti, usando git add --patchper selezionare le parti rilevanti del file. Quindi utilizzare git rebase --interactiveper riordinare e unire i commit parziali nella funzione finale e i commit di correzione prima di inviarli.

Ciò mantiene pulito il commit principale e consente comunque di risolvere immediatamente altri problemi riscontrati.

Non c'è niente di sbagliato in un git rebasein questo contesto poiché stai solo riscrivendo gli commit locali.


1

Un'altra opzione potrebbe essere "git stash" delle modifiche attuali. Il flusso di lavoro sarebbe simile al seguente:

  1. Inizia ad apportare modifiche relative alla funzione A
  2. Scopri Bug B e decidi di risolverlo immediatamente
  3. Dalla riga di comando nel repository esegui git stash (Dopo di che il codice tornerà allo stato in cui si trovava prima di iniziare a lavorare sulla funzione A )
  4. A questo punto le modifiche non impegnate per la funzione A vengono archiviate nello "stash"
  5. Apportare le modifiche al codice necessarie per correggere il bug B ed eseguire nuovamente il commit nel repository
  6. Dalla riga di comando eseguito git stash pop
  7. Le modifiche non impegnate per la funzione A ora vengono eliminate e ripristinate nel codice in corso insieme alla correzione (già impegnata) per il bug B

Potresti espandere un po 'di più su come funzionerebbe questo flusso di lavoro? Qual è lo stato del repository in ciascun punto? Potresti guidare qualcuno attraverso il processo di utilizzo di git stash?

0

Separare (e impegnare) separatamente le modifiche relative alla correzione di bug. In Git Extensions, questo è estremamente facile da fare. Dalla riga di comando, penso che tu debba farlo git add -p.

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.