2012-03-08 17 views
36

La nostra squadra al lavoro ha adottato con entusiasmo un flusso di lavoro di rebase, ma forse ci siamo un po 'trascinati, che è il punto di questa domanda: tu sei il giudice.Flussi di lavoro Git: riconduzione di rami pubblicati/condivisi

Utilizzare pull --rebase è un gioco da ragazzi per me ora. Tuttavia, disponiamo anche di ampi rami di funzionalità su cui lavorano più persone. Periodicamente, vogliamo apportare cambiamenti che stanno accadendo sul master. La saggezza convenzionale ci farebbe fondere perché è un ramo condiviso. Tuttavia, nella nostra ossessione di rebase, abbiamo deciso di ricollocare quei rami. Certo che richiede la collaborazione di tutti. Il flusso di lavoro è simile al seguente:

1) Il rebaser si coordina con tutti per assicurarsi che siano tutti registrati e spinti sul ramo della funzione, quindi chiede loro di non eseguire più operazioni su quel ramo finché non ottengono il tutto chiaro.

2) La rebaser rebases il ramo di caratteristica sulla matrice, cancella il ramo remoto funzione (push origin git: funzione), e quindi spinge il nuovo ramo della funzione ricalcolato (funzione push origin git)

3) L' rebaser ha recuperato tutti, che aggiorna il loro ramo di funzionalità, quindi elimina il loro ramo di funzione locale (funzione di git-ramo-D), quindi crea un nuovo ramo di funzione locale che tiene traccia del ramo di funzione remoto. Tutti quindi ottengono il tutto chiaro.

Questo flusso di lavoro funziona, in parte perché siamo un piccolo gruppo e le interruzioni di lavoro sono ridotte. Tuttavia, temo che stiamo imparando le cattive abitudini di Git (ridefinendo un ramo condiviso), o che il flusso di lavoro non si adatta bene.

Sul lato positivo, la nostra storia del repository è adorabile.

Cosa ne pensi, Git guru? Stiamo giocando con il fuoco o dondolando un flusso di lavoro ragionevole?

UPDATE:

E 'due anni da quando ho inizialmente fatto la domanda, e il mio è il nostro flusso di lavoro cambiato da allora. Facciamo ancora regolarmente git pull --rebase, quindi non è cambiato. È un buon senso e previene tutte le mini-unioni antiestetiche e confuse. (Manteniamo per lo più sincronizzati, quindi il costo è limitato a git pull --rebase).

A parte questo, tuttavia, e l'occasionale azione eroica per correggere un errore, siamo sopra la nostra follia rebase. L'unione ha senso per la maggior parte del tempo. Tuttavia, la fusione sfrenata è problematica e contribuisce alla storia confusa e caotica che mi preoccupava circa due anni fa.

La nostra soluzione ha diverse componenti:

filiale
  • Il master è "incontaminata". I rami dell'argomento vengono uniti e una volta eseguiti, il ramo dell'argomento viene ritirato. In altre parole, unire un ramo argomento significa che il lavoro è pronto per la produzione e ora fa parte del ramo principale. Guardando la nostra cronologia delle versioni, è molto chiaro cosa sta succedendo: i rami dell'argomento si fondono in master, e basta.

  • Utilizziamo i rami di integrazione monouso quando necessario. Ad esempio, se abbiamo i rami argomento A, B e C e nessuno di questi è pronto per l'integrazione in master, ma dobbiamo testarli insieme, creiamo solo un ramo QA (di solito fuori dal master) e quindi uniamo A, B e C in. A un certo punto, il ramo QA viene eliminato o riutilizzato.Il punto è che non è destinato a essere permanente in alcun modo, e non ha le stesse restrizioni del ramo principale (puoi unirmi ai rami dell'argomento tutte le volte che vuoi). Se la cronologia diventa troppo confusa, puoi semplicemente eliminare il ramo QA e ricominciare da capo (un approccio che abbiamo trovato molto naturale).

  • In caso di unione, sempre utilizzare git merge --no-ff. Questo è un così straordinario capovolgimento dalla nostra ossessione "storia di commit lineare" di due anni fa che merita un commento. Ora che ci siamo rilassati di una cronologia di commit lineare e abbiamo visto che le fusioni sono buone e utili, abbiamo iniziato a fare affidamento sui rami di argomento filiali effettive fuori dal master, non solo una serie di commit che alla fine diventa uno con il maestro git merge --no-ff assicura che ci sia sempre un commit di unione, anche quando non è necessario.

  • Abbiamo una convenzione ben conosciuta per messaggi di commit e filiali e, soprattutto, incrocia riferimenti al nostro sistema di tracciamento dei problemi. Il nostro sistema di tracciamento dei problemi utilizza numeri di numeri numerici e, per qualsiasi funzione (o difetto), abbiamo un numero di rilascio (1234, ad esempio). Se stai lavorando su questo problema, devi creare un ramo _1234 e avviare ogni messaggio di commit con "_1234: doing blah blah". Può sembrare un po 'ossessivo, ma ha davvero funzionato bene per noi e ha ridotto/eliminato significativamente la confusione.

  • Utilizzare un wrapper git per incoraggiare l'adesione del flusso di lavoro. Questo è qualcosa a cui stiamo lavorando al momento, ma ci siamo resi conto che è assolutamente necessario prevenire errori semplici e comprensibili, come il dirottamento di una cosa sbagliata (di recente abbiamo avuto un disastro completo quando uno sviluppatore ha creato un ramo di argomento da un dispositivo monouso Succursale QA: il ramo argomento è stato approvato per la pubblicazione, è stato unito in ... e un gruppo di changer che non è stato approvato per l'attivazione. Il nostro wrapper git richiederà la conferma ogni volta che si fa qualcosa di insolito (come la creazione di un ramo diverso da quello principale, creando un ramo non denominato _NNNN, facendo un commit che non inizia con _NNNN, ecc.). Occasionalmente, abbiamo bisogno di fare queste cose, quindi il wrapper non impedisce , ma impedisce alle persone di fare accidentalmente qualcosa che non dovrebbero.

+4

Penso che sia troppo. Se il tuo ramo delle funzionalità è così longevo, dovresti fare unioni. Altrimenti finirai con tutte le tue passate commesse dal master fino al capo del tuo ramo delle funzionalità senza aver eseguito test su di loro. La tua storia finisce anche per non essere molto rappresentativa di ciò che è realmente accaduto. –

+1

super domanda. sono nella stessa barca – CleanBold

+3

Sono passati circa 2 anni da quando ho chiesto ... tempo per un aggiornamento! Aggiornerò la domanda –

risposta

23

Sembra molto complicato e non si adatta bene. Probabilmente è molto più semplice solo unire periodicamente lo master nel ramo delle funzioni, e quindi quando arriva il momento di unire nuovamente il master, quindi, è possibile eseguire prima il rebase (rimuovere l'unione non necessaria intermedia) e unire nuovamente in master (presumibilmente con --no-ff per produrre un merge commit). Ciò richiede solo che una persona si occupi di rebase, e non devono fare alcun coordinamento perché nessun altro ha bisogno di aggiornare forzatamente nulla (perché, presumibilmente, il ramo verrà cancellato dopo essere stato unito, piuttosto che essere tenuto in giro uno stato riscritto). Potresti anche decidere di ignorare completamente il rebase e lasciare semplicemente le fusioni intermedie in atto, che riflettono più accuratamente il tuo flusso di lavoro di sviluppo e rimuovono il rischio di produrre commit che non vengono effettivamente creati.

+2

la risposta non sembra essere così chiara. – CleanBold

+0

È corretto che in questo caso, quali conflitti vengono risolti quando si esegue nuovamente la fusione del master nel ramo della funzione quando si esegue il rebasing? (Al contrario, vedo come si tratti di un flusso di lavoro molto conveniente se non ci si aspetta conflitti di fusione) – rethab

+0

@rethab: se si attiva rerere (consultare 'git help rerere'), potrebbe essere in grado di risolverli automaticamente, a seconda che possa identificare correttamente il conflitto come se fosse stato risolto in passato. –