git pullsta probabilmente creando il commit. Se esegui un commit locale e poi esegui git pulldopo che qualcun altro ha inviato un commit al repository, Git scarica il commit dell'altro sviluppatore e lo unisce al tuo ramo locale.
Come evitare questi impegni di unione in futuro
Potresti usarlo git pull --rebaseper evitare che ciò accada in futuro, ma il rebasing ha i suoi pericoli e consiglio di evitarlo del pulltutto .
Invece, ti incoraggio a seguire questo schema di utilizzo:
# download the latest commits
git remote update -p
# update the local branch
git merge --ff-only @{u}
# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}
Spiegazione
git remote update -pscarica tutti i commit nei repository remoti e aggiorna i rami di tracciamento remoti (ad es origin/master.). NON tocca la directory di lavoro, l'indice o le filiali locali.
L' -pargomento elimina le diramazioni a monte. Pertanto, se ilfoo ramo viene eliminato nel originrepository, git remote update -peliminerà automaticamente il riferimento origin/foo.
git merge --ff-only @{u}dice a Git di unire il ramo a monte (l' @{u}argomento) nel ramo locale, ma solo se il ramo locale può essere "inoltrato rapidamente" al ramo a monte (in altre parole, se non è divergente).
git rebase -p @{u}sposta efficacemente i commit che hai fatto ma non hai ancora spinto in cima al ramo a monte, il che elimina la necessità di creare i commit di unione sciocchi che stai cercando di evitare. Ciò migliora la linearità della storia di sviluppo, facilitando la revisione.
L' -popzione dice a Git di conservare le fusioni. Questo impedisce a Git di linearizzare i commit in fase di riequilibrio. Questo è importante se, ad esempio, hai unito un ramo di funzionalità in master. Senza -p, ogni commit sul ramo della funzione verrebbe duplicatomaster come parte della linearizzazione effettuata da git rebase. Ciò renderebbe più difficile rivedere la storia dello sviluppo, non più facile.
Attenzione : git rebasepotrebbe non fare quello che ti aspetti che faccia, quindi rivedi i risultati prima di spingere. Per esempio:
git log --graph --oneline --decorate --date-order --color --boundary @{u}..
Preferisco questo approccio rispetto git pull --rebaseai seguenti motivi:
- Ti permette di vedere i commit a monte in entrata prima di modificare la cronologia per incorporarli.
- Ti consente di passare l' opzione
-p( --preserve-merges) a git rebasenel caso in cui sia necessario rifare una fusione intenzionale (ad esempio, l'unione di un ramo di funzionalità già inserito in master).
Stenografia: git upinvece digit pull
Per semplificare l'esecuzione di quanto sopra, ti consiglio di creare un alias chiamato up:
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
Ora tutto ciò che devi fare per aggiornare il tuo ramo è eseguire:
git up
invece di git pull. Se ricevi un errore perché il tuo ramo locale si è discostato dal ramo a monte, questo è il tuo spunto per ribasare.
Perché no git pull --rebase?
La corsa git pull --rebaseè equivalente alla corsa git fetchseguita dagit rebase . Questo tenta di avanzare rapidamente ai nuovi commit a monte, ma se ciò non è possibile, ridisegnerà i tuoi commit locali sui nuovi commit a monte. Questo di solito è OK, ma fai attenzione:
- Rebase è un argomento avanzato e dovresti capire le implicazioni prima di riformulare.
git pull --rebasenon ti dà l'opportunità di esaminare i commit prima di incorporarli. A seconda di cosa è cambiato a monte, è molto probabile che rebase è sbagliato operazione-a rebase --onto, merge, reseto push -fpotrebbe essere più adatto di una pianurarebase .
- Non è (attualmente) possibile passare
--preserve-mergesall'operazione rebase, quindi qualsiasi unione intenzionale di un ramo di feature verrà linearizzata, ripetendo (e quindi duplicando) tutti i commit di branch di feature.
"Correzione" di un commit unione esistente creato da git pull
Se non hai ancora inviato un commit di unione creato da git pull, puoi modificare il commit di unione. Supponendo di non aver effettuato alcuna fusione intenzionale (ad esempio, unendo un ramo di funzionalità già inserito nel ramo corrente), è necessario:
git rebase @{u}
Il comando sopra dice a Git di selezionare tutti i commit non-merge raggiungibili da HEAD(il commit corrente), meno tutti i commit raggiungibili da @{u}(che è la scorciatoia per "il ramo upstream", cioè, origin/masterse lo HEADè master), replay (cherry-pick ) in cima al ramo a monte, quindi sposta il riferimento al ramo corrente in modo che punti al risultato della riproduzione dei commit. In questo modo, i commit non-merge vengono trasferiti sul commit upstream più recente, eliminando l'unione creata da git pull.
Se si dispone di un commit di unione intenzionale, non si desidera eseguire git rebase @{u}perché verrà riprodotto tutto dall'altro ramo. Affrontare questo caso è sostanzialmente più complicato, motivo per cui è buono da usare git uped evitare del git pulltutto. Probabilmente dovrai usare resetper annullare l'unione creata da pulle quindi fare git rebase -p @{u}. L' -pargomento per cui git rebasenon ha funzionato in modo affidabile per me, quindi potresti finire per dover resetannullare l'unione intenzionale, aggiornare il tuo ramo locale @{u}e quindi ripetere l'unione intenzionale (il che è un dolore se ci fosse molta unione pelosa conflitti).