La fusione in avanti veloce ha senso per i rami di breve durata, ma in una storia più complessa , la fusione in avanti non veloce può rendere la storia più facile da capire e rendere più semplice il ripristino di un gruppo di commit.
Avvertenza : l' avanzamento non rapido ha anche potenziali effetti collaterali. Si prega di rivedere https://sandofsky.com/blog/git-workflow.html , evitare il "no-ff" con i suoi "commit checkpoint" che rompono il bisect o la colpa e valutare attentamente se dovrebbe essere l'approccio predefinito per master
.
(Da nvie.com , Vincent Driessen , pubblica " Un modello di ramificazione Git di successo ")
Incorporando una funzionalità finita su sviluppo
Le funzionalità finite possono essere unite nel ramo di sviluppo per aggiungerle alla prossima versione:
$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop
Il --no-ff
flag fa sì che l'unione crei sempre un nuovo oggetto commit, anche se l'unione potrebbe essere eseguita con un avanzamento veloce. Ciò evita di perdere informazioni sull'esistenza storica di un ramo di funzionalità e raggruppa tutti i commit che insieme hanno aggiunto la funzionalità.
Jakub Narębski menziona anche la configurazionemerge.ff
:
Per impostazione predefinita, Git non crea un commit di unione extra quando si unisce un commit che è un discendente del commit corrente. Invece, la punta del ramo corrente viene fatta avanzare rapidamente.
Se impostato su false
, questa variabile dice a Git di creare un commit di unione extra in tal caso (equivalente a dare l' --no-ff
opzione dalla riga di comando).
Se impostato su ' only
', sono consentite solo tali fusioni di avanzamento rapido (equivalenti a fornire l' --ff-only
opzione dalla riga di comando).
L'avanzamento rapido è l'impostazione predefinita perché:
- i rami di breve durata sono molto facili da creare e utilizzare in Git
- I rami di breve durata spesso isolano molti commit che possono essere riorganizzati liberamente all'interno di quel ramo
- tali commit fanno effettivamente parte del ramo principale: una volta riorganizzato, il ramo principale viene fatto avanzare rapidamente per includerli.
Ma se prevedi un flusso di lavoro iterativo su un argomento / ramo di funzionalità (ovvero, unisco, torno a questo ramo di funzionalità e aggiungo altri commit), quindi è utile includere solo l'unione nel ramo principale, anziché tutti i commit intermedi del ramo funzione.
In questo caso, puoi finire per impostare questo tipo di file di configurazione :
[branch "master"]
# This is the list of cmdline options that should be added to git-merge
# when I merge commits into the master branch.
# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.
# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.
mergeoptions = --no-commit --no-ff
L'OP aggiunge nei commenti:
Vedo un senso nell'avanzamento rapido per i rami [di breve durata], ma renderlo l'azione predefinita significa che git presume che tu abbia spesso rami [di breve durata]. Ragionevole?
Jefromi risponde:
Penso che la durata delle filiali vari notevolmente da utente a utente. Tra gli utenti esperti, tuttavia, c'è probabilmente la tendenza ad avere filiali molto più di breve durata.
Per me, un ramo di breve durata è quello che creo per rendere più facile una certa operazione (rebasing, probabile o patching e test rapidi), e quindi eliminare immediatamente una volta terminato.
Ciò significa che probabilmente dovrebbe essere assorbito nel ramo dell'argomento da cui è stato biforcato e il ramo dell'argomento verrà unito come un ramo. Nessuno ha bisogno di sapere cosa ho fatto internamente al fine di creare la serie di commit implementando quella determinata funzionalità.
Più in generale, aggiungo:
dipende davvero dal flusso di lavoro di sviluppo :
- se è lineare, un ramo ha senso.
- Se è necessario isolare le funzionalità e lavorarci per un lungo periodo di tempo e unirle ripetutamente, diversi rami hanno senso.
Vedi " Quando dovresti diramare? "
In realtà, quando si considera il modello di ramo Mercurial, è al suo interno un ramo per repository (anche se è possibile creare teste anonime, segnalibri e persino rami con nome )
Vedi "Git e Mercurial - Confronta e Contrasto" .
Mercurial, per impostazione predefinita, utilizza codeline leggere anonime, che nella sua terminologia sono chiamate "teste".
Git utilizza rami con nome leggero, con mappatura iniettiva per mappare i nomi dei rami nel repository remoto ai nomi dei rami di tracciamento remoto.
Git "ti costringe" a nominare i rami (beh, ad eccezione di un singolo ramo senza nome, che è una situazione chiamata " HEAD distaccato "), ma penso che funzioni meglio con flussi di lavoro pesanti come il flusso di lavoro dei rami dell'argomento, il che significa più rami in un unico paradigma di repository.
no-ff
" con i suoi "punti di arresto" che interrompono il bisect o la colpa.