Perché sto unendo "origine / sviluppo" del ramo di monitoraggio remoto in sviluppo "?


125

Sono l'unico nella mia organizzazione che si sta impegnando con il seguente messaggio:

Unisci il ramo di tracciamento remoto "origine / sviluppo" in sviluppo

Non sono sicuro di cosa sto facendo per causarli, ma mi piacerebbe smettere.

Quale comando sto impartendo per creare questo commit e qual è il comando corretto che dovrei usare per non produrlo?


1
La risposta fatta da Richard Hansen va bene. Ma penso che potrebbe essere fonte di confusione per i principianti. La mia soluzione è continuare a fare pull --rebase ma per evitare il pericolo, nascondo i miei cambiamenti prima del pull. Quindi, dopo aver tirato, lo applico. Risolvo i conflitti. Finalmente posso impegnarmi e spingere.
Johnjohn,

Fa git pull --autostash --rebaselavoro per voi @Johnjohn?
sourcedelica,

Risposte:


206

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).


+1 per discutere di --preserve-merges, tranne per il fatto che non lo hai documentato nei comandi che gli hai detto di eseguire, quindi -1 per quello.
Seth Robertson,

@Seth: grazie per il commento; Ho aggiornato la risposta per raccomandare -p. Ho evitato di consigliarlo prima perché non è necessario molto spesso e il suo comportamento non è ben documentato.
Richard Hansen,

3
Qual è la differenza tra git remote update -pe git fetch?
Verifica il

3
@eckes: git remote update -pè lo stesso di git fetch --all -p. Ho preso l'abitudine di usare di git remote update -pnuovo quando fetchnon avevo l' -popzione.
Richard Hansen,

1
@ user1914692: una volta completata l'unione, Git aggiornerà il ramo locale in modo che punti al commit di unione appena creato, non allo stesso commit del ramo remoto. Questo nuovo commit di unione è il problema, specialmente quando viene spinto.
Richard Hansen,

18
git fetch
git rebase origin/master

Questo dovrebbe farlo. O se vuoi continuare a usare pull

git pull --rebase

Puoi anche impostare quel ramo nella tua configurazione per rifare automaticamente, o essere impostato in quel modo automaticamente per tutti gli altri rami di tracciamento futuri che creerai. Quindi puoi tornare a usare semplicemente

git pull

Altre informazioni al riguardo nella sezione "pull with rebase anziché merge" di questa pagina:

http://mislav.uniqpath.com/2010/07/git-tips/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.