Perché git status mostra che branch è aggiornato quando esistono modifiche a monte?


226

Le modifiche esistono a monte in un ramo tracciato, ma quando scrivo git statusindica che il mio ramo locale è aggiornato. Questo nuovo comportamento, ho modificato un'impostazione di configurazione o qualcosa non va?

Grazie per l'aiuto.

ubuntu@host:/my/repo# git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean


ubuntu@host:/my/repo# git pull
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From bitbucket.org:my/repo
   1234567..abcdefg  master     -> origin/master
Updating 1234567..abcdefg
Fast-forward
 file1        |  1 -
 file2        | 43 +++++++++++++++++++++++++++++++++++++++++++
 file3        | 21 ++++++++++++---------
 file4        | 21 ++++++++++++---------
 4 files changed, 67 insertions(+), 19 deletions(-)
 create mode 100644 file5

Risposte:


274

Ciò che lo stato ti sta dicendo è che sei dietro l'arbitro chiamato origin/master che è un riferimento locale nel tuo repository locale . In questo caso, ref rintraccia un ramo in qualche telecomando, chiamato origin, ma lo stato non ti dice nulla sul ramo sul telecomando. Ti sta parlando dell'arbitro, che è solo un ID commit memorizzato sul tuo filesystem locale (in questo caso, è in genere in un file chiamato .git/refs/remotes/origin/masternel tuo repository locale).

git pullesegue due operazioni; prima fa un git fetchaggiornamento per i commit nel repository remoto (che aggiorna il origin/masterref nel repository locale), quindi fa un git mergeper unire tali commit nel ramo corrente.

Fino a quando non si esegue il fetchpassaggio (da solo o tramite git pull) il repository locale non ha modo di sapere che ci sono ulteriori commit a monte e git statusguarda solo il riferimento locale origin/master.

Quando git statusdice aggiornato, significa "aggiornato con il ramo che il ramo corrente tiene traccia", che in questo caso significa "aggiornato con il riferimento locale chiamato origin/master". Ciò equivale solo a "aggiornato con lo stato upstream che è stato recuperato l'ultima volta che abbiamo eseguito un fetch" che non è lo stesso di "aggiornato con l'ultimo stato live dell'upstream".

Perché funziona in questo modo? Bene, il fetchpassaggio è un'operazione di rete potenzialmente lenta e costosa. Il design di Git (e di altri sistemi di controllo della versione distribuita ) è di evitare le operazioni di rete quando non necessario, ed è un modello completamente diverso dal tipico sistema client-server a cui molte persone sono abituate (sebbene, come sottolineato nei commenti sotto, il concetto di Git di un "ramo di tracciamento remoto" che causa confusione qui non è condiviso da tutti i DVCS). È del tutto possibile utilizzare Git offline, senza connessione a un server centralizzato, e l'output di git statusriflette questo.

La creazione e il cambio di rami (e il controllo del loro stato) in Git dovrebbero essere leggeri, non qualcosa che esegue un'operazione di rete lenta verso un sistema centralizzato. Il presupposto durante la progettazione di Git e git statusdell'output era che gli utenti lo capiscono (troppe funzionalità di Git hanno senso solo se sai già come funziona Git). Con l'adozione di Git da parte di molti e molti utenti che non hanno familiarità con DVCS questo presupposto non è sempre valido.


79
Un commento in ritardo ma mi sono imbattuto nella stessa situazione. Capisco perché git non ha modo di conoscere le modifiche prima del recupero. Ma allora non dovrebbe dire "aggiornato" che semplicemente non è vero. Meglio dire "non ho idea di cosa potrebbe essere successo a distanza".
Droidum,

31
Forse è strettamente logico, ma non è affatto umano-ragionevole. Perché non lo progetteresti per fare un recupero e poi dichiarare se è aggiornato? O cambia il messaggio per dire cosa ha realmente fatto, ad es. "La tua filiale era aggiornata con 'origin / master' l'ultima volta che hai controllato su {timestamp}"? O anche solo dire "Fai un recupero per scoprire se il tuo ramo è aggiornato"?
Colin maggio

25
perché preoccuparsi di mostrare il messaggio "La tua filiale è aggiornata"? Non vedo il punto di conoscere lo stato di origine / master e se si suppone che rappresenti l'attuale ramo master sul telecomando di origine, allora chiaramente non ne ha idea.
whiterook6,

2
@pastullo, quindi crea un alias.
Jonathan Wakely,

23
Questo è un perfetto esempio dell'orribile usabilità di Git. Adoro la sua potenza e flessibilità, ma semplicemente cambiando il messaggio in qualcosa del tipo "Il tuo ramo è aggiornato con la versione locale di 'origin / master'." sarebbe un enorme miglioramento. La confusione qui è che l'origine / master del ramo locale (il modello corrisponde a qualsiasi telecomando / ramo che stai usando) che tiene traccia di un ramo remoto.
Matthewcummings

35

Questo perché il repository locale non ha effettuato il check-in con i telecomandi upstream. Per fare in modo che funzioni come previsto, utilizzare git fetchquindi eseguire git statusnuovamente.


7

Mentre queste sono tutte risposte valide, ho deciso di dare il mio modo di verificare se il repository locale è in linea con il telecomando, senza recuperare o tirare. Per vedere dove sono i miei rami uso semplicemente:

git remote show origin

Ciò che fa è restituire tutti i rami tracciati correnti e, soprattutto, le informazioni se sono aggiornati, in anticipo o dietro quelli di origine remota. Dopo il comando precedente, questo è un esempio di ciò che viene restituito:

  * remote origin
  Fetch URL: https://github.com/xxxx/xxxx.git
  Push  URL: https://github.com/xxxx/xxxx.git
  HEAD branch: master
  Remote branches:
    master      tracked
    no-payments tracked
  Local branches configured for 'git pull':
    master      merges with remote master
    no-payments merges with remote no-payments
  Local refs configured for 'git push':
    master      pushes to master      (local out of date)
    no-payments pushes to no-payments (local out of date)

Spero che questo aiuti qualcuno.


0

"origine / master" si riferisce al riferimento di riferimento al commit HEAD del ramo "origine / master". Un riferimento è un nome alias umano-friendly per un oggetto Git, in genere un oggetto commit. Il riferimento "origine / master" viene aggiornato solo quando si è git pushsul telecomando ( http://git-scm.com/book/en/v2/Git-Internals-Git-References#Remotes ).

Dalla radice del tuo progetto, esegui:

cat .git/refs/remotes/origin/master

Confronta l'ID commit visualizzato con:

cat .git/refs/heads/master

Dovrebbero essere uguali, ed è per questo che Git dice che masterè aggiornato origin/master.

Quando corri

git fetch origin master

Che recupera i nuovi oggetti Git localmente nella cartella .git / objects. E Git aggiorna .git / FETCH_HEAD in modo che ora punti all'ultimo commit del ramo recuperato.

Quindi, per vedere le differenze tra il tuo attuale ramo locale e il ramo recuperato dall'upstream, puoi eseguire

git diff HEAD FETCH_HEAD

1
Non dovresti cercare gli oggetti nella directory .git, non funzionerà con i ref compressi. Anche il comportamento di recupero che hai descritto è per le versioni precedenti di git.
Andrew C,

l' origin/masterarbitro non viene aggiornato anche da un recupero, oltre che da una spinta?
Jonathan Wakely

Corretta. Finora stavo usando Git 1.8.3. Posso notare infatti con la versione 2.2.1, FETCH_HEAD viene aggiornato anche durante un recupero. Anche quando si tratta del messaggio "Il tuo ramo è aggiornato con ..." o "Il tuo ramo è dietro ... per X commit", viene visualizzato solo se il tuo ramo locale tiene traccia di un determinato ramo remoto. Affinché il master rintracci origine / master, è necessario eseguire git branch -u origin / master dal branch master. Se non c'è tracciamento, è comunque necessario eseguire git diff.
Marek Stanley,

Bene, allora ti suggerisco di correggere l'affermazione secondo cui "il riferimento" origine / master "viene aggiornato solo quando passi sul tuo telecomando"
Jonathan Wakely,

0

Lasciate sguardo in un repo git campione per verificare se your branch (master)è up to datecon origin/master.

Verifica che il master locale stia monitorando origine / master:

$ git branch -vv
* master a357df1eb [origin/master] This is a commit message

Ulteriori informazioni sulla filiale principale locale:

$ git show --summary
commit a357df1eb941beb5cac3601153f063dae7faf5a8 (HEAD -> master, tag: 2.8.0, origin/master, origin/HEAD)
Author: ...
Date:   Tue Dec 11 14:25:52 2018 +0100

    Another commit message

Verifica se origin / master è sullo stesso commit:

$ cat .git/packed-refs | grep origin/master
a357df1eb941beb5cac3601153f063dae7faf5a8 refs/remotes/origin/master

Possiamo vedere lo stesso hash in giro, e sicuro di dire che il ramo è coerente con quello remoto, almeno nell'attuale repository git.



0

Risposta fondamentale ma accurata in alcuni casi, come quella che mi ha portato qui. Stavo lavorando in un repository che era nuovo per me e ho aggiunto un file che non è stato visto come nuovo dallo stato.

Si conclude che il file corrispondeva a un modello nel file .gitignore.


0

in questo caso usa git add e integra tutti i file in sospeso e quindi usa git commit e poi git push

git add - integra tutti i file pedent

git commit - salva il commit

git push - salva nel repository

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.