Lasciami rispondere ai tuoi punti direttamente e chiaramente:
Il nostro problema riguarda i sidebranch a lungo termine, il tipo in cui alcune persone lavorano in un sidebranch che si divide dal master, ci sviluppiamo per alcuni mesi e quando raggiungiamo un traguardo sincronizziamo i due.
Di solito non vuoi lasciare i tuoi rami non sincronizzati per mesi.
Il ramo delle funzionalità si è ramificato in base al flusso di lavoro; chiamiamolo master
per semplicità. Ora, ogni volta che ti impegni a padroneggiare, puoi e dovresti git checkout long_running_feature ; git rebase master
. Ciò significa che, per progettazione, i tuoi rami sono sempre sincronizzati.
git rebase
è anche la cosa giusta da fare qui. Non è un hack o qualcosa di strano o pericoloso, ma completamente naturale. Si perde un po 'di informazioni, che è il "compleanno" del ramo delle funzionalità, ma il gioco è fatto. Se qualcuno lo trova importante, potrebbe essere fornito salvandolo da qualche altra parte (nel sistema di biglietteria o, se necessario, in un git tag
...).
Ora, IMHO, il modo naturale di gestirlo è, schiacciare il sidebranch in un unico commit.
No, non lo vuoi assolutamente, vuoi un commit di unione. Un commit di unione è anche un "commit singolo". In qualche modo, non inserisce tutti i singoli commit di ramo "in" master. È un unico commit con due genitori: la master
testa e la testa del ramo al momento della fusione.
Assicurati di specificare l' --no-ff
opzione, ovviamente; la fusione senza --no-ff
, nel tuo scenario, dovrebbe essere severamente vietata. Sfortunatamente, --no-ff
non è l'impostazione predefinita; ma credo che ci sia un'opzione che puoi impostare per renderlo tale. Vedi git help merge
cosa --no-ff
fa (in breve: attiva il comportamento che ho descritto nel paragrafo precedente), è cruciale.
non stiamo scaricando retroattivamente mesi di sviluppo parallelo nella storia del maestro.
Assolutamente no - non si sta mai scaricando qualcosa "nella storia" di un ramo, specialmente non con un commit di unione.
E se qualcuno ha bisogno di una migliore risoluzione per la storia del sidebranch, beh, ovviamente è ancora tutto lì - non è proprio nel master, è nel sidebranch.
Con un commit di unione, è ancora lì. Non nel maestro, ma nel fianco, chiaramente visibile come uno dei genitori della fusione commette, e mantenuto per l'eternità, come dovrebbe essere.
Vedi cosa ho fatto? Tutte le cose che descrivi per il tuo commit di squash sono proprio lì con il --no-ff
commit di merge .
Ecco il problema: lavoro esclusivamente con la riga di comando, ma il resto del mio team utilizza GUIS.
(Nota laterale: lavoro quasi esclusivamente anche con la riga di comando (beh, è una bugia, di solito uso emacs magit, ma questa è un'altra storia - se non sono in un posto conveniente con la mia configurazione individuale di emacs, preferisco il comando linea pure). Ma per favore fatevi un favore e provare almeno git gui
una volta. e ' così molto più efficiente per la raccolta di linee, fusti, ecc per l'aggiunta / rovina aggiunge.)
E ho scoperto che il GUIS non ha un'opzione ragionevole per visualizzare la cronologia di altri rami.
Questo perché ciò che stai cercando di fare è totalmente contrario allo spirito di git
. git
si basa dal nucleo su un "grafico aciclico diretto", il che significa che molte informazioni sono nella relazione genitore-figlio-commit delle commit. E, per le fusioni, ciò significa che la vera unione si impegna con due genitori e un figlio. Le GUI dei tuoi colleghi andranno bene non appena utilizzi i no-ff
commit di unione.
Quindi, se raggiungi un impegno di squash, dicendo "questo sviluppo schiacciato dal ramo XYZ", è un dolore enorme andare a vedere cosa c'è in XYZ.
Sì, ma questo non è un problema della GUI, ma del commit di squash. L'uso di uno squash significa lasciare la testa del ramo della funzione penzolante e creare un nuovo commit master
. Questo rompe la struttura su due livelli, creando un grande casino.
Quindi vogliono che queste grandi e lunghe catene di sviluppo si fondano, sempre con un impegno di unione.
E hanno assolutamente ragione. Ma essi non sono "fuse in ", sono solo uniti. Una fusione è una cosa veramente equilibrata, non ha un lato preferito che viene unito "nell'altro" ( git checkout A ; git merge B
è esattamente lo stesso che git checkout B ; git merge A
tranne per le differenze visive minori come i rami che vengono scambiati in git log
ecc.).
Non vogliono alcuna cronologia che non sia immediatamente accessibile dal ramo principale.
Che è completamente corretto. In un momento in cui non ci sono funzionalità non unite, avresti un singolo ramo master
con una ricca cronologia che incapsula tutte le linee di commit delle funzioni che ci sono mai state, tornando al git init
commit dall'inizio del tempo (nota che ho evitato espressamente di usare il termine " rami "nell'ultima parte di quel paragrafo perché la storia in quel momento non è più" rami ", anche se il grafico di commit sarebbe piuttosto ramoso).
Odio quell'idea;
Quindi provi un po 'di dolore, poiché stai lavorando contro lo strumento che stai utilizzando. L' git
approccio è molto elegante e potente, specialmente nell'area ramificata / di fusione; se lo fai bene (come accennato in precedenza, specialmente con --no-ff
) è a passi da gigante ad altri approcci (ad esempio, il pasticcio di sovversione di avere strutture di directory parallele per i rami).
significa un groviglio infinito e inarrivabile della storia dello sviluppo parallelo.
Infinito, parallelo - sì.
Innaffiabile, groviglio - no.
Ma non vedo quale alternativa abbiamo.
Perché non lavorare esattamente come l'inventore git
, i tuoi colleghi e il resto del mondo, ogni giorno?
Abbiamo qualche opzione qui oltre a fondere costantemente le sidebranches in master con merge-commit? Oppure, c'è una ragione per cui usare costantemente merge-commit non è così male come temo?
Nessuna altra opzione; non così male.