Come 'git pull' in un ramo che non è quello corrente?


126

Quando corri git pullsul masterramo, in genere tira da origin/master. Mi trovo in un ramo diverso chiamato newbranch, ma devo eseguire un comando che esegue un comando git pullda origin/masterin masterma non posso eseguire git checkoutper modificare il ramo selezionato fino a quando il pull non è completo. C'è un modo per fare questo?

Per fornire alcune informazioni di base, il repository memorizza un sito Web. Ho apportato alcune modifiche newbranche le ho distribuite passando al sito Web newbranch. Ora queste modifiche sono state unite a monte nel masterramo, sto cercando di riportare anche il sito Web al masterramo. A questo punto newbranche origin/mastersono identici, ma masterè in ritardo origin/mastere necessita di essere aggiornato. Il problema è, se lo faccio in modo tradizionale:

$ git checkout master
   # Uh oh, production website has now reverted back to old version in master
$ git pull
   # Website is now up to date again

Ho bisogno di ottenere lo stesso di sopra ( git checkout master && git pull), ma senza cambiare la directory di lavoro a una revisione precedente durante il processo.


@phi: non penso che funzionerebbe, perché ci sono newbranche non c'è niente da nascondere!
Malvineous

Vorrei clonare in una nuova directory, unire newbranch in master, unire nuovamente master in newbranch, quindi git pull da dove ti trovi. Master e newbranch saranno la stessa cosa.
AET

@aet Potrebbe farlo ora nella sua directory corrente facendo git fetch; git merge origin/masterdall'interno newbranch. Non vi è alcun vantaggio nella clonazione di un'intera seconda copia del repository.
meagar


Risposte:


5

Hai un albero di lavoro che non vuoi toccare, quindi usane un altro. Il clone è economico, è costruito per questo.

git fetch origin master       # nice linear tree
git clone . ../wip -b master  # wip's `origin/master` is my `master`
cd ../wip                     # .
git pull origin origin/master # merge origin's origin/master
git push origin master        # job's done, turn it in.
cd ../main
rm -rf ../wip                 # wip was pushed here, wip's done

git checkout master           # payload

Il problema con tutte le altre risposte qui è che in realtà non fanno il tiro. Se hai bisogno della fusione o del rebase per cui hai impostato il pull, hai bisogno di un altro albero di lavoro e della procedura sopra. Altrimenti basta git fetch; git checkout -B master origin/master.


2
Quando esegui il git checkout mastercheckout del vecchio masterramo perché non hai fatto un git pullnella maincartella per sincronizzarlo con origin / master. Questo è ciò che sto cercando di evitare.
Malvineous

Il checkout eseguito dal clone è del vecchio master, ma il checkout è in una directory che il server web non sta guardando. Il checkout principale alla fine è del master completamente unito che è stato respinto da wip.
jthill

Alla riga 6 sposti masternuovamente il unito (aggiornato) a origin, ma non credo che il tuo checkout finale sia aggiornato master. Non è git pullnecessario aggiornare il masterramo nella maindirectory, quindi a meno che non mi manchi qualcosa, i tuoi comandi non sono diversi dall'esecuzione da soli git checkout mastere dal vecchio masteralbero. Se guardi da vicino, non stai eseguendo alcun comando nella maindirectory che comunica a monte (a parte la riga 1, che viene eseguita prima di apportare modifiche al repository upstream.)
Malvineous

beh, potresti provarlo su un repository di prova o controllare i documenti push.
jthill

1
@jwg rispetto a cosa, per favore? Assicurati di soddisfare tutte le esigenze dichiarate dell'OP.
jthill

163

Semplice: aggiornamento da un ramo remoto a un ramo master attualmente non estratto :

git fetch origin master:master

dove origin è il tuo telecomando e sei attualmente estratto in qualche ramo, ad esempio dev .

Se vuoi aggiornare il tuo ramo attuale oltre a quello specificato in una volta sola:

git pull origin master:master

4
Hm, sembra che non funzioni sempre, però; Mi è appena stato chiesto di unirmi al mio ramo WIP.
underscore_d

@underscore_d lo stesso per me.
Greg

1
Ha funzionato per me ... se richiede di unire, immagino che ci siano cambiamenti nel tuo ramo che stai aggiornando che non sono impegnati nell'origine
skim

2
Come dovrebbe funzionare? Non funziona per me, cerca solo di unire origin / master nel mio ramo attualmente estratto.
mhogerheijde

3
Questo attira il master nel ramo corrente. Questo NON è sicuramente ciò che viene richiesto. Se cambi pull in fetch, questo sarebbe esattamente ciò che ti viene richiesto.
Jeff Wolski

90

La risposta è qui: Unisci, aggiorna ed estrai i rami Git senza usare i checkout

# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master

# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo

2
Questo è il migliore, poiché funziona con modifiche locali non confermate.
Tomasz Gandor

2
Se vuoi solo metterti al passo con le ultime modifiche che faresti git fetch origin master:master. git fetchdi per sé presumerebbe che tu intendessi aggiornare il ramo corrente e non qualche altro ramo.
John Leidegren

2
Questa è la risposta più semplice e diretta. Questa dovrebbe essere la risposta accettata IMO.
Keego

@JohnLeidegren - tranne che non sempre funziona come previsto. Vedi i commenti alla risposta stackoverflow.com/a/42902058/274579 .
ysap

22

A quanto pare, la risposta è apparentemente semplice:

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

Ciò consente di aggiornare il masterramo senza passare ad esso fino a quando non è stato aggiornato.


11
Questo non fa quello che hai chiesto come fare.
jthill

Come dice il commento sopra, la domanda che hai finito per fare non è in realtà la domanda a cui hai risposto. Dovresti aggiornare la tua domanda in modo che si tratti meno specificamente di fondersi in un ramo senza controllarlo e di più sul passaggio direttamente alla versione più recente di un ramo disponibile su un telecomando senza prima controllare la vecchia versione.
meagar

1
È assolutamente la risposta che sono venuto qui a cercare :)
Sophistifunk

1
Non quello che voleva OP, ma mi ha aiutato, ad essere onesto.
Marcel Bro

1
@anoniim, non quello che voleva l'OP? Intendi l'OP che ha appena risposto a questa domanda?
smac89

12

Sei preoccupato per qualcosa che non può essere risolto, poiché le operazioni Git non sono atomiche. Avrai sempre un buco in cui la tua directory di lavoro è a metà strada tra i rami, anche se aggiorni il master senza prima passare ad esso. Questo è il motivo per cui Git non è uno strumento di distribuzione .

Dal momento che non stai effettivamente eseguendo il commit del codice nel tuo ambiente di produzione (spero), non hai effettivamente bisogno di avere un ramo controllato. Puoi semplicemente fare a git fetchper aggiornare i tuoi ref remoti, e quindi git checkout origin/masterspostare la directory di lavoro direttamente sul commit attualmente puntato da origin/master. Questo ti metterà in uno stato di testa distaccato, ma ancora una volta, poiché non stai eseguendo il commit del codice, non importa.

Questo è il buco più piccolo che otterrai, ma come ho detto, esiste ancora un buco; checkoutnon è atomico.


Capisco i limiti dell'utilizzo di git per la distribuzione, il problema è che il buco in questo caso durerà pochi minuti invece che meno di un secondo. Bella idea di fare il check-out origin/master, però, potrebbe funzionare.
Malvineous

Cosa rende il buco lungo "minuti"? Tirando i dati attraverso la rete? Basta fare un git fetchprima di fare qualsiasi altra cosa e rimuovere il trasferimento effettivo dei dati.
meagar

È lungo pochi minuti perché un file (ora) non tracciato verrebbe sovrascritto da un commit precedente. Quindi devo copiare il file, fare le cose di git, quindi rimetterlo a posto. I "minuti" derivano dalla mia velocità di digitazione. (Sì, potrei scriverlo, ma era solo per sottolineare che avere Git fa tutto da solo è più veloce.)
Malvineous

3

Puoi usare update-ref per questo:

git fetch
git update-ref refs/heads/master origin/master
git checkout master

Nota che questo eliminerebbe tutti i commit locali nel ramo master. Nel tuo caso non ce ne saranno, quindi va bene. Per altre persone che cercano di farlo dove ci sono commit locali, non penso sia possibile, poiché l'unione può essere eseguita solo sul ramo corrente.


Questo sarebbe equivalente a git branch --force master origin/master? Questo costringe la testa locale mastera indicare la testa di originsmaster
Keego

2

La soluzione di Malvineous funziona per me

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

Basta dare l'errore


warning: not deleting branch 'master' that is not yet merged to
         'refs/remotes/origin/master', even though it is merged to HEAD.
error: The branch 'master' is not fully merged.
If you are sure you want to delete it, run 'git branch -D master'.

Quindi corro con l'opzione -D

Grazie


0

git fetch origin master:master

  • "Tira" (in realtà recupera) master.
  • Se hai modifiche sul tuo masterche non sono ancora state inviate, origin/masterviene unito al tuo master.
  • Se ci sono conflitti di unione, dovrai prima risolverli.
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.