J'ai créé une branche locale pour tester Solaris et Sun Studio. J'ai ensuite poussé la branche en amont. Après avoir validé une modification et tenté de pousser les modifications:
$ git commit blake2.cpp -m "Add workaround for missing _mm_set_epi64x"
[solaris 7ad22ff] Add workaround for missing _mm_set_epi64x
1 file changed, 5 insertions(+)
$ git push
fatal: The current branch solaris has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin solaris
Pourquoi dois-je faire quelque chose de spécial pour cela?
Y a-t-il un cas d'utilisation raisonnable où quelqu'un créerait <branch>
, pousserait le <branch>
vers distant, puis affirmerait qu'un commit sur <branch>
n'est pas censé être pour <branch>
?
J'ai suivi cette question et réponse sur Stack Overflow: Poussez une nouvelle branche locale vers un référentiel Git distant et suivez-la également . Je suppose que c'est une autre instance de réponse acceptée incomplète ou erronée. Ou, c'est une autre instance de Git prenant une tâche simple et la rendant difficile.
Voici la vue sur une machine différente. La branche existe clairement, elle a donc été créée et poussée:
$ git branch -a
alignas
* master
remotes/origin/HEAD -> origin/master
remotes/origin/alignas
remotes/origin/arm-neon
remotes/origin/det-sig
remotes/origin/master
remotes/origin/solaris
git config --add push.default current
, git push créera automatiquement la branche dans le référentiel distant si nécessaire.Réponses:
TL; DR:
git branch --set-upstream-to origin/solaris
La réponse à la question que vous avez posée - que je reformulerai un peu comme "dois-je définir un amont" - est: non, vous n'avez pas du tout à définir un amont.
Si vous n'avez pas d'amont pour la branche actuelle, cependant, Git change son comportement sur
git push
, et sur d'autres commandes également.L'histoire complète des push ici est longue et ennuyeuse et remonte à l'histoire d'avant la version 1.5 de Git. Pour le raccourcir beaucoup, a
git push
été mal implémenté. 1 À partir de la version 2.0 de Git, Git a maintenant un bouton de configuration orthographiépush.default
qui est désormais par défautsimple
. Pour plusieurs versions de Git avant et après 2.0, chaque fois que vous exécutiezgit push
, Git crachait beaucoup de bruit en essayant de vous convaincre de réglerpush.default
juste pour pouvoirgit push
vous taire.Vous ne mentionnez pas la version de Git que vous utilisez, ni si vous l'avez configurée
push.default
, il faut donc deviner. Je suppose que vous utilisez Git version 2-point-quelque chose, et que vous avez configurépush.default
poursimple
le faire taire. Précisément quelle version de Git que vous avez, et si tout ce que vous avezpush.default
réglé sur, ne importe, en raison de cette histoire longue et ennuyeux, mais à la fin, le fait que vous obtenez une autre plainte de Git indique que votre Git est configuré pour éviter l'une des erreurs du passé.Qu'est-ce qu'un amont?
Un amont est simplement un autre nom de branche, généralement une branche de suivi à distance, associé à une branche (régulière, locale).
Chaque branche a la possibilité d'avoir un (1) ensemble en amont. Autrement dit, chaque branche a un amont ou n'en a pas un. Aucune succursale ne peut en avoir plus d'une en amont.
L'amont devrait , mais ne doit pas être, une branche valide (qu'elle soit de type suivi à distance ou locale ). Autrement dit, si la branche actuelle B a U en amont , devrait fonctionner. Si cela ne fonctionne pas - s'il se plaint que U n'existe pas - alors la plupart de Git agit comme si l'amont n'était pas du tout défini. Quelques commandes, comme , afficheront le paramètre en amont mais le marqueront comme "parti".
origin/B
master
git rev-parse U
git branch -vv
A quoi sert un amont?
Si votre
push.default
est défini sursimple
ouupstream
, le paramètre en amont fonctionneragit push
, utilisé sans argument supplémentaire.C'est tout - c'est tout ce qu'il fait
git push
. Mais c'est assez important, cargit push
c'est l'un des endroits où une simple faute de frappe provoque des maux de tête majeurs.Si votre
push.default
est réglé surnothing
,matching
oucurrent
, la configuration d'un amont ne fait rien du tout pourgit push
.(Tout cela suppose que votre version de Git est au moins 2.0.)
L'amont affecte
git fetch
Si vous exécutez
git fetch
sans argument supplémentaire, Git détermine la télécommande à partir de laquelle récupérer en consultant l'amont de la branche actuelle. Si l'amont est une branche de suivi à distance, Git récupère à partir de cette télécommande. (Si l'amont n'est pas défini ou est une branche locale, Git essaie de récupérerorigin
.)L'amont affecte
git merge
etgit rebase
aussiSi vous exécutez
git merge
ougit rebase
sans arguments supplémentaires, Git utilise l'amont de la branche actuelle. Cela raccourcit donc l'utilisation de ces deux commandes.L'amont affecte
git pull
Vous ne devriez jamais 2 utiliser de
git pull
toute façon, mais si vous le faites,git pull
utilise le paramètre en amont pour savoir qui à distance pour aller chercher de, puis quelle branche fusion ou rebasage avec. Autrement dit,git pull
fait la même chose quegit fetch
—parce qu'il s'exécute réellementgit fetch
— et ensuite fait la même chose quegit merge
ougit rebase
, parce qu'il exécute en faitgit merge
ougit rebase
.(Vous devriez généralement simplement faire ces deux étapes manuellement, au moins jusqu'à ce que vous connaissiez suffisamment bien Git pour que lorsque l'une ou l'autre étape échoue, ce qu'elle finira par faire, vous reconnaîtrez ce qui n'a pas fonctionné et sachez quoi faire.)
L'amont affecte
git status
C'est peut-être le plus important. Une fois que vous avez un ensemble en amont, vous
git status
pouvez signaler la différence entre votre branche actuelle et son amont, en termes de commits.Si, comme c'est le cas normal, vous êtes sur une branche
B
avec son amont réglé sur , et que vous exécutez , vous verrez immédiatement si vous avez des commits que vous pouvez pousser et / ou des commits sur lesquels vous pouvez fusionner ou rebaser.origin/B
git status
C'est parce que
git status
s'exécute:git rev-list --count @{u}..HEAD
: combien de commits avez-vous surB
qui ne sont pas activés ?origin/B
git rev-list --count HEAD..@{u}
: combien de commits avez-vous sur qui ne sont pas activés ?origin/B
B
Mettre en place un amont vous donne toutes ces choses.
Comment se fait-il que
master
déjà un ensemble en amont?Lorsque vous clonez pour la première fois à partir d'une télécommande, en utilisant:
ou similaire, la dernière étape Git est, essentiellement,
git checkout master
. Cela vérifie votre succursale localemaster
-seulement vous n'ont une succursale localemaster
.D'autre part, vous n'avez une branche de suivi à distance nommé , parce que vous venez cloné il.
origin/master
Git suppose que vous devez avoir voulu dire: "faites-moi un nouveau local
master
qui pointe vers le même commit que le suivi à distanceorigin/master
, et, pendant que vous y êtes, définissez l'amont surmaster
toorigin/master
."Cela se produit pour chaque branche
git checkout
que vous n'avez pas déjà. Git crée la branche et la fait «suivre» (avoir en amont) la branche de suivi à distance correspondante.Mais cela ne fonctionne pas pour les nouvelles branches, c'est-à-dire les branches sans branche de suivi à distance encore .
Si vous créez une nouvelle branche:
il n'y a pas encore
origin/solaris
. Votre agence localesolaris
ne peut pas suivre la branche de suivi à distanceorigin/solaris
car elle n'existe pas.Lorsque vous poussez pour la première fois la nouvelle branche:
qui crée
solaris
surorigin
, et donc crée égalementorigin/solaris
dans votre propre référentiel Git. Mais il est trop tard: vous avez déjà un localsolaris
qui n'a pas d'amont . 3Git ne devrait-il pas simplement définir cela, maintenant, comme amont automatiquement?
Probablement. Voir «mal implémenté» et note de bas de page 1. Il est difficile de changer maintenant : il y a des millions 4 de scripts qui utilisent Git et certains peuvent bien dépendre de son comportement actuel. Changer le comportement nécessite une nouvelle version majeure, nag-ware pour vous forcer à définir un champ de configuration, et ainsi de suite. En bref, Git est victime de son propre succès: quelles que soient les erreurs qu'il y a, aujourd'hui, ne peuvent être corrigées que si le changement est soit essentiellement invisible, nettement mieux, soit effectué lentement au fil du temps.
Le fait est que ce n'est pas le cas aujourd'hui, sauf si vous utilisez
--set-upstream
ou-u
pendant legit push
. C'est ce que le message vous dit.Vous n'êtes pas obligé de le faire comme ça. Eh bien, comme nous l'avons noté ci-dessus, vous n'avez pas à le faire du tout, mais disons que vous voulez un en amont. Vous avez déjà créé la branche
solaris
surorigin
, par une poussée plus tôt, et que vosgit branch
spectacles de sortie, vous avez déjà avoirorigin/solaris
dans votre dépôt local.Vous ne l'avez tout simplement pas défini comme amont pour
solaris
.Pour le régler maintenant, plutôt que lors de la première poussée, utilisez
git branch --set-upstream-to
. La--set-upstream-to
sous-commande prend le nom de n'importe quelle branche existante, telle queorigin/solaris
, et définit la branche actuelle en amont sur cette autre branche.C'est tout - c'est tout ce qu'il fait - mais cela a toutes les implications mentionnées ci-dessus. Cela signifie que vous pouvez simplement exécuter
git fetch
, puis regarder autour de vous, puis exécutergit merge
ougit rebase
selon le cas, puis faire de nouveaux commits et exécutergit push
, sans trop de tracas.1 Pour être juste, il n'était pas clair à l'époque que la mise en œuvre initiale était sujette aux erreurs. Cela n'est devenu clair que lorsque chaque nouvel utilisateur a commis les mêmes erreurs à chaque fois. Il est désormais "moins pauvre", ce qui ne veut pas dire "génial".
2 "Jamais" est un peu fort, mais je trouve que les débutants de Git comprennent beaucoup mieux les choses quand je sépare les étapes, surtout quand je peux leur montrer ce qui a
git fetch
réellement fait, et ils peuvent alors voir ce quigit merge
ougit rebase
va faire ensuite.3 Si vous exécutez votre premier en
git push
tant quegit push -u origin solaris
— c'est-à-dire si vous ajoutez l'-u
indicateur — Git sera définiorigin/solaris
comme amont pour votre branche actuelle si (et seulement si) la transmission réussit. Vous devez donc fournir dès-u
la première poussée. En fait, vous pouvez le fournir sur n'importe quelle poussée ultérieure, et il définira ou modifiera l'amont à ce stade. Mais je pense quegit branch --set-upstream-to
c'est plus facile, si vous avez oublié.4 Mesuré par la méthode Austin Powers / Dr Evil qui consiste simplement à dire "un MILLLL-YUN", de toute façon.
la source
--set-upstream /dev/null
? Pourquoi le fardeau pèse-t-il sur le cas commun? Je ne comprends vraiment pas certaines de ces décisions d'ingénierie et d'utilisabilité.git push -u
, mais il semble vraiment que cegit push -u
devrait être la valeur par défaut, ou du moins la valeur par défaut s'il n'y a pas encore d' amont , et il devrait y avoir ungit push --no-set-upstream
quand il n'y a pas actuellement d'amont et que vous voulez garder il de cette façon (pour une raison incompréhensible :-)).git config --add push.default current
, git push créera automatiquement la branche dans le référentiel distant si nécessaire.La différence entre
git push origin <branch>
et
git push --set-upstream origin <branch>
est qu'ils poussent tous les deux très bien vers le référentiel distant, mais c'est lorsque vous tirez que vous remarquez la différence.
Si vous faites:
git push origin <branch>
lorsque vous tirez, vous devez faire:
git pull origin <branch>
Mais si vous faites:
git push --set-upstream origin <branch>
alors, lorsque vous tirez, vous n'avez qu'à faire:
git pull
Ainsi, l'ajout de
--set-upstream
permet de ne pas avoir à spécifier de quelle branche vous voulez extraire à chaque fois que vous le faitesgit pull
.la source
Une commande fondamentalement complète est comme
git push <remote> <local_ref>:<remote_ref>
. Si vous exécutez justegit push
, git ne sait pas quoi faire exactement à moins que vous n'ayez fait une configuration qui aide git à prendre une décision. Dans un dépôt git, nous pouvons configurer plusieurs télécommandes. Nous pouvons également pousser une référence locale vers n'importe quelle référence distante. La commande complète est le moyen le plus simple de pousser. Si vous voulez taper moins de mots, vous devez d'abord configurer, comme --set-upstream.la source