¿Por qué tengo que "git push –set-upstream origen <branch>"?

Creé una sucursal local para probar Solaris y Sun Studio. Luego empujé la twig aguas arriba. Después de realizar 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 <branch> a remote, y luego reclame que commit en <branch> no se suponga que sea para <branch> ?


Seguí esta pregunta y respuesta en Stack Overflow: inserte una nueva twig local en un repository 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 tomando una tarea simple y haciéndola difícil.


Aquí está la vista en una máquina diferente. La twig claramente existe, 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 

TL; DR: git branch --set-upstream-to origin/solaris


La respuesta a la pregunta que me hiciste, que voy a reformular un poco como "tengo que establecer un flujo ascendente", es: no, no tienes que establecer un flujo ascendente.

Sin embargo, si no tienes el flujo ascendente para la twig actual, Git cambia su comportamiento en git push y en otros commands también.

La historia 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 configuration deletreada push.default que ahora está por defecto en simple . Para varias versiones de Git antes y después de 2.0, cada vez que ejecutabas git push , Git soltaba mucho ruido tratando de convencerte de que establezcas push.default solo para que git push se push.default .

No mencionas qué versión de Git estás ejecutando, ni si has configurado push.default , así que debemos adivinar. Supongo que está usando la versión de Git de 2 puntos y algo, y que ha configurado push.default en simple para que se apague. Precisamente qué versión de Git tiene, y qué push.default si tiene establecido push.default , importa, debido a esa larga y aburrida historia, 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 upstream es simplemente otro nombre de twig, generalmente una twig de seguimiento remoto, asociada a una twig (regular, local).

Cada twig tiene la opción de tener un (1) set ascendente. Es decir, cada twig tiene un flujo ascendente, o no tiene un flujo ascendente. Ninguna twig puede tener más de una en sentido ascendente.

El upstream debe , pero no tiene por qué ser, una twig válida (ya sea de seguimiento remoto como origin/ B o local como master ). Es decir, si la twig 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 upstream no estuviera configurado. Algunos commands, como git branch -vv , mostrarán la configuration upstream pero la marcan como "ida".

¿De qué sirve un upstream?

Si push.default se configura en simple o en upstream , la configuration ascendente hará que git push , utilizado sin arguments 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 simple error tipográfico causa dolores de cabeza importantes.

Si su push.default está configurado en nothing , la matching o current configuration current un upstream no tiene nada que ver con git push .

(Todo esto supone que su versión de Git es al less 2.0).

La stream arriba afecta a la git fetch

Si ejecuta git fetch sin arguments adicionales, Git se da count de qué control remoto search al consultar la stream ascendente de la twig actual. Si el flujo ascendente es una twig de seguimiento remoto, Git obtiene de ese control remoto. (Si el flujo ascendente no está configurado o es una twig local, Git intenta get el origin ).

El upstream afecta a git merge y git rebase también

Si ejecuta git merge o git rebase sin arguments adicionales, Git usa el git rebase ascendente de la twig actual. Por lo tanto, acorta el uso de estos dos commands.

El flujo ascendente afecta la git pull

Nunca deberías 2 usar git pull todos modos, pero si lo haces, git pull usa la configuration ascendente para averiguar de qué control remoto extraer y con qué twig combinar o rebase. Es decir, git pull hace lo mismo que git fetch porque realmente 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, debes hacer estos dos pasos manualmente, al less hasta que conozcas a Git lo suficiente como para que, cuando uno de los dos pasos falle, lo cual eventualmente reconozca lo que salió mal y sepa qué hacer al respecto).

La stream ascendente afecta el git status

Esto realmente puede ser lo más importante. Una vez que tiene un set ascendente, el git status puede informar la diferencia entre su sucursal actual y su ascendente, en términos de confirmaciones.

Si, como es el caso normal, estás en la twig B con su set ascendente en origin/ B , y ejecutas el git status , verás inmediatamente si tienes confirmaciones que puedes presionar, y / o confirma que puedes unir o rebase en .

Esto es porque el git status ejecuta:

  • git rev-list --count @{u}..HEAD : ¿Cuántas confirmaciones tienes en B que no están en origin/ B ?
  • git rev-list --count HEAD..@{u} : ¿Cuántas confirmaciones tienes en origin/ B que no están en B ?

Establecer un upstream te da todas estas cosas.

¿Cómo es que el master ya tiene un set ascendente?

Cuando clonas por primera vez desde un control remoto, usando:

 $ git clone git://some.host/path/to/repo.git 

o similar, el último paso que hace Git es, esencialmente, el git checkout master . Esto verifica el master su sucursal local, solo que no tiene un master sucursal local.

Por otro lado, tienes una twig de seguimiento remoto llamada origin/master , porque la clonaste.

Git supone 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, establece el flujo ascendente para master origin/master ".

Esto sucede para todas las sucursales que git checkout que aún no tienes. Git crea la twig y la hace "seguir" (tener como un flujo ascendente) la twig correspondiente de seguimiento remoto.

Pero esto no funciona para nuevas sucursales, es decir, sucursales sin twig de seguimiento remoto todavía .

Si creas una nueva twig:

 $ git checkout -b solaris 

todavía no hay origin/solaris . Sus solaris locales no pueden rastrear el origin/solaris seguimiento de seguimiento remoto porque no existe.

Cuando empuja la nueva twig por primera vez:

 $ git push origin solaris 

que crea solaris en origin , y por lo tanto también crea origin/solaris en su propio repository de Git. Pero es demasiado tarde: ya tienes un solaris local que no tiene stream ascendente . 3

¿No debería Git simplemente establecer eso, ahora, como el upstream automáticamente?

Probablemente. Consulte "Implementado mal" y la nota 1. Es difícil cambiar ahora : 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, nag-ware para forzarle a establecer algún campo de configuration, y así sucesivamente. En resumen, Git es una víctima de su propio éxito: cualquier error que tenga, hoy, solo se puede arreglar si el cambio es mayormente invisible, claramente mejor, o se hace lentamente con el time.

El hecho es que hoy no, a less que use --set-upstream o -u durante el git push . Eso es lo que el post te está diciendo.

No tienes que hacerlo así. Bueno, como notamos arriba, no tienes que hacerlo en absoluto, pero digamos que quieres un flujo ascendente. Ya ha creado branch solaris en origin , a través de un push anterior, y como lo muestra su salida de git branch , ya tiene origin/solaris en su repository local.

Simplemente no lo tienes configurado como upstream para solaris .

Para configurarlo ahora, en lugar de hacerlo durante la primera inserción, use git branch --set-upstream-to . El --set-upstream-to toma el nombre de cualquier twig existente, como origin/solaris , y establece la twig actual de la twig ascendente a esa otra twig.

Eso es todo, eso es todo lo que hace, pero tiene todas las implicaciones mencionadas anteriormente. Significa que solo puedes ejecutar git fetch , luego mirar alnetworkingedor, luego ejecutar git merge o git rebase según corresponda, luego hacer nuevos commits y ejecutar git push , sin un montón de alboroto adicional.


1 Para ser justos, no estaba claro entonces que la implementación inicial fuera propensa a errores. Eso solo quedó claro cuando cada nuevo usuario cometía los mismos errores cada vez. Ahora es "less pobre", lo que no quiere decir "excelente".

2 "Nunca" es un poco fuerte, pero me parece que los novatos de Git entienden las cosas mucho mejor cuando separo los pasos, especialmente cuando puedo mostrarles lo que realmente hicieron los git fetch , y luego pueden ver qué git merge o git rebase haré después.

3 Si ejecutas tu primer git push como git push -u origin solaris -ie, si agregas el indicador -u , Git configurará origin/solaris como origin/solaris ascendente para tu twig actual si (y solo si) el impulso tiene éxito. Por lo tanto, debe suministrar -u en el primer impulso. De hecho, puede suministrarlo en cualquier momento posterior, y establecerá o cambiará el flujo ascendente en ese punto. Pero creo que la git branch --set-upstream-to es más fácil, si lo olvidaste.

4 Medido por el método Austin Powers / Dr Evil de simplemente decir "un MILLLL-YUN", de todos modos.

Un command básicamente completo es como git push <remote> <local_ref>:<remote_ref> . Si ejecuta solo git push , git no sabe qué hacer exactamente a less que haya hecho alguna configuration que ayude a Git a tomar una decisión. En un repository git, podemos configurar múltiples controles remotos. También podemos enviar una reference local a cualquier reference remota. El command completo es la forma más directa de hacer un push. Si quiere escribir less palabras, primero tiene que configurar, como –set-upstream.