Por que eu preciso fazer o `--set-upstream` o tempo todo?

1468

Eu crio uma nova ramificação no Git:

git branch my_branch

Empurre-o:

git push origin my_branch

Agora digamos que alguém fez algumas alterações no servidor e eu quero retirar origin/my_branch. Eu faço:

git pull

Mas eu entendo:

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.

Aprendi que posso fazê-lo funcionar com:

git branch --set-upstream my_branch origin/my_branch

Mas por que preciso fazer isso para cada ramo que eu criar? Não é óbvio que, se eu my_branchentrar origin/my_branch, eu gostaria de origin/my_branchentrar my_branch? Como posso tornar esse comportamento padrão?

Ram Rachum
fonte
21
O padrão para branch.autosetupmergesignifica que a configuração upstream para uma nova ramificação é definida automaticamente somente ao criar uma ramificação a partir de uma ramificação de rastreamento remoto (por exemplo <remote-name>/<branch-name>) (consulte git-config (1) ). Você provavelmente está criando suas ramificações a partir de ramificações locais existentes. Se você estiver efetivamente ramificando diretamente da ponta de uma ramificação remota (apesar de estar em uma ramificação local), poderá usar git branch my_branch <remote-name>/<branch-name>para definir automaticamente a configuração upstream.
Chris Johnsen
20
Para sua informação, a --set-upstreamopção está obsoleta. Você deve usar --trackou em --set-upstream-tovez disso.
Sean the Bean
139
se --set-upstreamfor descontinuado, talvez os devs git devam removê-lo da mensagem de ajuda que é exibida quando você executa git pushsem opções e sem o montante configurado.
Christopher Hunter
17
@ChristopherHunter Já faz mais de um ano desde o seu comentário e ele ainda diz isso. É apenas um feedback desleixado ou talvez haja uma razão tecnicamente sábia para manter isso em torno do qual ignoramos?
Konrad Viltersten
15
@ChristopherHunter git branch --set-upstreamestá obsoleto. git push --set-upstreamnão é.
Brian Gordon

Respostas:

1538

Um atalho, que não depende da lembrança da sintaxe para git branch --set-upstream 1, é o seguinte:

git push -u origin my_branch

... a primeira vez que você empurra esse galho. Ou, para enviar para a ramificação atual para uma ramificação com o mesmo nome (útil para um alias):

git push -u origin HEAD

Você só precisa usar -uuma vez, e isso configura a associação entre sua filial e a originda mesma maneira que git branch --set-upstreamfaz.

Pessoalmente, acho bom ter que estabelecer essa associação entre sua filial e a filial remota explicitamente. É uma pena que as regras sejam diferentes para git pushegit pull .


1 Pode parecer bobagem, mas eu frequentemente esqueço de especificar o ramo atual, assumindo que esse é o padrão - não é, e os resultados são mais confusos :)

Atualização 11/10/2012 : Aparentemente, não sou a única pessoa que achou fácil errar! Agradecemos ao VonC por apontar que o git 1.8.0 apresenta o mais óbvio git branch --set-upstream-to, que pode ser usado da seguinte maneira, se você estiver no ramo my_branch:

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

... ou com a opção curta:

git branch -u origin/my_branch

Essa alteração e seu raciocínio estão descritos nas notas de lançamento do git 1.8.0, candidato a lançamento 1 :

Era tentador dizer git branch --set-upstream origin/master, mas isso diz ao Git para organizar a filial local origin/masterpara integrar-se à filial atualmente com check-out, o que é altamente improvável o que o usuário quis dizer. A opção está obsoleta; use a nova opção --set-upstream-to(com um pequeno e doce -u).

Mark Longair
fonte
95
Observe também que, mesmo se você esquecer a -uprimeira vez que você enviar, poderá executá-lo novamente com essa bandeira e ela começará a rastrear.
Henrik N
70
Nada disso satisfaz o caso de uso do git push sem argumentos. Resta ainda me lembrar de 'git push -u origin my-branch' ao mover meu novo branch para o controle remoto pela primeira vez.
Karl the Pagan
19
Eu odeio lembrando que a sintaxe, bem, então eu criei o seguinte apelido:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
lillialexis
99
Tudo bem, mas ainda acho que a denúncia do OP é válida. Você inicia um ramo local, trabalha nele, envia-o à origem para compartilhar (sem argumentos); por que isso não deveria configurar o upstream? É realmente desejável, por algum motivo, NÃO configurar o upstream ao enviar uma nova ramificação para um controle remoto?
precisa saber é
23
Totalmente não vale tempo dev. Por que não faz isso automaticamente?
Sudo
1346

Você pode fazer isso acontecer com menos digitação. Primeiro, mude a maneira como seu push funciona:

git config --global push.default current

Isso inferirá a origin my_branchparte, assim você pode fazer:

git push -u

O que criará a ramificação remota com o mesmo nome e a rastreará.

Zamith
fonte
4
Como o git pode inferir originao executar git push -upara uma ramificação recém-criada no repositório recém-criado? A suposição de que o repositório foi clonado para que o ramo atual tenha seu controle remoto definido origin?
Piotr Dobrogost
73
Esse deve ser o padrão. Tantas coisas no git poderiam ser mais fáceis de usar se fossem fornecidas com padrões melhores.
phreakhead
13
Esteja ciente de que 'current' é um pouco inseguro do que usar 'simple' para fazer a mesma coisa, consulte stackoverflow.com/questions/23918062/…
Air
30
Sim, mas quando você tentar, pullprecisará especificar de onde. As -uconfigura o rastreamento ramo entre a origem eo seu repositório local.
Zamith 29/05
7
Embora marginalmente conveniente, isso ainda exige que um comando diferente seja executado para o primeiro e único push- o que derrota todo o ponto dessa questão. Em suma, não há uma boa resposta. O fato de os desenvolvedores do Git insistirem em manter essa experiência estranha de usuário (AUX) em face da dissidência generalizada da comunidade é ... esclarecedor. E desanimador. (Principalmente desencorajar.)
Cecil Curry
87

Você pode simplesmente

git checkout -b my-branch origin/whatever

em primeiro lugar. Se você definir branch.autosetupmergeou branch.autosetuprebase(o meu favorito) para always(o padrão é true), my-branchrastreará automaticamente origin/whatever.

Veja git help config.

cdunn2001
fonte
5
Isso produz "fatal: não é possível atualizar os caminhos e alternar para a ramificação 'my-branch' ao mesmo tempo."
Karl the Pagan
12
By the way, eu geralmente apenas git checkout -t origin/whatever, que também escolhe whatevercomo o novo nome do ramo. Muito conveniente!
cdunn2001
2
@cdunn Este é o ideal, mas dificilmente consistente. O sinalizador deve ser chamado -u/ --set-upstream.
Tobu
1
git checkout -t origin/whatevernão funciona para mim ao tentar criar um novo ramo:fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
1
git checkout -b my-branch origin/whatevertambém tem o mesmo erro (Eu estou tentando criar um novo ramo que não existe no local ou remoto): fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
81

Este é o meu uso mais comum 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.
...

Além disso, é divertido digitar palavrões no seu terminal.

Tamlyn
fonte
Isso precisa ser portado para o Windows (ou pelo menos git-bash).
BrianHVB
1
bem, essa pequena descoberta acabou de fazer o meu dia. obrigado
Ivan Durst
Ferramenta magnífica, obrigado!
Yurii 8/04
81

Você pode configurar o upstream mais simples de duas maneiras. Primeiro quando você cria a ramificação:

git branch -u origin/my-branch

ou depois de criar uma ramificação, você pode usar este comando.

git push -u origin my-branch

Você também pode ramificar, fazer check-out e configurar o upstream em um único comando:

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

Minha preferência pessoal é fazer isso em um comando de duas etapas:

git checkout -b my-branch
git push -u origin my-branch
Tzen
fonte
1
Ótima resposta! Aborda os dois casos de uso comuns. Depois de executar git branch -u origin/my-branch, posso executar git pullpara baixar minhas alterações.
Benjamin Atkin
2
"git checkout -b minha ramificação -t origem / minha ramificação" isto não funciona se 'origem / minha ramificação' ainda não existir.
Spongman
1
Na verdade, você pode simplesmente ficar git checkout -t origin/my-branchsem o -b my-branch, ele inferirá automaticamente my-brancho nome da filial local. No entanto, como o @Spongman mencionou, este comando não funcionará se origin/my-branchnão existir primeiro.
wisbucky
Sim, funcionará @wisbucky, -t funciona muito bem. No entanto, pessoalmente, mesmo dois anos depois de escrever essa resposta, ainda prefiro dividir em duas linhas com o checkout -b e o push -u. É mais explícito e nenhum erro na -b check-out quando eu não tenho controle remoto - que acontece muitas vezes quando experimentando :)
Tzen
2
git push -u origin/my-branchfalha para mim com fatal: 'origin/my-branch' does not appear to be a git repository. Isso funciona:git push -u origin my-branch
stason 26/10/18
48

Você pode usar:

git config --global branch.autosetupmerge always

que vinculará a ramificação upstream sempre que você criar ou efetuar checkout de uma nova ramificação.

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

Isso também funciona com branch.autosetuprebase, se você seguir um fluxo de trabalho mais focado em rebase, mas não o use a menos que saiba o que está fazendo, pois o padrão de comportamento do pull será rebase, o que pode causar resultados estranhos.

Daniel
fonte
8
Não funciona, eu ainda recebo a --set-upstreammensagem #
307 Dorian
2
@Dorian, você deve definir isso antes de criar o ramo. Veja stackoverflow.com/a/9753268/263998
cdunn2001
8
mas isso não define a ramificação de rastreamento como remota com a mesma ramificação, mas com a ramificação local atual. Portanto, quando você pressiona, tenta empurrar para a ramificação LOCAL que era antes de criar a nova ramificação ..
Arnold Roa
1
Isso tem um comportamento ainda mais estranho que o padrão. Se você basear o trabalho em um ramo, ele age de maneira estranha.
Beefster
1
Cuidado com essa configuração !! Depois de configurá-lo, você obtém esse comportamento. 1. Mude para master. 2. Corra git checkout -b new_branch. 3. Adicione uma confirmação a esse ramo. 4 git push origin new_branch. Isso empurra os comprometimentos para a masterramificação na origem (em vez de para uma nova ramificação na origem chamada new_branch).
stwr667
38

A propósito, o atalho para enviar a ramificação atual para um controle remoto com o mesmo nome:

$ git push -u origin HEAD
djanowski
fonte
22

Eu pessoalmente uso estes alias seguintes no bash

no arquivo ~ / .gitconfig

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

e no arquivo ~ / .bashrc ou ~ / .zshrc

alias gpo="git pushup"
alias gpof="gpo -f"
alias gf="git fetch"
alias gp="git pull"
Amrit Shrestha
fonte
1
Eu só precisava hcange .gitconfig, então eu poderia usar o comando git pushupque sempre envia a ramificação atual à origem. Eu sempre pode apenas usar git pushupem vez de git push👍
thespacecamel
18

Se o abaixo não funcionar:

git config --global push.default current

Você também deve atualizar a configuração local do seu projeto, pois é possível que seu projeto tenha configurações locais do git:

git config --local push.default current
youngrrrr
fonte
2
Mais explicações seriam ótimas. O que a primeira linha faz?
papillon
3
Essa resposta é a que parece legítima. Todos os que propõem aliases são soluções estúpidas. E os outros que justificam memorizar longas seqüências de comando são pedantes.
MarkHu
10

Você também pode dizer explicitamente ao git pull qual ramificação remota puxar (conforme mencionado na mensagem de erro):

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

No entanto, tenha cuidado com isso: se você estiver em um ramo diferente e fizer um puxão explícito, o refspec que você puxará será mesclado no galho em que você está!

mtbkrdave
fonte
10

Pelo que vale a pena, se você estiver tentando rastrear um ramo que já existe no controle remoto (por exemplo, origin / somebranch), mas ainda não o fez check-out localmente, você pode:

$ git checkout --track origin/somebranch

Nota: '-t' é a versão abreviada da opção '--track'.

Isso cria a mesma associação logo de cara.

mattacular
fonte
5
Na verdade, você pode apenas fazer checkout na filial. Então git checkout somebranché equivalente.
Zamith
2
@Zamith Isso não funciona apenas depois de ligar git fetchimediatamente?
Walter Roman
1
Não imediatamente, mas sim, você precisa ter uma referência a essa ramificação no seu repositório local, o que acontece sempre que você ligar git fetchou git pull. Eu nunca achei isso um problema, no entanto.
Zamith
10
git branch --set-upstream-to=origin/master<branch_name>

fonte
9

Eu uso esse alias do Git em vez de copiar / colar a sugestão do Git sempre: https://gist.github.com/ekilah/88a880c84a50b73bd306

Fonte copiada abaixo (adicione isso ao seu ~/.gitconfigarquivo):

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

Você pode configurar um alias realmente bom que possa lidar com isso sem a sintaxe excessivamente detalhada.

Eu tenho o seguinte alias em ~/.gitconfig:

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

Depois de fazer uma confirmação em uma nova ramificação, você pode enviar sua nova ramificação simplesmente digitando o comando:

git po
123
fonte
por que po? push origin? o que acontecerá se isso for executado várias vezes?
Arnold Roa
Sim, como na origem do envio. Nada acontece se for executado várias vezes. Eu também tenho um git push -falias configurado git pf, então eu o uso assim que a origem já tiver sido enviada.
123
veja o comentário de djanowski , você pode usar diretamenteHEAD
arhak
3

Para quem procura um alias que funcione git pull, é isso que eu uso:

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

Agora sempre que você obtiver:

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

Apenas corra:

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

E você está pronto para ir

jchavannes
fonte
2

Porque o git tem a capacidade legal de enviar / puxar ramificações diferentes para diferentes repositórios "upstream". Você pode até usar repositórios separados para empurrar e puxar - no mesmo ramo. Isso pode criar um fluxo distribuído em vários níveis; posso ver isso sendo útil em projetos como o kernel do Linux. O Git foi originalmente desenvolvido para ser usado nesse projeto.

Como conseqüência, ele não assume que repositório sua filial deve rastrear.

Por outro lado, a maioria das pessoas não usa o git dessa maneira, portanto pode ser uma boa opção para uma opção padrão.

O Git geralmente é de nível bastante baixo e pode ser frustrante. No entanto, existem GUIs e deve ser fácil escrever scripts auxiliar se você ainda quiser usá-lo no shell.

Rolf
fonte
2

Você também pode fazer git push -u origin $(current_branch)

ourmaninamsterdam
fonte
0

Eu meio que re-descobri legitpor causa desse problema (apenas OS X). Agora, tudo o que uso ao ramificar são esses dois comandos:

legit publish [<branch>] Publica ramificação especificada no controle remoto. (pseudónimo: pub)

legit unpublish <branch> Remove a ramificação especificada do controle remoto. (pseudónimo: unp)

O SublimeGit vem com legitsuporte por padrão, o que torna toda a rotina de ramificação tão fácil quanto pressionar Ctrl-b.

Benny K
fonte
0

Usamos o phabricator e não pressionamos usando o git. Eu tive que criar o alias do bash que funciona no Linux / mac

vim ~/.bash_aliases

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

Salve 

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

Aqui está um alias do bash para o git push, que é seguro para executar a cada push e alternará automaticamente entre a configuração upstream para o primeiro push e a execução de push normais depois disso.

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

Correio Original

Loren
fonte