¿Por qué necesito hacer `--set-upstream` todo el tiempo?

1469

Creo una nueva sucursal en Git:

git branch my_branch

Empujalo:

git push origin my_branch

Ahora digamos que alguien hizo algunos cambios en el servidor y quiero retirarlos origin/my_branch. Hago:

git pull

Pero me sale:

You asked me to pull without telling me which branch you
want to merge with, and 'branch.my_branch.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:

    [branch "my_branch"]
    remote = <nickname>
    merge = <remote-ref>

    [remote "<nickname>"]
    url = <url>
    fetch = <refspec>

See git-config(1) for details.

Aprendí que puedo hacer que funcione con:

git branch --set-upstream my_branch origin/my_branch

Pero, ¿por qué necesito hacer esto para cada rama que creo? No es obvio que si empujo my_branchhacia origin/my_branch, a continuación, me gustaría tirar origin/my_branchhacia my_branch? ¿Cómo puedo hacer que este sea el comportamiento predeterminado?

Ram Rachum
fuente
21
El valor predeterminado para branch.autosetupmergesignifica que la configuración ascendente para una nueva rama solo se establece automáticamente cuando se crea una rama desde una rama de seguimiento remoto (por ejemplo <remote-name>/<branch-name>) (consulte git-config (1) ). Probablemente esté creando sus sucursales a partir de sucursales locales existentes. Si está bifurcando directamente desde la punta de una bifurcación remota (a pesar de estar en una bifurcación local), puede usar git branch my_branch <remote-name>/<branch-name>para configurar automáticamente la configuración ascendente.
Chris Johnsen
20
Para su información, la --set-upstreamopción está en desuso. Deberías usar --tracko en su --set-upstream-tolugar.
Sean the Bean
139
si --set-upstreamestá en desuso, ¿quizás los desarrolladores de git deberían eliminarlo del mensaje de ayuda que se muestra cuando se ejecuta git pushsin opciones y no se establece ningún flujo ascendente?
Christopher Hunter
17
@ChristopherHunter Ha pasado más de un año desde su comentario y todavía lo dice. ¿Es solo una retroalimentación descuidada o tal vez hay una razón técnicamente sabia para ignorarla?
Konrad Viltersten
15
@ChristopherHunter git branch --set-upstreamestá en desuso. git push --set-upstreamno es.
Brian Gordon

Respuestas:

1538

Un atajo, que no depende de recordar la sintaxis para git branch --set-upstream 1 es hacer:

git push -u origin my_branch

... la primera vez que empujas esa rama. O, para pasar a la rama actual a una rama del mismo nombre (útil para un alias):

git push -u origin HEAD

Solo necesita usar -uuna vez, y eso establece la asociación entre su rama y la originde la misma manera que lo git branch --set-upstreamhace.

Personalmente, creo que es bueno tener que establecer esa asociación entre su sucursal y una en el control remoto explícitamente. Es una pena que las reglas sean diferentes para git pushygit pull .


1 Puede sonar tonto, pero con frecuencia olvido especificar la rama actual, suponiendo que sea la predeterminada, no lo es, y los resultados son muy confusos :)

Actualización 2012-10-11 : ¡Aparentemente no soy la única persona a la que le resultó fácil equivocarse! Gracias a VonC por señalar que git 1.8.0 presenta lo más obvio git branch --set-upstream-to, que puede usarse de la siguiente manera, si está en la rama my_branch:

git branch --set-upstream-to origin/my_branch

... o con la opción corta:

git branch -u origin/my_branch

Este cambio y su razonamiento se describen en las notas de la versión de git 1.8.0, versión candidata 1 :

Fue tentador decirlo git branch --set-upstream origin/master, pero eso le dice a Git que organice la sucursal local origin/masterpara que se integre con la sucursal actualmente desprotegida, lo que es muy poco probable a qué se refería el usuario. La opción está en desuso; use la nueva opción --set-upstream-to(con una -uopción corta y dulce ) en su lugar.

Mark Longair
fuente
95
También tenga en cuenta que incluso si olvida la -uprimera vez que presiona, puede volver a ejecutar el comando con esa bandera y comenzará a seguir.
Henrik N
70
Ninguno de estos satisface el caso de uso de usar git push sin argumentos. Sigue siendo que todavía tengo que recordar 'git push -u origin my-branch' cuando muevo mi nueva rama al control remoto por primera vez.
Karl the Pagan
19
Odio recordar esa sintaxis también, así que creé el siguiente alias:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
lillialexis
99
Todo está bien, pero sigo pensando que la queja del OP es válida. Comienza una rama local, trabaja en ella, la empuja al origen para compartir (sin argumentos); ¿por qué no debería eso establecer la corriente arriba? ¿Es realmente deseable por alguna razón NO configurar upstream cuando se empuja una nueva rama a un control remoto?
GaryO
23
Totalmente no vale la pena el tiempo de desarrollo. ¿Por qué no lo hace automáticamente?
sudo
1346

Puede hacer que esto suceda con menos tipeo. Primero, cambie la forma en que funciona su empuje:

git config --global push.default current

Esto inferirá la origin my_branchparte, por lo que puede hacer:

git push -u

Lo cual creará la rama remota con el mismo nombre y la rastreará.

Zamith
fuente
44
¿Cómo es posible que git infer se originejecute git push -upara una rama recién creada en un repositorio recién creado? ¿Es la suposición de que el repositorio ha sido clonado, por lo que la rama actual tiene su control remoto configurado origin?
Piotr Dobrogost
73
Este debería ser el predeterminado. Tantas cosas en git podrían ser más fáciles de usar si solo se envían con mejores valores predeterminados.
phreakhead
13
Tenga en cuenta que 'current' es un poco más inseguro que usar 'simple' para hacer lo mismo, consulte stackoverflow.com/questions/23918062/…
Air
30
Lo hace, pero cuando lo intentes pulltendrás que especificar desde dónde. Los -uconjuntos de hasta el seguimiento de la rama entre el origen y tu repositorio local.
Zamith
77
Si bien es marginalmente conveniente, esto aún exige que se ejecute un comando diferente para el primero y único push, lo que anula todo el punto de esta pregunta. En resumen, no hay una buena respuesta. Que los desarrolladores de Git insistan en retener esta experiencia de usuario incómoda (AUX) frente al disenso generalizado de la comunidad es ... esclarecedor. Y desalentador. (Mayormente desalentador.)
Cecil Curry
87

Puedes simplemente

git checkout -b my-branch origin/whatever

en primer lugar. Si establece branch.autosetupmergeo branch.autosetuprebase(mi favorito) en always(predeterminado es true), my-branchse realizará un seguimiento automático origin/whatever.

Ver git help config.

cdunn2001
fuente
55
Esto produce "fatal: no se pueden actualizar las rutas y cambiar a la rama 'my-branch' al mismo tiempo".
Karl the Pagan
12
Por cierto, generalmente solo git checkout -t origin/whatever, que también elige whatevercomo el nuevo nombre de rama. ¡Muy conveniente!
cdunn2001
2
@cdunn Este es ideal, pero apenas consistente. La bandera debe llamarse -u/ --set-upstream.
Tobu
1
git checkout -t origin/whateverno funciona para mí cuando intento crear una nueva sucursal:fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
1
git checkout -b my-branch origin/whatevertambién tiene el mismo error (estoy tratando de crear una nueva rama que no existe en local o remota): fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
81

Este es mi uso más común para The Fuck .

$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master

$ fuck
git push --set-upstream origin master [enter/↑/↓/ctrl+c]
Counting objects: 9, done.
...

Además, es divertido escribir palabras groseras en su terminal.

Tamlyn
fuente
Esto debe ser portado a Windows (o al menos git-bash).
BrianHVB
1
bueno, este pequeño descubrimiento acaba de alegrarme el día. gracias
Ivan Durst
Magnífica herramienta, gracias!
Yurii
81

Puede configurar upstream más simple de dos maneras. Primero cuando creas la rama:

git branch -u origin/my-branch

o después de haber creado una rama, puede usar este comando.

git push -u origin my-branch

También puede ramificar, verificar y configurar en un solo comando:

git checkout -b my-branch -t origin/my-branch

Mi preferencia personal es hacer esto en un comando de dos pasos:

git checkout -b my-branch
git push -u origin my-branch
Tzen
fuente
1
¡Gran respuesta! Aborda ambos casos de uso comunes. Después de correr git branch -u origin/my-branch, puedo correr git pullpara bajar mis cambios.
Benjamin Atkin
2
"git checkout -b my-branch -t origin / my-branch" esto no funciona si 'origin / my-branch' aún no existe.
Spongman el
1
En realidad, puede git checkout -t origin/my-branchprescindir de -b my-branch, simplemente deducirá automáticamente my-branchel nombre de la sucursal local. Sin embargo, como mencionó @Spongman, este comando no funciona si origin/my-branchno existe primero.
wisbucky
Sí, funcionará @wisbucky, -t funciona bien. Sin embargo, personalmente, incluso dos años después de que escribí esa respuesta, todavía prefiero dividirme en dos líneas con checkout -b y push -u. Es más explícito y no hay error al finalizar la compra -b cuando no tengo control remoto, lo que sucede con bastante frecuencia cuando experimento :)
Tzen
2
git push -u origin/my-branchme falla con fatal: 'origin/my-branch' does not appear to be a git repository. Esto funciona:git push -u origin my-branch
stason
48

Puedes usar:

git config --global branch.autosetupmerge siempre

que vinculará la rama ascendente cada vez que cree o finalice una nueva rama.

Ver https://felipec.wordpress.com/2013/09/01/advanced-git-concepts-the-upstream-tracking-branch/

Esto también funciona branch.autosetuprebasesi sigue un flujo de trabajo más centrado en rebase, pero no lo use a menos que sepa lo que está haciendo, ya que su comportamiento de extracción cambiará a rebase, lo que puede causar resultados extraños.

Daniel
fuente
8
No funciona, sigo recibiendo el --set-upstreammensaje
Dorian
2
@ Dorian, debe configurar esto antes de crear la rama. Ver stackoverflow.com/a/9753268/263998
cdunn2001
8
pero esto no establece la bifurcación de seguimiento como el remoto con la misma bifurcación, sino a la bifurcación local actual ... así que cuando empuje, intentará empujar a la bifurcación LOCAL que estaba antes de crear la bifurcación nueva ...
Arnold Roa
1
Esto tiene un comportamiento aún más extraño que el predeterminado. Si basas el trabajo en una rama, actúa de manera extraña.
Beefster
1
¡Ten cuidado con esta configuración! Después de configurarlo, obtienes este comportamiento. 1. Cambiar a master. 2. Corre git checkout -b new_branch. 3. Agregue un commit a esa rama. 4 git push origin new_branch.. Esto empuja ese compromiso con la masterrama en origen (en lugar de una nueva rama en origen llamada new_branch).
stwr667
38

Por cierto, el atajo para empujar la rama actual a un control remoto con el mismo nombre:

$ git push -u origin HEAD
djanowski
fuente
22

Yo personalmente uso estos siguientes alias en bash

en el archivo ~ / .gitconfig

[alias]
    pushup = "!git push --set-upstream origin $(git symbolic-ref --short HEAD)"

y en el archivo ~ / .bashrc o ~ / .zshrc

alias gpo="git pushup"
alias gpof="gpo -f"
alias gf="git fetch"
alias gp="git pull"
Amrit Shrestha
fuente
1
Solo necesitaba hacer hcange .gitconfig, luego podría usar el comando git pushupque siempre empuja la rama actual al origen. Siempre puedo usar en git pushuplugar de git push👍
thespacecamel
18

Si lo siguiente no funciona:

git config --global push.default current

También debe actualizar la configuración local de su proyecto, ya que es posible que su proyecto tenga configuraciones locales de git:

git config --local push.default current
youngrrrr
fuente
2
Más explicaciones serían geniales. ¿Qué hace la primera línea?
Papillon
3
Esta respuesta es la que se siente legítima. Todos los que proponen alias son soluciones tontas. Y los otros que justifican memorizar secuencias de comandos largas son pedantes.
MarkHu
10

También puede decirle explícitamente a git pull qué rama remota extraer (como se menciona en el mensaje de error):

git pull <remote-name> <remote-branch>

Sin embargo, tenga cuidado con esto: si se encuentra en una rama diferente y realiza una extracción explícita, la especificación de referencia que extraiga se fusionará con la rama en la que se encuentra.

mtbkrdave
fuente
10

Por lo que vale, si está intentando rastrear una rama que ya existe en el control remoto (por ejemplo, origen / alguna rama) pero aún no la ha extraído localmente, puede hacer lo siguiente:

$ git checkout --track origin/somebranch

Nota: '-t' es la versión abreviada de la opción '--track'.

Esto establece la misma asociación desde el principio.

mattacular
fuente
55
En realidad, solo puedes pagar en la sucursal. Entonces git checkout somebranches equivalente.
Zamith
2
@Zamith ¿No funciona eso solo después de haber llamado git fetchinmediatamente?
Walter Roman
1
No de inmediato, pero sí, debe tener una referencia a esa sucursal en su repositorio local, lo que sucede cada vez que llama git fetcho git pull. Sin embargo, nunca he encontrado que eso sea un problema.
Zamith
10
git branch --set-upstream-to=origin/master<branch_name>

fuente
9

Uso este alias de Git en lugar de copiar / pegar la sugerencia de Git cada vez: https://gist.github.com/ekilah/88a880c84a50b73bd306

Fuente copiada a continuación (agregue esto a su ~/.gitconfigarchivo):

[alias]
  pushup = "!gitbranchname() { git symbolic-ref --short HEAD; }; gitpushupstream() { git push --set-upstream origin `gitbranchname`; }; gitpushupstream"
manroe
fuente
7

Puede configurar un alias realmente bueno que pueda manejar esto sin la sintaxis demasiado detallada.

Tengo el siguiente alias en ~/.gitconfig:

po = "!git push -u origin \"$(git rev-parse --abbrev-ref HEAD)\""

Después de realizar una confirmación en una nueva rama, puede empujar su nueva rama simplemente escribiendo el comando:

git po
123
fuente
¿Por qué po? push origin? ¿Qué pasa si esto se ejecuta varias veces?
Arnold Roa
Sí, como en origen de inserción. No pasa nada si se ejecuta varias veces. También tengo un git push -falias configurado git pf, así que lo uso una vez que el origen ya se ha presionado.
123
vea el comentario de djanowski , puede usar directamenteHEAD
arhak
3

Para aquellos que buscan un alias que funcione git pull, esto es lo que uso:

alias up="git branch | awk '/^\\* / { print \$2 }' | xargs -I {} git branch --set-upstream-to=origin/{} {}"

Ahora cada vez que obtienes:

$ git pull
There is no tracking information for the current branch.
...

Solo corre:

$ up
Branch my_branch set up to track remote branch my_branch from origin.
$ git pull

Y eres bueno para ir

jchavannes
fuente
2

Porque git tiene la capacidad genial de empujar / jalar diferentes ramas a diferentes repositorios "aguas arriba". Incluso podría usar repositorios separados para empujar y tirar, en la misma rama. Esto puede crear un flujo distribuido de varios niveles, puedo ver que esto es útil en proyectos como el kernel de Linux. Git fue originalmente construido para ser usado en ese proyecto.

Como consecuencia, no supone qué repositorio debe rastrear su sucursal.

Por otro lado, la mayoría de las personas no usan git de esta manera, por lo que podría ser un buen caso para una opción predeterminada.

Git generalmente es de bajo nivel y puede ser frustrante. Sin embargo, hay interfaces gráficas de usuario y debería ser fácil escribir scripts de ayuda si todavía desea usarlo desde el shell.

Rolf
fuente
2

También puedes hacer git push -u origin $(current_branch)

ourmaninamsterdam
fuente
0

Me re-descubrí legitpor este problema (solo OS X). Ahora todo lo que uso cuando ramifico son estos dos comandos:

legit publish [<branch>] Publica la rama especificada en el control remoto. (alias: pub)

legit unpublish <branch> Elimina la rama especificada del control remoto. (alias: unp)

SublimeGit viene con legitsoporte por defecto, lo que hace que toda la rutina de ramificación sea tan fácil como presionar Ctrl-b.

Benny K
fuente
0

Usamos phabricator y no empujamos usando git. Tuve que crear bash alias que funciona en Linux / mac

vim ~/.bash_aliases

new_branch() {
    git checkout -b "$1"
    git branch --set-upstream-to=origin/master "$1"
}

salvar

source ~/.bash_aliases
new_branch test #instead of git checkout -b test
git pull
om471987
fuente
0

Aquí hay un alias bash para git push que es seguro de ejecutar para cada empuje y cambiará automáticamente entre la configuración aguas arriba para el primer empuje y luego hacer los empujes normales después de eso.

alias gpu='[[ -z $(git config "branch.$(git symbolic-ref --short HEAD).merge") ]] && git push -u origin $(git symbolic-ref --short HEAD) || git push'

Publicación original

Loren
fuente