'Git Pull Origin Mybranch' deixa o MyBranch N se compromete à frente da origem. Por quê?

StackOverflow https://stackoverflow.com/questions/1741143

  •  20-09-2019
  •  | 
  •  

Pergunta

Acabei de observar algo estranho sobre git pull, o que eu não entendo.

Na sexta -feira, trabalhei em uma filial local. Vamos chamá -lo mybranch. Antes de sair do escritório, empurrei -o para a origem (que é o meu repo Github): git push origin mybranch.

Ontem em casa, eu pullEd Mybranch para o meu laptop, fez mais codificação e depois empurrou minhas alterações de volta ao Github (origem).

Agora estou no trabalho novamente e tentei puxar as mudanças de ontem para minha máquina de trabalho (não mudei nada no repositório local do meu local de trabalho no fim de semana):

git pull origin mybranch

Isso causou uma mesclagem rápida, o que é bom. Eu então fiz um git status, e disse:

# On branch mybranch
# Your branch is ahead of 'origin/mybranch' by 6 commits.
#
nothing to commit (working directory clean)

Huh? Como pode ser 6 começos à frente quando eu nem tocei no fim de semana e acabou de sair da origem? Então eu corri um git diff origin/mybranch E os diferenciais foram exatamente as 6 alterações que acabei de retirar do controle remoto.

Eu só poderia "consertar" isso correndo git fetch origin:

From git@github.com:me/project
af8be00..88b0738  mybranch -> origin/mybranch

Aparentemente, meu repositório local estava faltando alguns objetos de referência, mas como isso pode ser? Quero dizer, uma atração já faz uma busca, e eu não trabalhei em nada, exceto naquele ramo, então um git fetch origin e git fetch origin mybranch deve ter o mesmo resultado?

Devo sempre usar git pull origin ao invés de git pull origin branchname?

Estou confuso.

Foi útil?

Solução

git pull chamadas git fetch com os parâmetros apropriados antes de mesclar as cabeças explicitamente buscadas (ou se nenhuma a ramificação remota configurada para mesclar) na ramificação atual.

A sintaxe: git fetch <repository> <ref> Onde <ref> é apenas um nome de ramo sem cólon é uma busca de 'tiro' que não faz uma busca padrão de todos os galhos rastreados do controle remoto especificado, mas, em vez disso, pega apenas o ramo nomeado em FETCH_HEAD.

Atualizar: Para versões Git desde 1.8.4, se houver uma filial de rastreamento remoto que rastreie o árbitro que você pediu para buscar, o ramo de rastreamento será atualizado agora por fetch. Essa mudança foi feita especificamente para evitar a confusão que o comportamento anterior causou.

Quando você se apresenta git pull <repository> <ref>, FETCH_HEAD é atualizado como acima e depois fundido no seu check -out HEAD Mas nenhuma das filiais de rastreamento padrão para o repositório remoto será atualizada (git <1.8.4). Isso significa que localmente parece Como você está à frente do ramo remoto, enquanto na verdade você está atualizado com ela.

Pessoalmente eu sempre faço git fetch Seguido por git merge <remote>/<branch> Porque eu consigo ver quaisquer avisos sobre atualizações forçadas antes de me fundir, e posso visualizar o que estou se fundindo. Se eu usasse git pull um pouco mais do que eu, eu faria uma planície git pull sem parâmetros na maioria das vezes, confiando branch.<branch>.remote e branch.<branch>.merge para 'fazer a coisa certa'.

Outras dicas

O que git remote -v show retorna quando se trata de origem?

Se a origem apontar para o GitHub, o status deve estar atualizado, e não antes de qualquer repo remoto. Pelo menos, com o Git1.6.5, estou usando para um teste rápido.

De qualquer forma, para evitar isso, defina explicitamente o repositório remoto do Master Branch:

$ git config branch.master.remote yourGitHubRepo.git

então uma git pull origin master, seguido por um git status deve retornar um status limpo (sem a frente).
Por quê? Porque o mestre de origem get fetch (incluído no mestre de origem do git) não apenas atualizaria FETCH_HEAD (Como Charles Bailey explica em sua resposta), mas isso também Atualize a "ramificação mestre remota" no seu repositório Git local.
Nesse caso, seu mestre local não parece mais "à frente" do mestre remoto.


Eu posso testar isso, com um git1.6.5:

Primeiro eu crio um workrepo:

PS D:\git\tests> cd pullahead
PS D:\git\tests\pullahead> git init workrepo
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/
PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt
PS D:\git\tests\pullahead\workrepo> git add -A 
PS D:\git\tests\pullahead\workrepo> git commit -m "first commit"

Eu simula um repo do github criando um repo nu (que pode receber um empurrão de qualquer lugar)

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone --bare workrepo github

Adicionei um modif ao meu repositório de trabalho, que pressiono para o repo do GitHub (adicionado como um controle remoto)

PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt
PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github"
PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo> git push github

Eu crio um repositório doméstico, clonado de github, no qual faço algumas modificações, empurrado para o Github:

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone github homerepo
PS D:\git\tests\pullahead> cd homerepo
PS D:\git\tests\pullahead\homerepo> type afile.txt
firstContent
aModif

PS D:\git\tests\pullahead\homerepo> echo aHomeModif1  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif"
PS D:\git\tests\pullahead\homerepo> echo aHomeModif2  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif"
PS D:\git\tests\pullahead\homerepo> git push github

Eu clono então WorkRepo para um primeiro experimento

PS D:\git\tests\pullahead\workrepo4> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo2
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/
PS D:\git\tests\pullahead> cd workrepo2
PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo2> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)

Nesse repositório, o status do Git menciona o mestre geing à frente de 'origin':

PS D:\git\tests\pullahead\workrepo5> git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)

Mas isso é apenas origin não é github:

PS D:\git\tests\pullahead\workrepo2> git remote -v show
github  d:/git/tests/pullahead/github (fetch)
github  d:/git/tests/pullahead/github (push)
origin  D:/git/tests/pullahead/workrepo (fetch)
origin  D:/git/tests/pullahead/workrepo (push)

Mas se eu repetir a sequência em um repositório que tem uma origem no Github (ou nenhuma origem, apenas um 'github' remoto definido), o status é limpo:

PS D:\git\tests\pullahead\workrepo2> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo4
PS D:\git\tests\pullahead> cd workrepo4
PS D:\git\tests\pullahead\workrepo4> git remote rm origin
PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo4> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
PS D:\git\tests\pullahead\workrepo4> git status
# On branch master
nothing to commit (working directory clean)

Se eu tivesse apenas origin apontando github, status Seria limpo para Git1.6.5.
Pode ser com um aviso 'à frente' para o Git anterior, mas de qualquer maneira, um git config branch.master.remote yourGitHubRepo.git definido explicitamente deve ser capaz de cuidar disso, mesmo com versões iniciais do Git.

Você tem o cuidado de adicionar todo o seu controle remoto (exceto origin que vem com seu clone original) usando git remote add NAME URL? Eu já vi esse bug quando eles acabaram de ser adicionados à configuração do Git.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top