Pourquoi appeler git branch --unset-upstream pour réparer?


161

Je suis plus novice en ce qui concerne les opérations avancées dans git. Je maintiens mon blog en utilisant le framework de blogs Octopress . Bien qu'Octopress ne soit pas en développement depuis 2011, cela sert bien mon objectif et je n'ai donc pas pensé à changer quoi que ce soit jusqu'à présent.

Pour info, mon blog est hébergé sur les pages Github.

Aujourd'hui, tout en travaillant sur un nouveau message, a git statusmontré le message suivant:

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

Le même message est répété pour toutes les commandes suivantes telles que git add ., git commit -m 'message'et git push origin source.

  • Que signifie le message?
  • Quelque chose est cassé?
  • Si oui, quoi?
  • Dois-je le réparer?

Si possible, veuillez me diriger vers un article pdf / web où je peux lire à ce sujet et le comprendre pour l'avenir.

Plus de détails:

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

Veuillez me faire savoir si plus d'informations sont nécessaires. Merci.

Réponses:


197

TL; version DR: la branche de suivi à distance origin/masterexistait autrefois, mais elle n'existe pas maintenant, donc la branche locale sourcesuit quelque chose qui n'existe pas, ce qui est au mieux suspect - cela signifie qu'une fonctionnalité Git différente ne peut rien faire pour vous - et Git vous en avertit. Vous vous entendez très bien sans que la fonction de "suivi en amont" fonctionne comme prévu, c'est donc à vous de changer quoi que ce soit.

Pour une autre interprétation des paramètres en amont, voir Pourquoi dois-je "git push --set-upstream origin <branch>"?


Cet avertissement est une nouveauté dans Git, apparaissant en premier dans Git 1.8.5. Les notes de publication ne contiennent qu'une petite puce à ce sujet:

  • "git branch -v -v" (et "git status") n'a pas fait la distinction entre une branche qui n'est basée sur aucune autre branche, une branche qui est synchronisée avec sa branche amont, et une branche qui est configurée avec une branche amont branche qui n'existe plus.

Pour décrire ce que cela signifie, vous devez d'abord connaître les "télécommandes", les "branches de suivi à distance" et comment Git gère le "suivi d'un amont". ( Les branches de suivi à distance sont un terme terriblement imparfait - j'ai commencé à utiliser des noms de suivi à distance place, ce qui, je pense, est une légère amélioration. Ci-dessous, cependant, j'utiliserai "branche de suivi à distance" pour la cohérence avec la documentation Git. )

Chaque "télécommande" est simplement un nom, comme originou octopressdans ce cas. Leur but est d'enregistrer des choses comme l'URL complète des endroits à partir desquels vous git fetchou mettez à git pulljour. Lorsque vous utilisez 1, Git accède à cette télécommande (en utilisant l'URL enregistrée) et apporte l'ensemble de mises à jour approprié. Il enregistre également les mises à jour, en utilisant des "branches de suivi à distance".git fetch remote,

Une "branche de suivi à distance" (ou nom de suivi à distance) est simplement un enregistrement d'un nom de branche tel que vu pour la dernière fois sur une "télécommande". Chaque télécommande est elle-même un référentiel Git, elle a donc des branches. Les branches sur "origine" distante sont enregistrées dans votre référentiel local sous remotes/origin/. Le texte que vous montriez dit qu'il ya une branche nommée sourcesur origin, et les branches nommées 2.1, linkloget ainsi de suite suroctopress .

(Une branche "normale" ou "locale", bien sûr, n'est qu'un nom de branche que vous avez créé dans votre propre référentiel.)

Enfin, vous pouvez configurer une branche (locale) pour «suivre» une «branche de suivi à distance». Une fois que la branche locale Lest configurée pour suivre la branche de suivi à distance R, Git appellera Rson "amont" et vous dira si vous êtes "en avance" et / ou "derrière" l'amont (en termes de commits). Il est normal (même recommandé) que la branche locale et les branches de suivi à distance utilisent le même nom (à l'exception de la partie du préfixe distant), comme sourceet origin/source, mais ce n'est pas vraiment nécessaire.

Et dans ce cas, cela ne se produit pas. Vous avez une succursale locale qui sourcesuit une succursale de suivi à distance origin/master.

Vous n'êtes pas censé avoir besoin de connaître les mécanismes exacts de la façon dont Git configure une branche locale pour suivre une branche distante, mais ils sont pertinents ci-dessous, je vais donc montrer comment cela fonctionne. Nous commençons par le nom de votre succursale locale, source. Il existe deux entrées de configuration utilisant ce nom, orthographié branch.source.remoteet branch.source.merge. D'après le résultat que vous avez montré, il est clair que ceux-ci sont tous les deux définis, de sorte que vous verrez ce qui suit si vous exécutez les commandes données:

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

Mettre ces ensemble, 2 cela indique Git que votre branche sourcesuit votre « branche de suivi à distance », origin/master.

Mais maintenant, regardez la sortie de git branch -a, qui montre tous les noms de branche de suivi locaux et distants dans votre référentiel. Les noms de suivi à distance sont répertoriés sous remotes/... et il n'y en a pasremotes/origin/master . Vraisemblablement, il y en a eu, à un moment donné, mais c'est parti maintenant.

Git vous dit que vous pouvez supprimer les informations de suivi avec --unset-upstream. Cela effacera à la fois branch.source.originet branch.source.mergeet arrêtera l'avertissement.

Cependant, il semble assez probable que vous souhaitiez passer du suivi origin/masterà autre chose: probablement origin/source, mais peut-être l'un des octopress/noms.

Vous pouvez le faire avec git branch --set-upstream-to, 3 par exemple:

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

(en supposant que vous êtes toujours sur la branche "source", et que origin/sourcec'est l'amont que vous voulez - il n'y a aucun moyen pour moi de dire laquelle, le cas échéant, vous voulez réellement).

(Voir aussi Comment faire pour qu'une branche Git existante suive une branche distante? )

Je pense que la façon dont vous êtes arrivé ici est que lorsque vous avez fait un git clone, la chose à partir de laquelle vous avez cloné avait une branche master. Vous aviez également une branche master, qui était configurée pour suivre origin/master(c'est une configuration normale et standard pour git). Cela signifiait que vous aviez branch.master.remoteet que vous vous branch.master.mergemettiez à originet refs/heads/master. Mais votre origintélécommande a changé son nom de masteren source. Pour correspondre, je crois que vous avez également changé votre nom local de masteren source. Cela a changé les noms de vos paramètres, de branch.master.remoteà branch.source.remoteet de branch.master.mergeà branch.source.merge... mais il a laissé les anciennes valeurs , donc branch.source.mergec'était maintenant faux.

C'est à ce moment que le lien «amont» s'est rompu, mais dans les versions de Git antérieures à la 1.8.5, Git n'a jamais remarqué le paramètre cassé. Maintenant que vous avez la version 1.8.5, cela indique cela.


Cela couvre la plupart des questions, mais pas celle «Dois-je résoudre le problème». Il est probable que vous ayez travaillé autour de la rupture depuis des années maintenant, en faisant (par exemple, ). Si vous continuez à faire cela, il continuera à contourner le problème - donc, non, vous n'avez pas besoin de le résoudre. Si vous le souhaitez, vous pouvez utiliser pour supprimer l'amont et arrêter les plaintes, et ne pas avoir de succursale locale marquée comme ayant du tout en amont.git pull remote branchgit pull origin source--unset-upstreamsource

L'intérêt d'avoir un amont est de rendre diverses opérations plus commodes. Par exemple, git fetchsuivi de " git mergefera généralement la bonne chose" si l'amont est défini correctement, et git statusaprès git fetchvous dira si votre dépôt correspond à l'amont, pour cette branche.

Si vous voulez la commodité, réinitialisez le fichier amont.


1git pull utilise git fetch, et à partir de Git 1.8.4, ceci (enfin!) Met également à jour les informations de "branche de suivi à distance". Dans les anciennes versions de Git, les mises à jour n'étaient pas enregistrées dans les branches de suivi à distance avec git pull, uniquement avec git fetch. Étant donné que votre Git doit être au moins la version 1.8.5, ce n'est pas un problème pour vous.

2 Eh bien, ceci plus une ligne de configuration que j'ignore délibérément qui se trouve sous remote.origin.fetch. Git doit mapper le nom "merge" pour comprendre que le nom local complet de la branche distante est refs/remotes/origin/master. La cartographie presque toujours fonctionne comme cela, cependant, il est donc prévisible que masterva origin/master.

3 Ou, avec git config. Si vous voulez juste définir l'amont sur origin/sourcela seule partie qui doit changer branch.source.merge, et le git config branch.source.merge refs/heads/source ferait. Mais --set-upstream-todit ce que vous voulez faire, plutôt que de vous obliger à le faire vous-même, c'est donc une «meilleure façon».


3
+1 pour "Si vous le souhaitez, vous pouvez utiliser --unset-upstream pour que la branche locale soit marquée comme n'ayant pas du tout d'amont."
BeatriceThalo

157

La réponse de torek est probablement parfaite, mais je voulais juste que le dossier mentionne un autre cas qui est différent de celui décrit dans la question originale mais la même erreur peut apparaître (car cela peut aider d'autres personnes avec un problème similaire):

J'ai créé un (nouveau) dépôt vide en utilisant l' git init --bareun de mes serveurs. Ensuite, je l'ai git clonetransféré dans un espace de travail local sur mon PC.

Après avoir validé une seule version sur le repo local, j'ai eu cette erreur après avoir appelé git status.

Suite à la réponse de torek, je comprends que ce qui s'est passé, c'est que le premier commit sur le repo de répertoire de travail local a créé une branche "master". Mais sur le référentiel distant (sur le serveur) il n'y avait jamais rien, donc il n'y avait même pas de branche "maître" (télécommandes / origine / maître).

Après avoir été exécuté à git push origin masterpartir du dépôt local, le dépôt distant avait finalement une branche principale. Cela a empêché l'erreur d'apparaître.

Donc pour conclure - on peut obtenir une telle erreur pour un nouveau repo distant sans aucun commit puisqu'il n'a pas de branche, y compris "master".


6
Il s'agit actuellement du résultat n ° 1 pour ce message d'erreur On branch source Your branch is based on 'origin/master', but the upstream is gone. (use "git branch --unset-upstream" to fixup)et, bien que subjectif, il est plus susceptible d'être causé par le clonage d'un référentiel vide si génial d'avoir une réponse alternative ici.
Bella du

2
Je pense que c'est pourquoi c'est toujours une bonne idée d'initialiser votre nouveau référentiel avec le fichier README.md, même s'il s'agit d'un fichier vide
Ahmed Hussein

8

Cela pourrait résoudre votre problème.

après avoir fait des changements, vous pouvez le valider et ensuite

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

J'espère que ça marche pour toi.

Merci


1
Cela aiderait en effet - la raison est détaillée dans ma réponse (en bref - cela crée la branche principale manquante dans le repo distant).
ElazarR

7

Pour moi, .git/refs/origin/masteravait été corrompu.

J'ai fait ce qui suit, ce qui a résolu le problème pour moi.

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

0

En fait, torek vous a déjà expliqué comment utiliser les outils bien mieux que je ne pourrais le faire. Cependant, dans ce cas, je pense qu'il est important de signaler quelque chose de particulier si vous suivez les directives sur http://octopress.org/docs/deploying/github/ . À savoir, vous aurez plusieurs référentiels github dans votre configuration. Tout d'abord celui avec tout le code source de votre site Web dans le répertoire $WEBSITE, par exemple, puis celui avec uniquement les fichiers générés statiques résidant dans $WEBSITE/_deploy. La chose amusante de l'installation est qu'il y a un .gitignorefichier dans le $WEBSITErépertoire pour que cette installation fonctionne réellement.

Assez d'introduction. Dans ce cas, l'erreur peut également provenir du référentiel dans _deploy.

cd _deploy

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

Dans, .git/configvous devrez normalement trouver quelque chose comme ceci:

[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

Mais dans votre cas, le maître de succursale n'a pas de télécommande.

[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/*

Ce que vous pouvez résoudre par:

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

Donc, tout est comme Torek vous l'a dit, mais il peut être important de souligner que cela pourrait très bien concerner le _deploy répertoire plutôt que la racine de votre site Web.

PS: Cela pourrait valoir la peine d'utiliser un shell comme zshavec un gitplugin pour ne pas être mordu par cette chose à l'avenir. Il montrera immédiatement que _deployconcerne un référentiel différent.


0

J'ai eu cette question deux fois, et elle était toujours causée par la corruption du fichier de cache git dans ma branche locale. Je l'ai corrigé en écrivant le hachage de validation manquant dans ce fichier. J'ai obtenu le bon hachage de validation du serveur et j'ai exécuté la commande suivante localement:

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

0

Problème: votre branche est basée sur «origine / maître», mais l'amont a disparu.

Solution: branche git --unset-upstream


3
Bienvenue dans stackoverflow. La question n'est pas de savoir comment l'erreur peut être corrigée, il veut savoir pourquoi cette erreur est soulevée et s'il doit faire quelque chose. Veuillez répondre à cela dans votre réponse.
cronoik

0

supprimez votre branche locale en suivant la commande

git branch -d branch_name

tu pourrais aussi faire

git branch -D branch_name 

ce qui force essentiellement une suppression (même si locale n'est pas fusionnée avec la source)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.