para - ¿Por qué tengo que "git push--set-upstream origin<branch>"?
git delete branch (3)
TL; DR:
git branch --set-upstream-to origin/solaris
La respuesta a la pregunta que hizo, que reformularé un poco como "¿Tengo que configurar un flujo ascendente?" Es: no, no tiene que configurar un flujo ascendente en absoluto.
Sin embargo, si no tiene un flujo ascendente para la rama actual, Git cambia su comportamiento en
git push
y también en otros comandos.
La historia de empuje completa aquí es larga y aburrida y se remonta a la historia anterior a Git versión 1.5.
Para acortarlo mucho,
git push
se implementó mal.
1
A partir de la versión 2.0 de Git, Git ahora tiene una perilla de configuración deletreada
push.default
que ahora por defecto es
simple
.
Para varias versiones de Git antes y después de 2.0, cada vez que ejecutaba
git push
, Git emitía mucho ruido tratando de convencerlo de configurar
push.default
solo para que
git push
callara.
No menciona qué versión de Git está ejecutando, ni si ha configurado
push.default
, por lo que debemos adivinar.
Supongo que está utilizando Git versión 2-point-something, y que ha configurado
push.default
en
simple
para que se cierre.
Precisamente qué versión de Git tiene, y qué
push.default
si tiene algo
push.default
para
push.default
, importa, debido a ese largo y aburrido historial, pero al final, el hecho de que
push.default
otra queja de Git indica que su Git
está
configurado para evitar uno de los errores del pasado.
¿Qué es un upstream?
Un flujo ascendente es simplemente otro nombre de rama, generalmente una rama de seguimiento remoto, asociada con una rama (regular, local).
Cada rama tiene la opción de tener un (1) conjunto ascendente. Es decir, cada rama tiene un flujo ascendente o no tiene un flujo ascendente. Ninguna sucursal puede tener más de una corriente arriba.
El flujo ascendente
debe
, pero no tiene que ser, una rama válida (ya sea de seguimiento remoto como
origin/
B
o local como
master
).
Es decir, si la rama actual
B
tiene
U
ascendente,
git rev-parse
U
debería
funcionar.
Si no funciona, si se queja de que
U
no existe, entonces la mayoría de Git actúa como si el flujo ascendente no estuviera configurado.
Algunos comandos, como
git branch -vv
, mostrarán la configuración aguas arriba pero la marcarán como "desaparecida".
¿De qué sirve una corriente arriba?
Si su
push.default
está configurado en
simple
o
upstream
, la configuración ascendente hará que
git push
, usado sin argumentos adicionales, simplemente funcione.
Eso es todo, eso es todo lo que hace para
git push
.
Pero eso es bastante significativo, ya que
git push
es uno de los lugares donde un error tipográfico simple causa grandes dolores de cabeza.
Si su
push.default
está establecido en
nothing
,
matching
o
current
, configurar un
push.default
ascendente no hace nada para
git push
.
(Todo esto supone que su versión de Git es al menos 2.0).
La corriente arriba afecta a
git fetch
Si ejecuta
git fetch
sin argumentos adicionales, Git descubre desde
qué
control remoto debe buscar consultando el flujo ascendente de la rama actual.
Si el flujo ascendente es una rama de seguimiento remoto, Git obtiene de ese control remoto.
(Si el flujo ascendente no está configurado o es una rama local, Git intenta buscar el
origin
).
El upstream también afecta a
git merge
y
git rebase
Si ejecuta
git merge
o
git rebase
sin argumentos adicionales, Git usa el
git rebase
ascendente de la rama actual.
Por lo tanto, acorta el uso de estos dos comandos.
La corriente arriba afecta a
git pull
Nunca debe usar
git pull
todos modos, pero si lo hace,
git pull
usa la configuración aguas arriba para averiguar desde qué control remoto buscar, y luego con qué rama fusionar o rebase.
Es decir,
git pull
hace lo mismo que
git fetch
porque en realidad
ejecuta
git fetch
y luego hace lo mismo que
git merge
o
git rebase
, porque realmente
ejecuta
git merge
o
git rebase
.
(Por lo general, solo debe hacer estos dos pasos manualmente, al menos hasta que conozca a Git lo suficientemente bien como para que cuando cualquiera de los pasos falle, lo que eventualmente ocurrirá, reconozca lo que salió mal y sepa qué hacer al respecto).
El flujo ascendente afecta el
git status
Esto en realidad puede ser lo más importante.
Una vez que tenga un conjunto ascendente, el
git status
puede informar la diferencia entre su rama actual y su ascendente, en términos de confirmaciones.
Si, como es el caso normal, se encuentra en la rama
B
con su configuración aguas arriba establecida en
origin/
B
, y ejecuta el
git status
, verá de inmediato si tiene compromisos que puede empujar, y / o compromisos que puede fusionar o rebasar en .
Esto se debe a que se ejecuta el
git status
:
-
git rev-list --count @{u}..HEAD
: ¿cuántas confirmaciones tienes enB
que no están enorigin/ B
? -
git rev-list --count HEAD..@{u}
: ¿cuántas confirmaciones tiene enorigin/ B
que no están enB
?
Establecer un flujo ascendente le brinda todas estas cosas.
¿Cómo es que el
master
ya tiene un conjunto ascendente?
Cuando clones por primera vez desde un control remoto, usa:
$ git clone git://some.host/path/to/repo.git
o similar, el último paso que Git hace es, esencialmente,
git checkout master
.
Esto verifica tu
master
sucursal local, solo que no
tienes
un
master
sucursal local.
Por otro lado, tiene una rama de seguimiento remoto llamada
origin/master
, porque la clonó.
Git adivina que debes haber querido decir: "hazme un nuevo
master
local que apunte a la misma confirmación que el
origin/master
seguimiento remoto y, mientras lo haces, configura el flujo ascendente para
master
a
origin/master
".
Esto sucede para
cada
sucursal que tiene que
git checkout
que aún no tiene.
Git crea la rama
y la
hace "rastrear" (tener como un flujo ascendente) la rama de seguimiento remoto correspondiente.
Pero esto no funciona para nuevas sucursales, es decir, sucursales sin sucursal de seguimiento remoto todavía .
Si crea una nueva rama:
$ git checkout -b solaris
todavía no hay
origin/solaris
.
Su
solaris
local
no puede
rastrear el
origin/solaris
sucursal de seguimiento remoto
origin/solaris
porque no existe.
Cuando empuja la nueva rama por primera vez:
$ git push origin solaris
eso
crea
solaris
en
origin
, y por lo tanto también crea
origin/solaris
en su propio repositorio Git.
Pero es demasiado tarde: ya tienes un
solaris
local que
no tiene corriente arriba
.
3
¿No debería Git simplemente configurar eso, ahora, como el flujo ascendente automáticamente?
Probablemente. Ver "implementado mal" y la nota al pie 1. Ahora es difícil cambiar: hay millones 4 de scripts que usan Git y algunos pueden depender de su comportamiento actual. Cambiar el comportamiento requiere una nueva versión principal, un programa para forzarlo a establecer algún campo de configuración, y así sucesivamente. En resumen, Git es víctima de su propio éxito: cualquier error que tenga, hoy en día, solo puede repararse si el cambio es en su mayoría invisible, claramente mucho mejor o se hace lentamente con el tiempo.
El hecho es que no lo hace hoy, a
menos
que use
--set-upstream
o
-u
durante el
git push
.
Eso es lo que te dice el mensaje.
No tienes que hacerlo así.
Bueno, como señalamos anteriormente, no tiene que hacerlo en absoluto, pero supongamos que
desea
un flujo ascendente.
Ya ha creado rama
solaris
en
origin
, a través de un empuje anterior, y como muestra su salida de
git branch
, ya
tiene
origin/solaris
en su repositorio local.
Simplemente no lo tiene configurado como upstream para
solaris
.
Para configurarlo ahora, en lugar de durante el primer
git branch --set-upstream-to
, use
git branch --set-upstream-to
.
El
--set-upstream-to
toma el nombre de cualquier rama existente, como
origin/solaris
, y establece la rama actual en sentido ascendente a esa otra rama.
Eso es todo, eso es todo lo que hace, pero tiene todas las implicaciones mencionadas anteriormente.
Significa que puede ejecutar
git fetch
, luego mirar a su alrededor, luego ejecutar
git merge
o
git rebase
según corresponda, luego realizar nuevas confirmaciones y ejecutar
git push
, sin un montón de complicaciones adicionales.
1 Para ser justos, no estaba claro en ese entonces que la implementación inicial fuera propensa a errores. Eso solo quedó claro cuando cada nuevo usuario cometió los mismos errores cada vez. Ahora es "menos pobre", lo que no quiere decir "genial".
2
"Nunca" es un poco fuerte, pero creo que los novatos de Git entienden mucho mejor las cosas cuando separo los pasos, especialmente cuando puedo mostrarles lo que
git fetch
realmente hizo, y luego pueden ver qué
git merge
o
git rebase
Lo haremos a continuación.
3
Si ejecuta su
primer
git push
como
git push -u origin solaris
, es decir, si agrega la bandera
-u
, Git establecerá
origin/solaris
como aguas arriba para su rama actual si (y solo si) el empuje tiene éxito.
Por lo tanto, debe suministrar
-u
en el
primer
impulso.
De hecho, puede suministrarlo en cualquier inserción posterior, y establecerá
o cambiará
el flujo ascendente en ese punto.
Pero creo que
git branch --set-upstream-to
es más fácil, si lo olvidó.
4 Medido por el método Austin Powers / Dr Evil de simplemente decir "un MILLLL-YUN", de todos modos.
Creé una sucursal local para probar Solaris y Sun Studio. Luego empujé la rama río arriba. Después de cometer un cambio e intentar impulsar los cambios:
$ 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
¿Por qué tengo que hacer algo especial para esto?
¿Hay algún caso de uso razonable en el que alguien cree
<branch>
, empuje el
<branch>
a control remoto y luego reclame que un commit en
<branch>
no debe ser para
<branch>
?
Seguí esta pregunta y respuesta en Stack Overflow: empuje una nueva rama local a un repositorio remoto de Git y también realice un seguimiento . Supongo que es otra instancia de una respuesta aceptada incompleta o incorrecta. O bien, es otra instancia de Git que toma una tarea simple y la dificulta.
Aquí está la vista en una máquina diferente. La rama existe claramente, por lo que fue creada y empujada:
$ 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
La diferencia entre
git push origin <branch>
y
git push --set-upstream origin <branch>
es que ambos empujan muy bien al repositorio remoto, pero es cuando sacas que notas la diferencia.
Si lo haces:
git push origin <branch>
al tirar, tienes que hacer:
git pull origin <branch>
Pero si lo haces:
git push --set-upstream origin <branch>
entonces, al tirar, solo tienes que hacer:
git pull
Por lo tanto, agregar el
--set-upstream
permite no tener que especificar de qué rama desea extraer cada vez que hace
git pull
.
Un comando básicamente completo es como
git push <remote> <local_ref>:<remote_ref>
.
Si ejecuta solo
git push
, git no sabe qué hacer exactamente a menos que haya realizado alguna configuración que ayude a git a tomar una decisión.
En un repositorio de git, podemos configurar múltiples controles remotos.
También podemos enviar una referencia local a cualquier referencia remota.
El comando completo es la forma más directa de dar un empujón.
Si desea escribir menos palabras, primero debe configurar, como --set-upstream.