2013-05-08 24 views
11

ho la git flusso di lavoro seguente:Lo schiacciamento si impegna in una pratica ottimale (per questo particolare flusso di lavoro)?

  1. Crea nuovo ramo di caratteristica
  2. lavoro sul ramo di caratteristica
  3. Commit spesso
  4. Una volta funzione è completa, si fondono in master ramo
  5. sciacquare e ripetere

Tuttavia, a volte, ho bisogno per ripristinare un'intera funzione dal master. Ciò potrebbe coinvolgere un sacco di revert ing. (Il motivo per cui ho bisogno di annullare una funzionalità è che ho un sito Web che funziona da un repository.In questo punto, utilizziamo uno script che distribuisce il sito sul nostro sito di produzione o sul sito di Staging. Non chiedere, è proprio quello che mi è stato dato per lavorare. A volte, sto lavorando a qualcosa che ho messo in scena, ma poi è necessario apportare un cambiamento immediato, quindi avevo bisogno di un modo per tirare le mie modifiche in ordine per pulire il repository)

Sto pensando che il modo più semplice per farlo è se ogni ramo di funzionalità ha un solo commit. Quindi potrei revert che commette. Quindi, naturalmente, sto pensando di schiacciare tutti i commit di un ramo di funzionalità in uno, prima di unirlo a master.

Così ora il mio flusso di lavoro sarà simile:

  1. Crea nuovo ramo di caratteristica
  2. lavoro sul ramo di caratteristica
  3. Commit spesso
  4. Una volta caratteristica è completa git rebase -i HEAD ~ number_of_commits (o se la filiale remota è disponibile, origine/funzione_branco)

C'è qualche problema con questa logica? Va contro le migliori pratiche? Ho fatto alcuni test e l'intero flusso di lavoro sembra funzionare senza intoppi e risolve il mio problema, ma volevo gestire l'idea con altri (più intelligenti) Git-ers per vedere se c'è qualcosa di sbagliato in questo.

Grazie!

+1

Hai esaminato 'git merge --squash'? Qualche ragione particolare per cui hai scelto 'rebase' invece di usare' squash merge'? Non avresti una cronologia lineare quando esegui un 'unione', ma i commit nel ramo della funzione avranno comunque una cronologia lineare e avresti solo una fusione. – Tuxdude

+0

Ho appena esaminato quello per il mio scenario. Molto bella. Non so quale userei di più (forse 'rebase' dato che butto via questi rami un po 'spesso), ma avere la storia sul mio ramo delle funzionalità è una cosa carina da avere. Grazie per l'aiuto! –

+1

@Tuxdude: prendi in considerazione una risposta. Probabilmente * è * la risposta. – sleske

risposta

12

Si dovrebbe cercare di sfruttare la capacità di fusione dello squash di git, ad esempio git merge --squash, in modo da non riscrivere la storia inutilmente.

Entrambe git merge --squash e git rebase --interactive possono essere utilizzate per produrre un commit schiacciato con lo stesso albero di lavoro risultante, ma sono intesi per servire 2 scopi completamente diversi.Alla fine il tuo albero finisce per sembrare diverso in entrambi i casi.

albero iniziale:

a -- b -- c -- d master 
     \ 
     \-- e -- f feature1 

Dopo git checkout master; git merge --squash feature1; git commit:

a -- b -- c -- d -- F master 
     \ 
     \-- e -- f feature1 

Dopo git checkout master; git rebase -i feature1 e scegliendo di pick c e squash d:

a -- b   /-- F master 
     \  /
     \-- e -- f feature1 

Come si può vedere dalla differenza, si fa non riscrivere la storia di qualsiasi ramo quando si utilizza git merge --squash ma si finisce per riscrivere la cronologia di master quando si utilizza git rebase -i.

Si noti inoltre che i commit effettivi (per quelli che sono stati schiacciati) sarebbero presenti nella cronologia git in entrambi i casi, solo fino a quando si dispone di un riferimento di ramo o tag attraverso il quale tali commit sono raggiungibili.

In altre parole, nell'esempio di cui sopra, se si elimina feature1 dopo aver fatto merge --squash, non sarebbe in grado di visualizzare in realtà i commit e o f in futuro (soprattutto dopo i 90 giorni reflog periodo). Lo stesso vale per i commit c e d nell'esempio rebase.

+0

Grazie per l'ottima spiegazione! –

3

Uno svantaggio specifico del tuo approccio è che riduce drasticamente l'utilità di git bisect nel rintracciare i bug nel tuo codice.

Detto questo, se vi trovate tornando un'intera funzione abbastanza spesso al punto in cui siete alla ricerca di modi per ottimizzare questo processo, si consiglia di chiedersi se si sta fondendosi in master troppo in fretta. Si consiglia di prendere in considerazione l'utilizzo di più rami di lunga durata per impostare un flusso di lavoro adatto al proprio progetto.

+0

La ragione di ciò è che ho un sito web che funziona su un repository. Da lì, usiamo uno script che distribuisce il sito al nostro sito di produzione o al sito di Staging. Entrambi sono fatti dal nostro ramo "master". (Non chiedere, è proprio quello che mi è stato dato per lavorare.) A volte, sto lavorando a qualcosa che ho messo in scena, ma poi è necessario apportare un cambiamento immediato, quindi avevo bisogno di un modo per tirare le mie modifiche per pulire il repository. –

+0

Se possibile, proverei a modificare lo script per distribuire un ramo diverso su Staging (o, idealmente, consentire la distribuzione di rami arbitrari su entrambi i siti). Ma se non puoi, allora il tuo approccio proposto sembra ragionevole. –

+0

Sì, ci sto lavorando con il nostro team, ma per il momento stavo per vedere se c'è un buon modo per farlo. Grazie per l'aiuto! –