Por que o status do git mostra que o branch está atualizado quando existem alterações no upstream?

226

Existem alterações a montante em uma ramificação rastreada, mas quando digito, git statusisso indica que minha ramificação local está atualizada. Esse é um novo comportamento, alterei uma configuração ou algo está errado?

Obrigado pela ajuda.

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
GregB
fonte

Respostas:

274

O que o status está dizendo é que você está atrás do árbitro chamado, origin/master que é um árbitro local no seu repositório local . Nesse caso, ref faz o rastreamento de uma filial em algum controle remoto, chamado origin, mas o status não está informando nada sobre a filial no controle remoto. Ele está falando sobre a ref, que é apenas um ID de confirmação armazenado em seu sistema de arquivos local (nesse caso, normalmente está em um arquivo chamado .git/refs/remotes/origin/masterem seu repositório local).

git pullfaz duas operações; primeiro, ele faz git fetcha atualização das confirmações no repositório remoto (que atualiza a origin/masterreferência no repositório local) e, em seguida, faz git mergea mesclagem dessas confirmações na ramificação atual.

Até você executar a fetchetapa (por conta própria ou via git pull), seu repositório local não tem como saber que existem confirmações adicionais a montante e git statusapenas analisa a origin/masterreferência local .

Quando git statusatualizado, significa "atualizado com a ramificação que a ramificação atual rastreia", que neste caso significa "atualizado com a referência local chamada origin/master". Isso equivale a "atualizado com o status upstream que foi recuperado da última vez que fizemos um fetch" que não é o mesmo que "atualizado com o status ao vivo mais recente do upstream".

Por que funciona dessa maneira? Bem, o fetchpasso é uma operação de rede potencialmente lenta e cara. O design do Git (e outros sistemas de controle de versão distribuído ) é evitar operações de rede quando desnecessárias e é um modelo completamente diferente do sistema cliente-servidor típico ao qual muitas pessoas estão acostumadas (embora, como indicado nos comentários abaixo, o conceito do Git de um "ramo de rastreamento remoto" que causa confusão aqui não é compartilhado por todos os DVCSs). É totalmente possível usar o Git offline, sem conexão com um servidor centralizado, e a saída git statusreflete isso.

Criar e alternar ramificações (e verificar seu status) no Git deve ser leve, não algo que execute uma operação de rede lenta para um sistema centralizado. A suposição ao projetar o Git, e a git statussaída, era que os usuários entendessem isso (muitos recursos do Git só fazem sentido se você já sabe como o Git funciona). Com a adoção do Git por muitos e muitos usuários que não estão familiarizados com o DVCS, essa suposição nem sempre é válida.

Jonathan Wakely
fonte
79
Um comentário tardio, mas me deparei com a mesma situação. Entendo por que o git não tem como saber sobre as alterações antes da busca. Mas então não deve dizer "atualizado", o que simplesmente não é verdade. É melhor dizer "não faço ideia do que poderia ter acontecido remotamente".
Droidum
31
Talvez seja estritamente lógico, mas não é de todo humano. Por que você não o projetou para fazer uma busca e então declara se está atualizado? Ou altere a mensagem para informar o que realmente fez, por exemplo, "Seu ramo estava atualizado com 'origem / mestre' quando foi verificado pela última vez em {timestamp}"? Ou até mesmo diga: "Faça uma busca para descobrir se sua filial está atualizada"?
Colin May
25
por que se incomodar em exibir a mensagem "Sua filial está atualizada"? Não vejo sentido em saber o status da origem / mestre e, se é suposto representar a ramificação mestre real no controle remoto de origem, claramente não faz ideia de qualquer maneira.
whiterook6
2
@pastullo, então crie um alias.
Jonathan Wakely
23
Este é um exemplo perfeito da horrível usabilidade do Git. Adoro seu poder e flexibilidade, mas simplesmente altero a mensagem para algo como "Sua filial está atualizada com a versão local de 'origem / mestre'". seria uma grande melhoria. A confusão aqui é que a origem / mestre da ramificação local (o padrão corresponde aos controles / ramificações que você estiver usando) que rastreiam uma ramificação remota.
precisa
35

Isso ocorre porque seu repositório local não fez check-in com os controles remotos upstream. Para ter esse trabalho como você espera, use git fetche execute git statusnovamente.

Ryan
fonte
7

Embora todas sejam respostas viáveis, decidi dar uma maneira de verificar se o repo local está alinhado com o controle remoto, sem buscar ou puxar. Para ver onde estão meus galhos, uso simplesmente:

git remote show origin

O que ele faz é retornar todos os ramos rastreados atuais e, o mais importante - as informações estejam atualizadas, à frente ou atrás dos de origem remota. Após o comando acima, este é um exemplo do que é retornado:

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

Espero que isso ajude alguém.

Skycube
fonte
0

"origem / mestre" refere-se à referência feita ao commit HEAD da ramificação "origem / mestre". Uma referência é um nome alternativo compatível com humanos para um objeto Git, geralmente um objeto de confirmação. A referência "origem / mestre" é atualizada somente quando você está git pushno seu controle remoto ( http://git-scm.com/book/en/v2/Git-Internals-Git-References#Remotes ).

De dentro da raiz do seu projeto, execute:

cat .git/refs/remotes/origin/master

Compare o ID de confirmação exibido com:

cat .git/refs/heads/master

Eles devem ser os mesmos, e é por isso que o Git diz que masterestá atualizado origin/master.

Quando você corre

git fetch origin master

Isso recupera novos objetos Git localmente na pasta .git / objects. E o Git atualiza .git / FETCH_HEAD para que agora aponte para o último commit da ramificação buscada.

Portanto, para ver as diferenças entre sua filial local atual e a filial buscada a montante, você pode executar

git diff HEAD FETCH_HEAD
Marek Stanley
fonte
1
Você não deve colocar itens no diretório .git, pois ele não funcionará com referências compactadas. Além disso, o comportamento de busca que você descreveu é para versões mais antigas do git.
Andrew C
o origin/masterjuiz também não é atualizado por uma busca e por um empurrão?
Jonathan Wakely,
Corrigir. Eu estava usando o Git 1.8.3 até agora. Percebo que, com a versão 2.2.1, FETCH_HEAD também é atualizado durante uma busca. Além disso, quando se trata da mensagem "Sua ramificação está atualizada com ..." ou "Sua ramificação está atrasada ... por X confirma", ela será exibida apenas se a ramificação local rastrear uma ramificação remota. Para que o mestre rastreie a origem / mestre, é necessário executar o git branch -u origin / master no branch master. Se não houver rastreamento, você ainda precisará executar o git diff.
Marek Stanley
Bem, então eu sugiro que você corrija a afirmação de que a referência '' origin / master '' só é atualizada quando você pressiona o git no controle remoto ''
Jonathan Wakely
0

Vamos analisar um exemplo de repositório git para verificar se your branch (master)está up to datecom origin/master.

Verifique se o mestre local está rastreando a origem / mestre:

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

Mais informações sobre a filial principal local:

$ 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

Verifique se a origem / mestre está no mesmo commit:

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

Podemos ver o mesmo hash ao redor, e é seguro dizer que o branch está em consistência com o remoto, pelo menos no atual repositório git.

themefield
fonte
0

tente com git add .antesgit commit

Dejan Baric llevo3
fonte
0

Resposta trivial, porém precisa, em alguns casos, como o que me trouxe aqui. Eu estava trabalhando em um repositório novo para mim e adicionei um arquivo que não era visto como novo pelo status.

Conclui que o arquivo correspondeu a um padrão no arquivo .gitignore.

krustyengineer
fonte
0

neste caso, use git add e integre todos os arquivos pendentes e, em seguida, use git commit e git push

git add - integra todos os arquivos pedent

git commit - salva o commit

git push - salva no repositório

Airton Silveira
fonte