Qual è la differenza tra 'git pull' e 'git fetch'?


11919

Quali sono le differenze tra git pulle git fetch?


364
Ho trovato questo articolo ben scritto su git fetch e git pull che vale la pena leggere: longair.net/blog/2009/04/16/git-fetch-and-merge
Marcos Oliveira,

51
Il nostro approccio alternativo è diventato git fetch; git reset --hard origin/masterparte del nostro flusso di lavoro. Elimina le modifiche locali, ti tiene aggiornato con il MA MA ti assicura di non limitarti a inserire nuove modifiche in cima alle modifiche correnti e fare un pasticcio. Lo abbiamo usato per un po 'e in pratica sembra molto più sicuro in pratica. Assicurati solo di aggiungere / impegnare / stash qualsiasi lavoro in corso prima!
Michael Durrant,

26
Assicurati di sapere come usare git stash correttamente. Se stai chiedendo "pull" e "fetch", forse anche "stash" dovrà essere spiegato ...
Henry Heleine,

36
Molte persone provenienti da Mercurial continuano a usare "git pull", pensando che sia equivalente a "hg pull". Che non lo è. L'equivalente di Git di "hg pull" è "git fetch".
Serge Shultz,

8
comando git fetch che recupera il codice aggiornato con branch e inoltre otterrà i nuovi rami aggiunti nel tuo locale, comando git pull recupera solo il codice aggiornato del solo ramo corrente
Kartik Patel

Risposte:


9920

In parole povere, git pullfa git fetchseguito da a git merge.

Puoi fare un git fetchin qualsiasi momento per aggiornare i tuoi rami di localizzazione remota in refs/remotes/<remote>/.

Questa operazione non cambia mai nessuna delle tue filiali locali sotto refs/heads, ed è sicura da fare senza cambiare la tua copia di lavoro. Ho anche sentito parlare di persone che corrono git fetchperiodicamente in un cron job in background (anche se non consiglierei di farlo).

A git pullè ciò che faresti per aggiornare una filiale locale con la sua versione remota, aggiornando anche le altre filiali di tracciamento remoto.

Documentazione git - git pull :

Nella sua modalità predefinita, git pullè una scorciatoia per git fetchseguita da git merge FETCH_HEAD.


326
"A" git pull "è ciò che faresti per aggiornare il tuo repository" <- l'aggiornamento del repository non è già stato eseguito da fetch? non vuoi dire che aggiorna le tue filiali locali con le filiali remote? All'unione: unisce i rami remoti con le copie locali di tali rami, o cosa si fonde esattamente qui?
Albert,

194
@Albert: Sì, è stranamente formulato. git pullsi unirà sempre nel ramo corrente . Quindi si seleziona quale ramo si vuole tirare da , e lo tira nel ramo corrente. La filiale from può essere locale o remota; può anche essere un ramo remoto che non è registrato git remote(il che significa che si passa un URL dalla git pullriga di comando).
intuito il

129
@espertus: No. La spinta non fa mai automaticamente una fusione. Ci si aspetta che l'utente tiri, risolvendo eventuali conflitti di unione a livello locale, quindi rispedisca al telecomando.
Greg Hewgill

33
Se sono /home/alice/e faccio git fetch /home/bob, quali parametri devo passare al successivo git merge?
ripper234,

106
Nota per le persone che imparano Git: in pullrealtà non può essere emulato da un fetchplus a merge. Ho appena recuperato una modifica in cui cambia solo un puntatore di filiale remota e si mergerifiuta di fare qualsiasi cosa. pull, d'altra parte, avanza rapidamente il mio ramo di tracciamento.
Roman Starkov,

2173
  • Quando lo usi pull, Git cerca di fare automaticamente il tuo lavoro per te. È sensibile al contesto , quindi Git unirà tutti i commit estratti nel ramo in cui stai attualmente lavorando. Unisce pull automaticamente i commit senza lasciarti esaminare prima . Se non gestisci da vicino le tue filiali, potresti imbatterti in frequenti conflitti.

  • Quando si fetch, Git raccoglie tutti i commit dal ramo di destinazione che non esistono nel ramo corrente e li memorizza nel repository locale . Tuttavia, non li unisce al ramo corrente . Ciò è particolarmente utile se è necessario mantenere aggiornato il repository, ma si sta lavorando su qualcosa che potrebbe interrompersi se si aggiornano i file. Per integrare i commit nella tua filiale principale, devi usare merge.


34
D'accordo, ottimo commento. Ecco perché odio git pull. Quando avrebbe mai senso lasciare che uno strumento di revisione apportasse modifiche al codice per te? E non è quello che sta facendo l'unione di due file? Che cosa succede se queste due modifiche sono fisicamente separate nel file, ma LOGICALMENTE in contrasto?
Lee Dixon,

126
@elexhobby short put, git fetchaggiorna solo la tua .git/directory (AKA: repository locale) e niente al di fuori .git/(AKA: albero di lavoro). Non cambia le filiali locali e non tocca masterneanche. Tocca remotes/origin/masterperò (vedi git branch -avv). Se hai più telecomandi, prova git remote update. Questo è un git fetchper tutti i telecomandi in un solo comando.
Tino,

24
@Tino tuo è davvero il punto più importante. Le persone potrebbero non sapere che i rami "remoti" sono effettivamente archiviati come un mucchio di hash .git/refs/remotes/origin/.
Chris,

13
Quando recuperi, Git raccoglie eventuali commit dal ramo di destinazione che non esistono nel tuo ramo corrente e li memorizza nel tuo repository locale : come posso vedere cosa è stato portato dal telecomando e come posso unirlo ai miei rami locali?
ア レ ッ ク ス

13
@Tino Quello che ancora non capisco è ... qual è il punto? Perché usare fetch se si aggiorna solo .git? Qual è il vantaggio previsto e cosa dovrei fare dopo?
BadHorsie,

1210

È importante confrontare la filosofia di progettazione di git con la filosofia di uno strumento di controllo del codice sorgente più tradizionale come SVN.

Subversion è stato progettato e costruito con un modello client / server. Esiste un unico repository che è il server e diversi client possono recuperare il codice dal server, lavorarci su, quindi ripristinarlo sul server. Il presupposto è che il client può sempre contattare il server quando deve eseguire un'operazione.

Git è stato progettato per supportare un modello più distribuito senza bisogno di un repository centrale (anche se puoi sicuramente usarne uno se vuoi). Inoltre git è stato progettato in modo tale che il client e il "server" non debbano essere online contemporaneamente. Git è stato progettato in modo tale che anche le persone su un link inaffidabile possano scambiare codice via e-mail. È possibile lavorare completamente disconnesso e masterizzare un CD per scambiare codice tramite git.

Per supportare questo modello git mantiene un repository locale con il tuo codice e anche un repository locale aggiuntivo che rispecchia lo stato del repository remoto. Mantenendo una copia del repository remoto in locale, git può capire le modifiche necessarie anche quando il repository remoto non è raggiungibile. Successivamente, quando è necessario inviare le modifiche a qualcun altro, git può trasferirle come un insieme di modifiche da un momento noto al repository remoto.

  • git fetch è il comando che dice "aggiorna la mia copia locale del repository remoto".

  • git pull dice "porta le modifiche nel repository remoto dove mantengo il mio codice".

Normalmente lo git pullfa eseguendo un git fetchaggiornamento per aggiornare la copia locale del repository remoto, quindi unendo le modifiche nel proprio repository di codice e possibilmente nella copia di lavoro.

Il take away è tenere presente che spesso ci sono almeno tre copie di un progetto sulla workstation. Una copia è il tuo repository con la tua cronologia di commit. La seconda copia è la tua copia di lavoro in cui stai modificando e costruendo. La terza copia è la copia locale "memorizzata nella cache" di un repository remoto.


75
Tecnicamente, i repository locali e remoti sono davvero la stessa cosa. In Git, un repository è un DAG di commit che punta ai loro genitori. Le filiali non sono, tecnicamente, nient'altro che nomi significativi di commit. L'unica differenza tra filiali locali e remote è che quelle remote hanno il prefisso remoteName/ Git da zero è un'ottima lettura. Una volta capito come funziona Git - ed è meravigliosamente semplice , davvero - tutto ha un senso.
Emil Lundberg,

13
Grazie mille per la spiegazione. Finora non avevo capito davvero che Git fosse stato progettato, quindi non dovevi avere un repository centrale. Tutti dicono sempre "DVCS" quando descrivono Git, ma come un programmatore relativamente nuovo, questo non significa nulla per me. Non ho mai visto un CVCS e non ho mai lavorato con un repository remoto centrale quando collaboravo con altri (ad esempio Github), quindi fino ad ora devo ancora capire cosa ha reso speciale Git.
Brian Peterson,

7
Quindi, in base a questo, perché non è una buona idea git-fetch con un lavoro cron? Tenere sempre una copia del telecomando con cui stai lavorando sul tuo computer locale sembra una buona idea. In effetti, ho voglia di scrivere uno script che controlla se ho aggiornato il mio telecomando nelle ultime 24 ore e collegarlo con un hook udev per la connessione a Internet.
Brian Peterson,

24
Uno dei motivi per cui NON è una buona idea avere un lavoro cron: spesso quando lavoro su un nuovo ticket o sugli aggiornamenti di un ramo, mi piace vedere le modifiche recuperate. Se i cambiamenti non arrivano durante un recupero, sarò più sicuro nel chiedere al mio collega programmatore "ehi hai spinto?". Ho anche la sensazione di quanto "agitato" nel repository dall'ultima volta che ho recuperato. Questo aiuta anche a darmi un'idea della quantità e della velocità delle modifiche attualmente in corso su questo repository.
Michael Durrant,

5
@Nabheet La cosa è che, Git è orientato al contenuto. Memorizza i dati una sola volta e li punta più volte. Ecco perché in Git, anche più commit sopra un originale non influiscono molto sulla dimensione del repository, poiché la maggior parte degli oggetti sono gli stessi.
cst1992,

890

Ecco l'immagine di Oliver Steele di come tutto combacia :

inserisci qui la descrizione dell'immagine

Se l'interesse è sufficiente, suppongo di poter aggiornare l'immagine per aggiungere git clonee git merge...


156
Un'immagine aggiornata con git clonee git mergesarebbe molto utile!
MEM

20
Sì, per favore aggiungi git merge- dovrebbe mostrare chiaramente che mergechiamare separatamente NON è lo stesso di chiamare pullperché si pullsta unendo solo da remoto e ignora i tuoi commit locali nella tua filiale locale che sta monitorando la filiale remota da cui viene estratto.
JustAMartin,

12
Un'immagine vale più di mille parole! L'immagine aggiornata con il clone e l'unione del flusso di dati è pronta da qualche parte? Qualche altro flusso di dati oltre a quello che è già nel diagramma?
shikhanshu,

10
@Contango, aggiungi clone e unisci. Sarebbe utile per i neofiti come me.
affitta il

11
Esistono due diagrammi che mostrano il clone e l'unione in altre risposte (sotto) di th3sly e tharkarkenger.
intotecho,

488

Un caso d'uso di git fetchè che quanto segue ti dirà eventuali cambiamenti nel ramo remoto dall'ultimo pull ... in modo da poter controllare prima di fare un pull effettivo, che potrebbe cambiare i file nel tuo ramo corrente e nella copia di lavoro.

git fetch
git diff ...origin

Vedi: https://git-scm.com/docs/git-diff per quanto riguarda la sintassi a doppio e triplo punto nel comando diff


9
perchè no git diff ..origin?
Erik Kaplun,

3
git diff origin e git diff ..origin sembrano funzionare ma non questa strana ... roba
Marc

19
@Compustretch Non doveva esserci uno spazio. git diff ...originè equivalente a git diff $(git-merge-base HEAD origin) origin(consultare la git diff [--options] <commit>...<commit> [--] [<path>…]sezione di kernel.org/pub/software/scm/git/docs/git-diff.html#_description ), che è diverso da git diff origin; git diff ...originè concettualmente le modifiche apportate da originquando si è ramificato il ramo corrente origin, mentre git diff origininclude anche il contrario delle modifiche apportate al ramo corrente da quando si è ramificato origin.
Max Nanasy,

2
nessuno dei comandi .. ha funzionato per me (su Windows), ma git diff origin/masterfunziona, come indicato di seguito
Brian Burns,

lo stesso qui usando git 2.0.0 su OSX. Nessuno di questi comandi ha funzionato. Sono stati deprecati?
K.-Michael Aye,

373

Mi è costato un po 'capire qual era la differenza, ma questa è una spiegazione semplice. masternel tuo localhost è un ramo.

Quando si clona un repository, si recupera l'intero repository sull'host locale. Ciò significa che in quel momento hai un puntatore origin / master HEADe un master che punta allo stesso HEAD.

quando inizi a lavorare e fai dei commit fai avanzare il puntatore principale a HEAD+ i tuoi commit. Ma il puntatore origin / master punta ancora a quello che era quando hai clonato.

Quindi la differenza sarà:

  • Se lo fai git fetch, recupera tutte le modifiche nel repository remoto ( GitHub ) e sposta il puntatore origine / master su HEAD. Nel frattempo il tuo direttore di filiale locale continuerà a indicare dove si trova.
  • Se lo fai git pull, eseguirà sostanzialmente il recupero (come spiegato in precedenza) e unirà tutte le nuove modifiche al ramo principale e sposta il puntatore su HEAD.

14
origin / master è una filiale locale che è una COPIA del master sull'origine. Quando recuperi, aggiorni local: / origin / master. Una volta che hai davvero capito che tutto in git è un ramo, questo ha molto senso ed è un modo molto potente per mantenere diversi set di modifiche, creare filiali locali veloci, unire e rifare le basi e in genere ottenere molto valore dalla ramificazione economica modello.
cam8001,

3
Ancora confuso. Ho pensato git fetchdi scaricare letteralmente le modifiche sul repository remoto nel repository locale, ma NON di commetterle, ovvero devono ancora essere aggiunte / impegnate nel repository locale.
krb686,

3
il recupero tira solo da remoto / origine (github) alla tua origine locale. Ma non lo unisce ai tuoi file di lavoro effettivi. se fai un pull, recupererà e si unirà ai tuoi file di lavoro correnti
Gerardo,

223

A volte aiuta una rappresentazione visiva.

inserisci qui la descrizione dell'immagine


18
Penso che l'immagine abbia mostrato che influenza anche il repository locale. Cioè, Git pull è una combinazione di effetti sul repository locale e sulla copia di lavoro. In questo momento sembra influire solo sulla copia di lavoro.
polarità

10
@太極者無極而生D'accordo - questa immagine è piuttosto fuorviante, perché fa apparire come git pullè per saltare l'operazione di recupero, che naturalmente è imprecisa.
forresthopkinsa,

9
qual è la differenza tra un "repository locale" e una "copia di lavoro"? Non sono entrambi locali sul computer?
theITvideos

1
A che cosa serve allora git fetch? come vedere che differenza c'è nel repository locale e nella copia di lavoro?
Vikash,

2
@theITvideos No, non lo è. Un repository locale è dove va il tuo codice (dal repository funzionante) quando esegui il commit. (Va al repository remoto quando si preme).
Vikash,

219

Brevemente

git fetchè simile pullma non si fonde. cioè recupera gli aggiornamenti remoti ( refse objects) ma il tuo locale rimane lo stesso (cioè origin/masterviene aggiornato ma masterrimane lo stesso).

git pull si abbassa da un telecomando e si fonde all'istante.

Di Più

git clone clona un repo.

git rebasesalva cose dal ramo corrente che non si trova nel ramo a monte in un'area temporanea. La tua filiale ora è la stessa di prima di iniziare le modifiche. Quindi, git pull -rebaseabbassa le modifiche remote, riavvolgi il tuo ramo locale, riproduci le modifiche sopra la parte superiore del ramo corrente una per una fino a quando non sei aggiornato.

Inoltre, git branch -ati mostrerà esattamente cosa sta succedendo con tutte le tue filiali - locali e remote.

Questo post sul blog è stato utile:

La differenza tra git pull, git fetch e git clone (e git rebase) - Mike Pearce

e le coperture git pull, git fetch, git clonee git rebase.

====

AGGIORNARE

Ho pensato di aggiornarlo per mostrare come lo useresti in pratica.

  1. Aggiorna il tuo repository locale dal telecomando (ma non unire):

    git fetch 
    
  2. Dopo aver scaricato gli aggiornamenti, vediamo le differenze:

    git diff master origin/master 
    
  3. Se sei soddisfatto di questi aggiornamenti, quindi unisci:

    git pull
    

Appunti:

Al passaggio 2: per ulteriori informazioni sulle differenze tra locali e telecomandi, vedere: Come confrontare un ramo git locale con il suo ramo remoto?

Al passaggio 3: probabilmente è più preciso (ad esempio in un repo che cambia rapidamente) fare un git rebase originqui. Vedi il commento di @Justin Ohms in un'altra risposta.

Vedi anche: http://longair.net/blog/2009/04/16/git-fetch-and-merge/


1
Mi sembra che se qualcuno vuole solo che il codice locale rifletta "la punta", dovrebbe usare git clone. Metto la punta tra virgolette, dato che presumo significherebbe qualunque sia il maestro e cosa qualcuno "Scarichi come zip" da github.com
Chris K

3
cosa succede se non sei soddisfatto delle modifiche dopo aver recuperato? cosa fare dopo?
Kugutsumen,

Il tuo paragrafo su rebase era proprio quello che stavo cercando. L'intera idea di azzerare tutto, aggiornare da remoto, quindi riprodurre le modifiche in aggiunta ai precedenti commit avvenuti mentre stavi lavorando. Spiegazione perfetta supponendo che sia corretta. ;)
coblr

178
git-pull - Recupera da e unisci con un altro repository o un ramo locale
SINOSSI

git pull ...
DESCRIZIONE

Esegue git-fetch con i parametri indicati e chiama git-merge per unire il file 
recuperate le teste nel ramo corrente. Con --rebase, chiama git-rebase
invece di git-merge.

Nota che puoi usare. (directory corrente) come <repository> da estrarre
dal repository locale - questo è utile quando si uniscono filiali locali 
nel ramo corrente.

Nota anche che le opzioni significano git-pull stesso e git-merge sottostante 
deve essere fornito prima delle opzioni pensate per git-fetch.

Tireresti se vuoi che le storie si fondano, andresti a prendere se volessi semplicemente "codez" dato che qualcuno ha taggato alcuni articoli qui intorno.


5
Molto interessante, ma non riesco davvero a vedere un caso d'uso in cui si desidera "solo il codice". E cosa succede con il tuo codice quando recuperi? È cancellato? Cosa succede con il telecomando cambia? Come va nel tuo repository senza cancellare il tuo codice se non ti unisci?
e-soddisfa il

11
@ e-satis: il ramo remoto è anche memorizzato localmente sul tuo computer. Quindi, quando lo fai git fetch, recupera le modifiche dal repository e aggiorna il tuo ramo remoto locale. Non influisce sul ramo locale che tiene traccia del ramo remoto locale, quindi non influisce sulla copia di lavoro. Ora, quando lo fai merge, unirà le modifiche recuperate con il tuo ramo locale.
Jeffreyveon,

Un semplice caso d'uso per il comando fetch: esegui operazioni che richiedono molto tempo e che coinvolgono recenti commit di altre persone, come l'unione o una revisione del codice, accedendo al tuo repository locale aggiornato senza requisiti di connettività di rete, perché in precedenza hai utilizzato fetch per il download tutto ciò di cui hai bisogno rapidamente (ad es. mentre visiti qualche altro sviluppatore e sei connesso alla rete di un altro repository). Il comando pull scarica gli stessi commit, ma l'unione che esegue può essere indesiderabile.
Lorenzo Gatti,

163

È possibile recuperare da un repository remoto, vedere le differenze e quindi estrarre o unire.

Questo è un esempio per un repository remoto chiamato origine un ramo chiamato mastertracking del ramo remoto origin/master:

git checkout master                                                  
git fetch                                        
git diff origin/master
git rebase origin master

35
Probabilmente vuoi saltare il pull e fare semplicemente una "origine git rebase" come ultimo passo da quando hai già recuperato le modifiche. Il motivo è che qualcuno potrebbe aver apportato modifiche nel tempo da quando hai fatto il recupero e questi non sarebbero stati in recupero su cui hai fatto la revisione diff.
Justin Ohms,

158

La risposta semplice e breve è quella git pull è semplicemente git fetchseguita da git merge.

È molto importante notare che git pullsi fonderanno automaticamente, che ti piaccia o no . Ciò potrebbe, naturalmente, provocare conflitti di unione. Diciamo che il tuo telecomando è origine il tuo ramo èmaster . Se git diff origin/masterprima di tirare, dovresti avere qualche idea di potenziali conflitti di unione e potresti preparare la tua filiale locale di conseguenza.

Oltre a tirare e spingere, alcuni flussi di lavoro comportano git rebase, come questo, che parafrasi dall'articolo collegato:

git pull origin master
git checkout foo-branch
git rebase master
git push origin foo-branch

Se ti trovi in ​​una situazione del genere, potresti essere tentato di farlo git pull --rebase. A meno che tu non sappia davvero cosa stai facendo, ti sconsiglio. Questo avviso è dalla manpagina per git-pull, versione 2.3.5:

Questa è una modalità operativa potenzialmente pericolosa. Riscrive la cronologia, il che non fa ben sperare quando hai già pubblicato quella cronologia. Non usare questa opzione se non hai letto attentamente git-rebase (1).


2
@JustinOhms Se git pull --rebasenon è la cosa giusta in una determinata situazione, è giusto se lo si fa in due passaggi? Se è la cosa giusta da fare, qual è il vantaggio extra di farlo in due passaggi?
Kaz,

@Kaz - perché il rebase non è automatico. Il recupero delle modifiche per primo consente di effettuare la chiamata di giudizio. Non risolve il problema con la cronologia di rebasing che hai già inviato. Ti permetterà di vedere se è sicuro rifare le modifiche che non hai già fatto.
Justin Ohms,

2
@JustinOhms Come decideresti se è sicuro rifare le modifiche? Vorrei solo provare git rebase e tornare indietro se creasse un pasticcio, nel qual caso potrei anche fare git pull --rebase. Ma forse hai un altro modo?
Kaz,

3
@KaZ gitk ti consente di vedere visivamente la struttura del ramo. Mostrerà la posizione della tua testa locale, i telecomandi e le strutture del tuo ramo in relazione a ciò che hai preso. In questo modo puoi assicurarti di non ripristinare le modifiche recuperate basate su un antenato precedente a ciò che hai già inviato ai tuoi telecomandi.
Justin Ohms,

Utilizzare rebasequando si lavora su un ramo locale non già inviato. Se stai lavorando su un ramo esistente nel telecomando, rebasepuò causare alcuni problemi spiacevoli, quindi dovresti preferire un normale merge.
Justus Romijn,

151

OK , qui ci sono alcune informazioni su git pulle git fetch, quindi puoi capire le effettive differenze ... in poche parole, recuperare recupera i dati più recenti, ma non cambia il codice e non si scherza con il tuo attuale codice locale, ma tira get il codice cambia e uniscilo al tuo ramo locale, continua a leggere per avere maggiori dettagli su ciascuno:

git fetch

Scaricherà tutti i ref e gli oggetti e tutti i nuovi rami nel tuo Repository locale ...

Recupera rami e / o tag (collettivamente, "refs") da uno o più altri repository, insieme agli oggetti necessari per completare le loro storie. I rami di tracciamento remoto vengono aggiornati (vedere la descrizione di seguito per i modi per controllare questo comportamento).

Per impostazione predefinita, viene recuperato anche qualsiasi tag che punta alle cronologie da recuperare; l'effetto è recuperare i tag che puntano ai rami che ti interessano. Questo comportamento predefinito può essere modificato usando le opzioni --tags o --no-tags o configurando remote..tagOpt. Usando un refspec che recupera i tag in modo esplicito, puoi recuperare i tag che non puntano anche ai rami che ti interessano.

git fetch può essere recuperato da un singolo repository o URL denominato o da più repository contemporaneamente se viene fornito e sono presenti telecomandi. voce nel file di configurazione. (Vedi git-config 1 ).

Quando non viene specificato alcun telecomando, per impostazione predefinita verrà utilizzato il telecomando di origine, a meno che non sia configurato un ramo a monte per il ramo corrente.

I nomi dei ref che vengono recuperati, insieme ai nomi degli oggetti a cui puntano, vengono scritti in .git / FETCH_HEAD. Queste informazioni possono essere utilizzate da script o altri comandi git, come git-pull.


git pull

Applicherà le modifiche da remoto al ramo corrente in locale ...

Incorpora le modifiche da un repository remoto al ramo corrente. Nella sua modalità predefinita, git pull è una scorciatoia per git fetch seguito da git merge FETCH_HEAD.

Più precisamente, git pull esegue git fetch con i parametri indicati e chiama git merge per unire le teste di ramo recuperate nel ramo corrente. Con --rebase, esegue git rebase invece di git merge.

dovrebbe essere il nome di un repository remoto come passato a git-fetch 1 . può nominare un ref remoto arbitrario (ad esempio, il nome di un tag) o anche una raccolta di ref con corrispondenti rami di tracciamento remoto (ad esempio refs / head / : refs / remotes / origin / ), ma di solito è il nome di un ramo nel repository remoto.

I valori predefiniti per e vengono letti dalla configurazione "remota" e "unisci" per il ramo corrente come impostato da git-branch --track.


Creo anche la grafica qui sotto per mostrarti come git fetche git pulllavorare insieme ...

git pull e git fetch


10
Se ti piace l'immagine, dai un'occhiata al cheat sheet di git, che è lo stesso tipo di cose per tutti i comandi git ... ndpsoftware.com/git-cheatsheet.html
Tom

3
Il clone non influisce anche sul repository locale (copiando tutta la cronologia da remoto)?
Tom Loredo,

135

inserisci qui la descrizione dell'immagine

Questa rappresentazione grafica interattiva è molto utile per comprendere git: http://ndpsoftware.com/git-cheatsheet.html

git fetchsemplicemente "scarica" ​​le modifiche dal telecomando al repository locale. git pullscarica le modifiche e le unisce nel ramo corrente. "Nella sua modalità predefinita, git pullè una scorciatoia per git fetchseguito da git merge FETCH_HEAD."


18
Persone, fai clic sul link per interagire con le diverse colonne. Questo cheatsheet è la miglior risorsa che abbia mai visto per comprendere appieno le differenze tra ciascun comando.
M. Luisa Carrión,

Questa risposta deve andare in cima
Tessaracter,

126

Bonus:

Parlando di pull & fetch nelle risposte sopra, vorrei condividere un trucco interessante,

git pull --rebase

Questo comando sopra è il comando più utile nella mia vita git che mi ha fatto risparmiare un sacco di tempo.

Prima di inviare i tuoi nuovi commit al server, prova questo comando e sincronizzerà automaticamente le ultime modifiche del server (con un fetch + merge) e posizionerà il tuo commit in alto nel log di git. Non è necessario preoccuparsi di estrazione / unione manuale.

Per i dettagli, consultare: http://gitolite.com/git-pull--rebase


4
Bel suggerimento, anche se vale la pena ricordare ai nuovi utenti git che rebase modifica gli hash di commit (ho scoperto che la sorpresa proviene dalla sovversione).
AlexMA,

1
Puoi spiegare qual è la differenza tra git pulle git pull --rebase?
Shaijut,

2
Vedere il duro avvertimento di questo metodo in una risposta di cui sopra: stackoverflow.com/a/6011169/241244

118

Mi piace avere una rappresentazione visiva della situazione per cogliere queste cose. Forse anche altri sviluppatori vorrebbero vederlo, quindi ecco la mia aggiunta. Non sono del tutto sicuro che sia tutto corretto, quindi per favore commenta se trovi qualche errore.

                                         LOCAL SYSTEM
                  . =====================================================    
================= . =================  ===================  =============
REMOTE REPOSITORY . REMOTE REPOSITORY  LOCAL REPOSITORY     WORKING COPY
(ORIGIN)          . (CACHED)           
for example,      . mirror of the      
a github repo.    . remote repo
Can also be       .
multiple repo's   .
                  .
                  .
FETCH  *------------------>*
Your local cache of the remote is updated with the origin (or multiple
external sources, that is git's distributed nature)
                  .
PULL   *-------------------------------------------------------->*
changes are merged directly into your local copy. when conflicts occur, 
you are asked for decisions.
                  .
COMMIT            .                             *<---------------*
When coming from, for example, subversion, you might think that a commit
will update the origin. In git, a commit is only done to your local repo.
                  .
PUSH   *<---------------------------------------*
Synchronizes your changes back into the origin.

Alcuni importanti vantaggi per avere un mirroring recuperato del telecomando sono:

  • Performance (scorri tutti i commit e i messaggi senza provare a spingerli attraverso la rete)
  • Feedback sullo stato del tuo repository locale (ad esempio, utilizzo Atlassian's SourceTree, che mi fornirà una lampadina che indica se sono impegnato in anticipo o in ritardo rispetto all'origine. Queste informazioni possono essere aggiornate con un GIT FETCH).

Non si git pullesegue anche un'unione, ovvero si arriva fino alla copia di lavoro?
Kamiel Wanrooij,

Buon punto, sì, inserirà tutte le modifiche nella tua copia di lavoro e quindi potrai impegnarlo tu stesso nel repository locale. Aggiornerò il visual.
Justus Romijn il

@JustusRomijn Un pull non aggiorna anche il repository locale? Non dovrebbe esserci un asterisco tra l'originale e gli asterischi copia funzionanti?
user764754

2
@ user764754 Quando tiri, la tua copia di lavoro riceve le modifiche (possono esserci anche alcuni conflitti che potresti dover risolvere). Devi ancora impegnarlo nel tuo repository locale.
Justus Romijn il

@JustusRomijn: Grazie per l'illustrazione. Sarebbe bello se riuscissi a rendere il diagramma più completo illustrando gli effetti di operazioni come reset, cherry pick sugli stati del repository.
jith912,

106

Ho lottato anche con questo. In effetti sono arrivato qui con una ricerca su Google esattamente della stessa domanda. Leggendo tutte queste risposte, alla fine ho dipinto un'immagine nella mia testa e ho deciso di provare a analizzarlo osservando lo stato dei 2 repository e 1 sandbox e le azioni eseguite nel tempo mentre ne guardavo la versione. Quindi ecco cosa mi è venuto in mente. Per favore, correggimi se ho fatto un casino ovunque.

I tre repository con un recupero:

---------------------     -----------------------     -----------------------
- Remote Repo       -     - Remote Repo         -     - Remote Repo         -
-                   -     - gets pushed         -     -                     -
- @ R01             -     - @ R02               -     - @ R02               -
---------------------     -----------------------     -----------------------

---------------------     -----------------------     -----------------------
- Local Repo        -     - Local Repo          -     - Local Repo          -
- pull              -     -                     -     - fetch               -
- @ R01             -     - @ R01               -     - @ R02               -
---------------------     -----------------------     -----------------------

---------------------     -----------------------     -----------------------
- Local Sandbox     -     - Local Sandbox       -     - Local Sandbox       -
- Checkout          -     - new work done       -     -                     -
- @ R01             -     - @ R01+              -     - @R01+               -
---------------------     -----------------------     -----------------------

I tre pronti contro termine

---------------------     -----------------------     -----------------------
- Remote Repo       -     - Remote Repo         -     - Remote Repo         -
-                   -     - gets pushed         -     -                     -
- @ R01             -     - @ R02               -     - @ R02               -
---------------------     -----------------------     -----------------------

---------------------     -----------------------     -----------------------
- Local Repo        -     - Local Repo          -     - Local Repo          -
- pull              -     -                     -     - pull                -
- @ R01             -     - @ R01               -     - @ R02               -
---------------------     -----------------------     -----------------------

---------------------     -----------------------     -----------------------
- Local Sandbox     -     - Local Sandbox       -     - Local Sandbox       -
- Checkout          -     - new work done       -     - merged with R02     -
- @ R01             -     - @ R01+              -     - @R02+               -
---------------------     -----------------------     -----------------------

Questo mi ha aiutato a capire perché un recupero è piuttosto importante.


Non così difficile da leggere: le caselle rappresentano lo stato di un repository, che in ogni riga cambia nel tempo da sinistra a destra dopo l'operazione riportata nella riga 2 della scatola. Le etichette R0n sono tag in git e un tag con un + è ancora roba senza commit. Sanbox viene utilizzato per la cartella di lavoro, che è diversa dalla cartella repository, in cui sono archiviati gli elementi memorizzati.
user1708042

96

La differenza tra GIT Fetch e GIT Pull può essere spiegata con il seguente scenario: (Tenendo presente che le immagini parlano più delle parole !, ho fornito una rappresentazione pittorica)

Facciamo un esempio del fatto che stai lavorando a un progetto con i membri del tuo team. Quindi il loro sarà uno dei rami principali del progetto e tutti i partecipanti dovranno deviarlo al proprio repository locale e quindi lavorare su questo ramo locale per modificare / aggiungere moduli e poi tornare al ramo principale.

Così, Stato iniziale dei due rami quando si biforcuta il progetto principale del repository locale sarà come questo- ( A, Be Csono moduli già completata del progetto)

inserisci qui la descrizione dell'immagine

Ora, si è iniziato a lavorare sul nuovo modulo (supponiamo D) e dopo aver completato il Dmodulo che si vuole spingere al ramo principale, ma intanto quello che succede è che uno dei tuoi compagni di squadra ha sviluppato nuovo modulo E, Fe modificato C.
Quindi ora ciò che è accaduto è che il tuo repository locale manca dietro il progresso originale del progetto e quindi l'inoltro delle modifiche al ramo principale può portare a conflitti e può causare Dmalfunzionamenti del modulo .

inserisci qui la descrizione dell'immagine

Per evitare tali problemi e lavorare in parallelo con l'avanzamento originale del progetto, ci sono due modi:

1. Git Fetch: questo scaricherà tutte le modifiche apportate al progetto di origine / filiale principale che non sono presenti nella filiale locale. Attenderà il comando Git Merge per applicare le modifiche che sono state recuperate nel tuo repository o ramo.

inserisci qui la descrizione dell'immagine

Quindi ora puoi monitorare attentamente i file prima di unirli al tuo repository. E puoi anche modificare Dse necessario a causa di Modified C.

inserisci qui la descrizione dell'immagine

2. Git Pull: questo aggiornerà il tuo ramo locale con l'origine / ramo principale, cioè in realtà ciò che fa è una combinazione di Git Fetch e Git che si fondono uno dopo l'altro. Ma ciò può causare conflitti, quindi si consiglia di utilizzare Git Pull con una copia pulita.

inserisci qui la descrizione dell'immagine


1
se potessi cambiare 'Main Branch' in 'Remote Repo', sarebbe un'ottima risposta.
Qibiron che il

87

Diciamo semplicemente:

git pull == git fetch + git merge

Se si esegue git pull, non è necessario unire i dati in locale. Se esegui git fetch, significa che devi eseguire git mergeper ottenere l'ultimo codice sul tuo computer locale. Altrimenti, il codice macchina locale non verrebbe modificato senza unire.

Quindi in Git Gui, quando esegui il recupero, devi unire i dati. Il recupero stesso non modificherà il codice nel tuo locale. Puoi verificarlo quando aggiorni il codice recuperando una volta recupera e vedi; il codice non cambierà. Quindi unisci ... Vedrai il codice modificato.


3
Preferirei dire git pull == git fetch + git merge:)
melvynkim il

2
Magit pull --rebase = git fetch + git rebase
Tino,

83

git fetchestrae il codice dal server remoto ai rami di tracciamento nel repository locale. Se il telecomando è chiamato origin(il default) allora questi rami sarà all'interno origin/, per esempio origin/master, origin/mybranch-123ecc Questi non sono i tuoi rami attuali, sono locali le copie di quei rami dal server.

git pullfa un git fetchma poi unisce anche il codice dal ramo di tracciamento alla versione locale corrente di quel ramo. Se non sei ancora pronto per queste modifiche, git fetchprima di tutto.


78

git fetchrecupererà i rami remoti in modo da poterli git diffo git mergecon il ramo corrente. git pulleseguirà il recupero sul brach remoto seguito dal ramo corrente e quindi unirà il risultato. È possibile utilizzare git fetchper vedere se ci sono aggiornamenti al ramo remoto senza unirli necessari con il ramo locale.


73

Git Fetch

Scarica le modifiche alla tua filiale locale dall'origine attraverso il recupero. Fetch chiede al repository remoto tutti gli commit che altri hanno fatto ma non hai sul repository locale. Fetch scarica questi commit e li aggiunge al repository locale.

Git Merge

Puoi applicare le modifiche scaricate tramite fetch utilizzando il comando unisci. Unisci prenderà i commit recuperati dal recupero e proverà ad aggiungerli alla tua filiale locale. L'unione manterrà la cronologia di commit delle modifiche locali in modo che quando condividi la tua filiale con push, Git saprà come gli altri possono unire le tue modifiche.

Git Pull

Fetch e merge eseguiti insieme abbastanza spesso da creare un comando che combina i due pull. Pull esegue il recupero e quindi l'unione per aggiungere i commit scaricati nella tua filiale locale.


51

L'unica differenza tra git pulle git fetchè che:

git pull estrae da un ramo remoto e lo unisce.

git fetch recupera solo dal ramo remoto ma non si unisce

cioè git pull = git fetch + git merge ...


1
E nemmeno aiutare se Git pensa che tu sia dietro con impegni e può "avanzare rapidamente", il che alla fine ho finito rm -rfcon il tutto e ricominciare da capo. Stupido Git, per favore, fammi solo sapere in modo che io possa tornare al lavoro?
Chris K,

47

In parole povere, se stavi per salire su un aereo senza alcuna connessione a Internet ... prima di partire, potresti semplicemente farlo git fetch origin <master>. Recupererebbe tutte le modifiche nel tuo computer, ma le manterrà separate dallo sviluppo / area di lavoro locale.

Sull'aereo, è possibile apportare modifiche allo spazio di lavoro locale e quindi unirlo a ciò che è stato recuperato e risolvere potenziali conflitti di unione tutti senza una connessione a Internet. E a meno che qualcuno non abbia apportato nuove modifiche contrastanti al repository remoto, una volta arrivato a destinazione lo faresti git push origin <branch>e andresti a prendere il tuo caffè.


Da questo fantastico tutorial di Atlassian :

Il git fetchcomando scarica commit, file e ref da un repository remoto nel repository locale.

Recuperare è ciò che fai quando vuoi vedere su cosa hanno lavorato tutti gli altri . È simile all'aggiornamento SVN in quanto ti consente di vedere come è progredita la cronologia centrale, ma non ti obbliga a unire effettivamente le modifiche nel tuo repository. Git isola il contenuto recuperato come contenuto locale esistente , non ha assolutamente alcun effetto sul lavoro di sviluppo locale . Il contenuto recuperato deve essere verificato esplicitamente utilizzando il git checkoutcomando. Questo rende il recupero un modo sicuro per rivedere i commit prima di integrarli con il tuo repository locale.

Al contenuto scaricato da un repository remoto, git pulle git fetchcomandi sono disponibili per realizzare il compito. Puoi prendere in considerazione git fetchla versione "sicura" dei due comandi. Scaricherà il contenuto remoto, ma non aggiornerà lo stato di funzionamento del repository locale, lasciando intatto il lavoro corrente. git pullè l'alternativa più aggressiva, scaricherà il contenuto remoto per il ramo locale attivo ed eseguirà immediatamente git mergeper creare un commit di unione per il nuovo contenuto remoto. Se sono in corso modifiche in corso, ciò causerà conflitti e darà il via al flusso di risoluzione dei conflitti di unione.


Con git pull:

  • Non ottieni alcun isolamento.
  • Colpisce il tuo sviluppo locale.
  • Non ha bisogno di essere verificato esplicitamente. Perché lo fa implicitamente a git merge.
  • Fondamentalmente NON è sicuro. È aggressivo
  • A differenza di git fetchdove influenza solo il tuo .git/refs/remotes, git pull influenzerà sia il tuo che il tuo.git/refs/remotes .git/refs/heads/

Hmmm ... quindi se non sto aggiornando la copia funzionante git fetch, allora dove sto facendo le modifiche? Dove Git fetch memorizza i nuovi commit?

Ottima domanda Lo mette da qualche parte isolato dalla tua copia di lavoro. Ma di nuovo dove? Scopriamolo.

Nella directory del tuo progetto (ovvero, dove esegui i tuoi gitcomandi) fai:

  1. ls. Questo mostrerà i file e le directory. Niente di speciale, lo so.

  2. Adesso fallo ls -a. Questo mostrerà dot file , vale a dire, i file che iniziano con .Sarete quindi in grado di vedere una directory chiamata: .git.

  3. Fare cd .git. Questo ovviamente cambierà la tua directory.
  4. Ora arriva la parte divertente; fare ls. Vedrai un elenco di directory. Stiamo cercando refs. Fare cd refs.
  5. È interessante vedere cosa c'è dentro tutte le directory, ma concentriamoci su due di esse. headse remotes. Utilizzare cdper controllare anche al loro interno.
  6. Qualsiasi git fetch cosa tu faccia aggiornerà gli elementi nella /.git/refs/remotesdirectory. Non aggiornerà nulla nella /.git/refs/headsdirectory.
  7. Chiunque git pull eseguirà prima di tutto git fetch, aggiornerà gli elementi nella /.git/refs/remotesdirectory, quindi si unirà al proprio locale e quindi cambierà la testa all'interno della /.git/refs/headsdirectory.

Una risposta correlata molto buona può anche essere trovata in Dove si posiziona 'git fetch'? .

Inoltre, cerca "Notazione barra" nel post delle convenzioni di denominazione del ramo Git . Ti aiuta a capire meglio come Git colloca le cose in diverse directory.


Per vedere la differenza reale

Basta fare:

git fetch origin master
git checkout master

Se il master remoto è stato aggiornato, riceverai un messaggio come questo:

Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Se non lo facessi fetche lo facessi, il git checkout mastertuo git locale non saprebbe che sono stati aggiunti 2 commit. E direbbe solo:

Already on 'master'
Your branch is up to date with 'origin/master'.

Ma è obsoleto e errato. È perché Git ti darà feedback esclusivamente sulla base di ciò che sa. È ignaro dei nuovi impegni che non ha ancora abbattuto ...


Esiste un modo per vedere le nuove modifiche apportate in remoto mentre si lavora sul ramo in locale?

Alcuni IDE (ad esempio Xcode) sono super intelligenti e utilizzano il risultato di a git fetche possono annotare le righe di codice che sono state modificate nel ramo remoto del ramo di lavoro corrente. Se quella linea è stata cambiata sia dalle modifiche locali sia dal ramo remoto, allora quella linea viene annotata in rosso. Questo non è un conflitto di unione. È un potenziale conflitto di unione. È un headsup che puoi usare per risolvere il futuro conflitto di unione prima di farlo git pulldal ramo remoto.

inserisci qui la descrizione dell'immagine


Consiglio divertente:

Se hai recuperato un ramo remoto, ad esempio:

git fetch origin feature/123

Quindi questo andrebbe nella directory dei telecomandi. Non è ancora disponibile per la tua directory locale. Tuttavia, semplifica il checkout a quel ramo remoto tramite DWIM (fai ciò che intendo):

git checkout feature/123

non devi più fare:

git checkout -b feature/123 origin/feature/123

Per saperne di più leggi qui


1
Mi piace questa risposta
Kid_Learning_C

44

Git consente di applicare commit cronologicamente più vecchi dopo i commit più recenti. Per questo motivo, l'atto di trasferire i commit tra i repository è diviso in due fasi:

  1. La copia di nuovi commit dal ramo remoto alla copia di questo ramo remoto all'interno del repository locale.

    (operazione repo to repo) master@remote >> remote/origin/master@local

  2. Integrazione di nuovi commit nella filiale locale

    (operazione dentro-repo) remote/origin/master@local >> master@local

Esistono due modi per eseguire il passaggio 2. È possibile:

  1. Esegui il fork della filiale locale dopo l'ultimo antenato comune e aggiungi nuovi commit in parallelo ai commit unici per il repository locale, finalizzati dalla fusione del commit, chiudendo il fork.
  2. Inserisci nuovi commit dopo l'ultimo antenato comune e riapplica i commit unici nel repository locale.

Nella gitterminologia, il passaggio 1 è git fetch, il passaggio 2 è git mergeogit rebase

git pullè git fetchegit merge


37

Git ottiene il ramo dell'ultima versione dal remoto al locale usando due comandi:

  1. git fetch: Git otterrà l'ultima versione da remoto a locale, ma non si unirà automaticamente.      git fetch origin master git log -p master..origin/master git merge origin/master

         I comandi sopra indicano che scarica l'ultima versione del ramo principale dall'origine dal ramo principale remoto a quello principale. Quindi confronta il ramo principale locale e il ramo principale di origine. Infine, unisci.

  2. git pull: Git otterrà l'ultima versione dal telecomando e si unirà al locale.

        git pull origin master

         Il comando sopra è l'equivalente di git fetche git merge. In pratica, git fetchforse più sicuro perché prima dell'unione possiamo vedere le modifiche e decidere se unire.


37

Qual è la differenza tra git pulle git fetch?

Per capirlo, devi prima capire che il tuo git locale mantiene non solo il tuo repository locale, ma mantiene anche una copia locale del repository remoto.

git fetchaggiorna la tua copia locale del repository remoto. Ad esempio, se il repository remoto è GitHub, è possibile che si desideri recuperare tutte le modifiche apportate nel repository remoto nella propria copia locale del repository remoto. Ciò ti consentirà di eseguire operazioni come confronto o unione.

git pulld'altra parte porterà le modifiche nel repository remoto a dove mantieni il tuo codice. In genere, git pulleseguirà una git fetchprima operazione per aggiornare la copia locale del repository remoto, quindi unirà le modifiche nel proprio repository di codice e possibilmente nella copia di lavoro.


35

git pull == (git fetch + git merge)

git fetch non cambia nelle filiali locali.

Se hai già un repository locale con una configurazione remota per il progetto desiderato, puoi prendere tutti i rami e i tag per il telecomando esistente usando git fetch. ... Fetch non apporta alcuna modifica alle filiali locali, quindi sarà necessario unire una filiale remota con una filiale locale accoppiata per incorporare le nuove modifiche di recupero. da github


34

Cercando di essere chiaro e semplice.

Il comando git pull è in realtà un comando shortcutfor git fetch seguito dal comando git merge o dal comando git rebase a seconda della configurazione. Puoi configurare il tuo repository Git in modo che git pull sia un recupero seguito da un rebase.


33

Una semplice rappresentazione grafica per principianti,

inserisci qui la descrizione dell'immagine

Qui,

git pull  

recupererà il codice dal repository e si rinnoverà con il tuo locale ... in git pull c'è la possibilità di creare nuovi commit.

ma in ,

git fetch

recupererà il codice dal repository e dobbiamo rifarlo manualmente usando git rebase

ad es .: vado a prendere dal server master e lo rifacerò nel mio master locale.

1) git pull (rebase verrà eseguito automaticamente):

git pull origin master

qui l' origine è il tuo repo master remoto è il tuo ramo

2) git fetch (necessità di rifare manualmente):

git fetch origin master

recupererà le modifiche del server dall'origine. e rimarrà nel tuo locale fino a quando non lo rifarai da solo. dobbiamo correggere manualmente i conflitti controllando i codici.

git rebase origin/master

questo ridisegnerà il codice in locale. prima assicurati di essere nel ramo giusto.


Bel grafico, ma potresti voler spiegare perché usi "rebase" quando il grafico dice "unisci".
Guntram Blohm sostiene Monica il

2
unione rappresenterà un altro commit di diramazione e produrrà un nuovo commit che contiene commit come riferimento. ma rebase replicherà i commit da un altro ramo e non creerà nuovi commit piuttosto che replicare
Mohideen bin Mohammed,

33

In realtà Git mantiene una copia del proprio codice e del repository remoto.

Il comando git fetchaggiorna la copia locale ottenendo i dati dal repository remoto. Il motivo per cui ne abbiamo bisogno è perché qualcun altro potrebbe aver apportato alcune modifiche al codice e si desidera tenersi aggiornati.

Il comando git pullporta le modifiche nel repository remoto in cui si conserva il proprio codice. Normalmente, git pulleseguendo prima un 'git fetch' per aggiornare la copia locale del repository remoto, quindi unisce le modifiche nel proprio repository di codice e possibilmente nella copia di lavoro.

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.