Por que chamar git branch --unset-upstream para correção?


161

Eu sou mais novato quando se trata de operações avançadas no git. Eu mantenho meu blog usando a estrutura de blogs Octopress . Embora o Octopress não esteja em desenvolvimento desde 2011, ele serve bem ao meu propósito e, portanto, não pensei em mudar nada até agora.

Para sua informação, meu blog está hospedado nas páginas do Github.

Hoje, enquanto trabalhava em uma nova postagem, git statusmostrou a seguinte mensagem:

On branch source
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)

A mesma mensagem repetida para todos os comandos subseqüentes, como git add ., git commit -m 'message'e git push origin source.

  • O que a mensagem significa?
  • Algo está quebrado?
  • Se sim, o que?
  • Preciso corrigi-lo?

Se possível, indique-me um artigo em pdf / web onde eu possa ler sobre isso e entendê-lo para o futuro.

Mais detalhes:

bash-3.2$ git branch -a
* source
  remotes/octopress/2.1
  remotes/octopress/HEAD -> octopress/master
  remotes/octopress/gh-pages
  remotes/octopress/linklog
  remotes/octopress/master
  remotes/octopress/refactor_with_tests
  remotes/octopress/rubygemcli
  remotes/octopress/site
  remotes/origin/source

Entre em contato se precisar de mais informações. Obrigado.

Respostas:


197

Versão TL; DR: a ramificação de rastreamento remoto origin/mastercostumava existir, mas não existe agora, portanto a ramificação local sourceestá rastreando algo que não existe, o que é suspeito na melhor das hipóteses - significa que um recurso Git diferente não pode fazer nada por você - e Git está avisando sobre isso. Você está se dando muito bem sem que o recurso "rastreamento upstream" funcione conforme o esperado, portanto, é sua decisão alterar alguma coisa.

Para outra opinião sobre as configurações upstream, consulte Por que eu tenho que "git push --set-upstream origin <branch>"?


Esse aviso é uma novidade no Git, aparecendo primeiro no Git 1.8.5. As notas de versão contêm apenas um pequeno item sobre ele:

  • "git branch -v -v" (e "git status") não fez distinção entre uma ramificação que não se baseia em nenhuma outra ramificação, uma ramificação que esteja sincronizada com sua ramificação upstream e uma ramificação configurada com uma ramificação upstream ramo que não existe mais.

Para descrever o que isso significa, primeiro você precisa saber sobre "controles remotos", "ramificações de rastreamento remoto" e como o Git lida com "rastrear um upstream". ( Ramificações de rastreamento remoto é um termo terrivelmente defeituoso - comecei a usar nomes de rastreamento remoto , o que acho que é uma pequena melhoria. Abaixo, porém, usarei "ramificação de rastreamento remoto" para garantir a consistência com a documentação do Git. )

Cada "remoto" é simplesmente um nome, como originou octopressneste caso. O objetivo deles é registrar coisas como o URL completo dos locais dos quais você git fetchou git pullatualiza. Quando você usa o 1 Git, acessa esse controle remoto (usando a URL salva) e traz o conjunto apropriado de atualizações. Ele também registra as atualizações usando "ramificações de rastreamento remoto".git fetch remote,

Um "ramo de rastreamento remoto" (ou nome de rastreamento remoto) é simplesmente uma gravação de um nome de ramo como visto pela última vez em alguns "remotos". Cada controle remoto é um repositório Git, portanto, possui ramificações. As ramificações na "origem" remota são registradas no seu repositório local em remotes/origin/. O texto que mostrou diz que há um ramo chamado sourceem origine ramos chamado 2.1, linkloge assim por diante no octopress.

(Uma ramificação "normal" ou "local", é claro, é apenas um nome de ramificação que você criou em seu próprio repositório.)

Por fim, você pode configurar uma ramificação (local) para "rastrear" uma "ramificação de rastreamento remoto". Depois que o ramo local Lestiver definido para rastrear o ramo de rastreamento remoto R, o Git chamará Rseu "upstream" e informará se você está "à frente" e / ou "atrás" do upstream (em termos de confirmações). É normal (mesmo recomendável) que a filial local e as ramificações de rastreamento remoto usem o mesmo nome (exceto a parte do prefixo remoto), como sourcee origin/source, mas isso não é realmente necessário.

E neste caso, isso não está acontecendo. Você tem uma filial local que sourcerastreia uma filial de rastreamento remoto origin/master.

Você não precisa saber a mecânica exata de como o Git configura uma ramificação local para rastrear uma ramificação remota, mas elas são relevantes abaixo, então mostrarei como isso funciona. Começamos com o nome da sua filial local source,. Existem duas entradas de configuração usando esse nome, ortografado branch.source.remotee branch.source.merge. A partir da saída que você mostrou, é claro que ambos estão definidos, para que você veja o seguinte se executar os comandos fornecidos:

$ git config --get branch.source.remote
origin
$ git config --get branch.source.merge
refs/heads/master

Juntando isso, 2 isso indica ao Git que seu ramo sourcerastreia o seu "ramo de rastreamento remoto" origin/master,.

Mas agora observe a saída de git branch -a, que mostra todos os nomes de ramificações de rastreamento local e remoto em seu repositório. Os nomes de rastreamento remoto estão listados em remotes/... e não háremotes/origin/master . Presumivelmente, houve uma vez, mas agora se foi.

O Git está lhe dizendo que você pode remover as informações de rastreamento --unset-upstream. Isso limpará ambos branch.source.origine branch.source.merge, e interromperá o aviso.

Parece bastante provável que o que você deseja, porém, seja mudar de rastreamento origin/master, para rastrear outra coisa: provavelmente origin/source, mas talvez um dos octopress/nomes.

Você pode fazer isso com git branch --set-upstream-to, 3 por exemplo:

$ git branch --set-upstream-to=origin/source

(supondo que você ainda esteja na "origem" da ramificação, e esse origin/sourceé o fluxo que você deseja - não há como eu dizer qual, se houver, você realmente deseja).

(Veja também Como você faz com que uma ramificação Git existente rastreie uma ramificação remota? )

Eu acho que o jeito que você chegou aqui é que, quando você fez o primeiro git clone, a coisa da qual você clonou tinha um ramo master. Você também tinha uma ramificação masterque foi configurada para rastrear origin/master(esta é uma configuração normal e padrão para o git). Isso significava que você tinha branch.master.remotee branch.master.mergedefinia, para origine refs/heads/master. Mas então o seu origincontrole remoto mudou seu nome de masterpara source. Para corresponder, acredito que você também alterou seu nome local de masterpara source. Isso alterou os nomes das suas configurações, de branch.master.remotepara branch.source.remotee de branch.master.mergepara branch.source.merge... mas deixou os valores antigos , branch.source.mergeagora estava errado.

Foi nesse ponto que a ligação "upstream" quebrou, mas nas versões Git anteriores à 1.8.5, o Git nunca percebeu a configuração quebrada. Agora que você tem 1.8.5, está apontando isso.


Isso cobre a maioria das perguntas, mas não a pergunta "preciso corrigir isso". É provável que você tenha trabalhado em torno do quebrantamento há anos, fazendo (por exemplo, ). Se você continuar fazendo isso, ele continuará solucionando o problema - então, não, você não precisará corrigi-lo. Se desejar, você pode remover o montante e interromper as reclamações e não ter uma filial local marcada como tendogit pull remote branchgit pull origin source--unset-upstreamsource qualquer montante.

O ponto de ter um upstream é tornar várias operações mais convenientes. Por exemplo, git fetchseguido por git mergegeralmente "fará a coisa certa" se o upstream estiver definido corretamente egit status depois git fetchinformará se o seu repo corresponde ao upstream, para esse ramo.

Se você quiser a conveniência, redefina o upstream.


1git pull usa git fetche, a partir do Git 1.8.4, isso (finalmente!) Também atualiza as informações de "filial de rastreamento remoto". Nas versões mais antigas do Git, as atualizações não eram registradas em ramificações de rastreamento remoto git pull, apenas comgit fetch . Como seu Git deve ter pelo menos a versão 1.8.5, isso não é um problema para você.

2 Bem, isso mais uma linha de configuração que eu estou deliberadamente ignorando que é encontrada em remote.origin.fetch. O Git precisa mapear o nome "mesclar" para descobrir que o nome local completo da ramificação remota é refs/remotes/origin/master. O mapeamento quase sempre funciona assim, portanto, é previsível que isso masterocorra origin/master.

3 Ou com git config. Se você apenas deseja configurar o upstream para origin/sourcea única parte que precisa ser alterada branch.source.merge, e o git config branch.source.merge refs/heads/source faria. Mas --set-upstream-todiz o que você quer fazer, em vez de fazê-lo manualmente, por isso é uma "maneira melhor".


3
+1 em "Se desejar, você pode usar --unset-upstream para que a ramificação local seja marcada como não tendo nenhum upstream".
BeatriceThalo

157

a resposta de torek provavelmente é perfeita, mas eu queria que o registro mencionasse outro caso diferente do descrito na pergunta original, mas o mesmo erro pode aparecer (pois pode ajudar outras pessoas com problemas semelhantes):

Eu criei um repo vazio (novo) usando git init --bareem um dos meus servidores. Então eu o coloquei git cloneem um espaço de trabalho local no meu PC.

Depois de confirmar uma única versão no repositório local, recebi esse erro depois de ligar git status.

Após a resposta da torek, entendo que o que aconteceu foi que o primeiro commit no repositório de diretório de trabalho local criou uma ramificação "master". Mas no repositório remoto (no servidor) nunca havia nada, portanto não havia nem mesmo um ramo "mestre" (controles remotos / origem / mestre).

Depois de executar a git push origin masterpartir do repositório local, o repositório remoto finalmente teve uma ramificação principal. Isso parou o erro de aparecer.

Então, para concluir - pode-se obter esse erro para um novo repo remoto com zero confirmações, uma vez que não possui ramificação, incluindo "master".


6
Atualmente, este é o resultado nº 1 desta mensagem de erro On branch source Your branch is based on 'origin/master', but the upstream is gone. (use "git branch --unset-upstream" to fixup)e, embora subjetivo, é mais provável que seja causado pela clonagem de um repositório vazio tão bom que você terá uma resposta alternativa aqui.
Bella

2
Eu acho que é por isso que é sempre uma boa idéia para inicializar seu novo repositório com o arquivo README.md, mesmo que seja um arquivo vazio
Ahmed Hussein

8

Isso pode resolver seu problema.

depois de fazer alterações, você pode confirmar e depois

git remote add origin https://(address of your repo) it can be https or ssh
then
git push -u origin master

espero que funcione para você.

obrigado


1
Isso realmente ajudaria - o motivo está detalhado na minha resposta (em resumo - isso cria o ramo mestre ausente no repositório remoto).
precisa saber é o seguinte

7

Para mim, .git/refs/origin/masterficou corrompido.

Fiz o seguinte, que corrigiu o problema para mim.

rm .git/refs/remotes/origin/master
git fetch
git branch --set-upstream-to=origin/master

0

Na verdade, a Torek já lhe disse como usar as ferramentas muito melhor do que eu seria capaz de fazer. No entanto, neste caso, acho importante ressaltar algo peculiar se você seguir as diretrizes em http://octopress.org/docs/deploying/github/ . Ou seja, você terá vários repositórios do github em sua configuração. Primeiro, aquele com todo o código-fonte do seu site, digamos o diretório $WEBSITE, e depois aquele com apenas os arquivos estáticos gerados residindo $WEBSITE/_deploy. O engraçado da configuração é que há um .gitignorearquivo no $WEBSITEdiretório para que essa configuração realmente funcione.

Chega de introdução. Nesse caso, o erro também pode vir do repositório em _deploy.

cd _deploy

git branch -a
* master
remotes/origin/master
remotes/origin/source

Em .git/confignormalmente você vai precisar encontrar algo como isto:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = git@github.com:yourname/yourname.github.io.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

Mas no seu caso, o mestre da filial não possui um controle remoto.

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = git@github.com:yourname/yourname.github.io.git
    fetch = +refs/heads/*:refs/remotes/origin/*

Que você pode resolver:

cd _deploy
git branch --set-upstream-to=origin/master

Portanto, tudo está como lhe foi dito, mas talvez seja importante ressaltar que isso pode muito bem dizer respeito ao _deploydiretório, e não à raiz do seu site.

PS: Pode valer a pena usar um shell como zshum gitplug-in para não ser mordido por essa coisa no futuro. Ele mostrará imediatamente que se _deployrefere a um repositório diferente.


0

Eu tive essa pergunta duas vezes e sempre foi causada pela corrupção do arquivo de cache do git na minha filial local. Corrigi-o escrevendo o hash de confirmação ausente nesse arquivo. Eu obtive o hash de confirmação correto do servidor e executei o seguinte comando localmente:

cat .git/refs/remotes/origin/feature/mybranch \
echo 1edf9668426de67ab764af138a98342787dc87fe \
>> .git/refs/remotes/origin/feature/mybranch

0

Problema: sua filial é baseada em 'origem / mestre', mas o upstream desapareceu.

Solução: git branch --unset-upstream


3
Bem-vindo ao stackoverflow. A questão não é sobre como o erro pode ser corrigido, ele quer saber por que esse erro foi causado e se deve fazer algo a respeito. Por favor, resolva isso em sua resposta.
cronoik

0

exclua sua filial local seguindo o comando

git branch -d branch_name

você também poderia fazer

git branch -D branch_name 

que basicamente força uma exclusão (mesmo que o local não seja mesclado à origem)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.