Perché devo fare sempre "--set-upstream"?


1469

Creo una nuova filiale in Git:

git branch my_branch

Spingilo:

git push origin my_branch

Ora dì che qualcuno ha apportato alcune modifiche al server e voglio estrarre origin/my_branch. Lo voglio:

git pull

Ma ottengo:

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.

Ho imparato che posso farlo funzionare con:

git branch --set-upstream my_branch origin/my_branch

Ma perché devo farlo per ogni ramo che creo? Non è ovvio che se spingo my_branchdentro origin/my_branch, allora vorrei origin/my_branchentrare my_branch? Come posso rendere questo comportamento predefinito?


21
L'impostazione predefinita per branch.autosetupmergeindica che la configurazione upstream per un nuovo ramo viene impostata automaticamente solo quando si crea un ramo da un ramo di tracciamento remoto (ad es. <remote-name>/<branch-name>) (Vedere git-config (1) ). Probabilmente stai creando le tue filiali da filiali locali esistenti. Se si sta effettivamente ramificando direttamente dalla punta di un ramo remoto (nonostante si trovi su un ramo locale), è possibile utilizzare git branch my_branch <remote-name>/<branch-name>per impostare automaticamente la configurazione a monte.
Chris Johnsen,

20
Cordiali saluti, l' --set-upstreamopzione è obsoleta. Dovresti usare --tracko --set-upstream-toinvece.
Sean the Bean,

139
se --set-upstreamè deprecato, forse gli sviluppatori git dovrebbero rimuoverlo dal messaggio di aiuto che viene visualizzato quando si esegue git pushsenza opzioni e non è impostato alcun upstream?
Christopher Hunter,

17
@ChristopherHunter È passato più di un anno dal tuo commento e lo dice ancora . È solo un feedback sciatto o forse c'è una ragione tecnicamente saggia per tenerlo in giro di cui siamo ignoranti?
Konrad Viltersten,

15
@ChristopherHunter git branch --set-upstreamè deprecato. git push --set-upstreamnon è.
Brian Gordon,

Risposte:


1538

Una scorciatoia, che non dipende dal ricordare la sintassi per git branch --set-upstream 1, è fare:

git push -u origin my_branch

... la prima volta che spingi quel ramo. Oppure, per passare al ramo corrente su un ramo con lo stesso nome (utile per un alias):

git push -u origin HEAD

Hai solo bisogno di usare -uuna volta, e questo imposta l'associazione tra il tuo ramo e quello originnello stesso modo in cui lo git branch --set-upstreamfa.

Personalmente, penso che sia una buona cosa dover creare esplicitamente quell'associazione tra la tua filiale e una sul telecomando. È un peccato che le regole siano diverse per git pushegit pull .


1 Può sembrare sciocco, ma mi dimentico molto spesso di specificare il ramo corrente, supponendo che sia quello predefinito - non lo è, e i risultati sono più confusi :)

Aggiornamento 2012-10-11 : Apparentemente non sono l'unica persona che ha trovato facile sbagliarsi! Grazie a VonC per aver sottolineato che git 1.8.0 introduce il più ovvio git branch --set-upstream-to, che può essere usato come segue, se sei sul ramo my_branch:

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

... o con l'opzione breve:

git branch -u origin/my_branch

Questa modifica e il suo ragionamento sono descritti nelle note di rilascio di git 1.8.0, rilascio candidato 1 :

Era allettante dirlo git branch --set-upstream origin/master, ma questo dice a Git di organizzare il ramo locale origin/masterper integrarlo con il ramo attualmente estratto, il che è altamente improbabile sul significato dell'utente. L'opzione è obsoleta; usa invece la nuova opzione --set-upstream-to(con una breve e dolce -u).


95
Si noti inoltre che anche se si dimentica la -uprima volta che si preme, è possibile eseguire nuovamente la spinta con quella bandiera e inizierà il tracciamento.
Henrik N,

70
Nessuno di questi soddisfa il caso d'uso dell'uso di git push senza argomenti. Resta che devo ancora ricordare di 'git push -u origin my-branch' quando trasferisco il mio nuovo ramo sul telecomando per la prima volta.
Karl the Pagan,

19
Odio ricordare anche quella sintassi, quindi ho creato il seguente alias:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
lillialexis,

99
Va tutto bene, ma penso ancora che il reclamo del PO sia valido. Si avvia un ramo locale, ci si lavora, lo si spinge all'origine per condividere (senza argomenti); perché questo non dovrebbe impostare l'upstream? È davvero desiderabile per qualche motivo NON impostare a monte quando si spinge un nuovo ramo su un telecomando?
GaryO,

23
Non vale assolutamente il tempo di sviluppo. Perché non lo fa solo automaticamente?
sudo,

1346

Puoi farlo accadere con meno battiture. Innanzitutto, modifica il modo in cui funziona la tua push:

git config --global push.default current

Questo inferirà la origin my_branchparte, quindi puoi fare:

git push -u

Ciò creerà entrambi il ramo remoto con lo stesso nome e lo seguirà.


4
Come può git inferire originquando si esegue git push -uper il ramo appena creato nel repository appena creato? Si presume che il repository sia stato clonato in modo che il ramo corrente abbia il suo telecomando impostato su origin?
Piotr Dobrogost,

73
Questo dovrebbe essere il valore predefinito. Tante cose in git potrebbero essere più user-friendly se spedito con impostazioni predefinite migliori.
phreakhead,

13
Tieni presente che "attuale" è leggermente più pericoloso dell'uso di "semplice" per fare la stessa cosa, vedi stackoverflow.com/questions/23918062/…
Air

30
Lo fa, ma quando proverai pulldovrai specificare da dove. I -uset up il tracking ramo tra l'origine e il vostro repo locale.
Zamith,

7
Seppur marginalmente conveniente, ciò richiede comunque che venga eseguito un comando diverso per il primo e unico push- che sconfigge l'intero punto di questa domanda. In breve, non c'è una buona risposta. Che gli sviluppatori di Git insistano nel mantenere questa eXperience (AUX) Awkward User di fronte al diffuso dissenso della comunità è ... illuminante. E scoraggiante. (Per lo più scoraggiante.)
Cecil Curry

87

Puoi semplicemente

git checkout -b my-branch origin/whatever

innanzitutto. Se si imposta branch.autosetupmergeo branch.autosetuprebase(il mio preferito) su always(impostazione predefinita è true), my-branchverrà automaticamente monitorato origin/whatever.

Vedere git help config.


5
Questo produce "fatale: impossibile aggiornare i percorsi e passare contemporaneamente al ramo" my-branch "."
Karl the Pagan,

12
A proposito, di solito lo so git checkout -t origin/whatever, che sceglie anche whatevercome nuovo nome di filiale. Molto conveniente!
cdunn2001,

2
@cdunn Questo è l'ideale, ma difficilmente coerente. Il flag dovrebbe essere chiamato -u/ --set-upstream.
Tobu,

1
git checkout -t origin/whatevernon funziona per me quando fatal: Cannot update paths and switch to branch 'whatever' at the same time.
provo

1
git checkout -b my-branch origin/whateverha anche lo stesso errore (sto cercando di creare un nuovo ramo che non esiste su locale o remoto): fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky

81

Questo è il mio uso più comune per 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.
...

Inoltre, è divertente digitare parolacce nel tuo terminale.


Questo quindi deve essere portato su Windows (o almeno git-bash).
BrianHVB,

1
beh questa piccola scoperta mi ha appena reso felice. grazie
Ivan Durst il

Strumento magnifico, grazie!
Yurii

81

È possibile impostare l'upstream più semplice in due modi. Innanzitutto quando si crea il ramo:

git branch -u origin/my-branch

o dopo aver creato un ramo, è possibile utilizzare questo comando.

git push -u origin my-branch

Puoi anche ramificare, estrarre e impostare upstream in un singolo comando:

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

La mia preferenza personale è di farlo in un comando in due passaggi:

git checkout -b my-branch
git push -u origin my-branch

1
Bella risposta! Risolve entrambi i casi d'uso comuni. Dopo l'esecuzione, git branch -u origin/my-branchposso correre git pullper annullare le mie modifiche.
Benjamin Atkin,

2
"git checkout -b my-branch -t origin / my-branch" non funziona se 'origin / my-branch' non esiste ancora.
Spongman,

1
In realtà puoi semplicemente fare a git checkout -t origin/my-branchmeno di -b my-branch, si dedurrà automaticamente my-branchal nome del ramo locale. Tuttavia, come menzionato @Spongman, questo comando non funziona se origin/my-branchnon esiste per primo.
Wisbucky

Sì, funzionerà @wisbucky, -t funziona bene. Personalmente, anche se due anni dopo aver scritto quella risposta, preferisco comunque dividere in due righe con il checkout -b e il push -u. È più esplicito e nessun errore al checkout -b quando non ho il telecomando - cosa che succede abbastanza spesso durante gli esperimenti :)
Tzen

2
git push -u origin/my-branchfallisce per me con fatal: 'origin/my-branch' does not appear to be a git repository. Funziona così:git push -u origin my-branch
Stason,

48

Puoi usare:

git config --global branch.autosetupmerge sempre

che collegherà il ramo upstream ogni volta che crei o esegui il checkout di un nuovo ramo.

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

Funziona anche con branch.autosetuprebase, se segui un flusso di lavoro più focalizzato sul rebase, ma non utilizzalo a meno che tu non sappia cosa stai facendo, poiché il comportamento pull verrà predefinito in rebase, il che può causare risultati strani.


8
Non funziona, ricevo ancora il --set-upstreammessaggio
Dorian,

2
@Dorian, devi impostarlo prima di creare il ramo. Vedere stackoverflow.com/a/9753268/263998
cdunn2001

8
ma questo non imposta il ramo di tracciamento come remoto con lo stesso ramo, ma al ramo locale corrente .. quindi quando lo fai, proverai a spingere sul ramo LOCALE che stavi prima di creare il nuovo ramo ..
Arnold Roa

1
Questo ha un comportamento ancora più strano di quello predefinito. Se si basa il lavoro su un ramo, agisce in modo davvero strano.
Beefster,

1
Stai attento con questa impostazione !! Dopo averlo impostato, ottieni questo comportamento. 1. Passa a master. 2. Esegui git checkout -b new_branch. 3. Aggiungi un commit a quel ramo. 4 git push origin new_branch. Questo spinge quel commit sul masterramo sull'origine (piuttosto che su un nuovo ramo sull'origine chiamato new_branch).
stwr667,

38

A proposito, il collegamento per spingere il ramo corrente su un telecomando con lo stesso nome:

$ git push -u origin HEAD

22

Personalmente uso questi seguenti alias in bash

nel file ~ / .gitconfig

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

e nel file ~ / .bashrc o ~ / .zshrc

alias gpo="git pushup"
alias gpof="gpo -f"
alias gf="git fetch"
alias gp="git pull"

1
Avevo solo bisogno di modificare .gitconfig, quindi potevo usare il comando git pushupche porta sempre il ramo corrente all'origine. Posso sempre basta usare git pushupal posto di git push👍
thespacecamel

18

Se il seguito non funziona:

git config --global push.default current

Dovresti anche aggiornare la configurazione locale del tuo progetto, poiché è possibile che il tuo progetto abbia configurazioni git locali:

git config --local push.default current

2
Altre spiegazioni sarebbero grandi. Cosa fa la prima riga?
papillon,

3
Questa risposta è quella che sembra legittima. Tutti quelli che propongono degli alias sono stupide soluzioni alternative. E gli altri che giustificano la memorizzazione di lunghe sequenze di comandi sono pedanti.
MarkHu,

10

Puoi anche dire esplicitamente a git pull quale ramo remoto estrarre (come menziona nel messaggio di errore):

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

Fai attenzione, tuttavia: se ti trovi su un ramo diverso e fai un pull esplicito, il refspec che tirerai verrà unito al ramo in cui ti trovi!


10

Per quello che vale, se stai cercando di rintracciare un ramo già esistente sul telecomando (es. Origin / somebranch) ma non l'hai ancora verificato localmente, puoi fare:

$ git checkout --track origin/somebranch

Nota: '-t' è la versione abbreviata dell'opzione '--track'.

Questo crea la stessa associazione fin dall'inizio.


5
Puoi effettivamente fare il checkout alla filiale. Quindi git checkout somebranchè equivalente.
Zamith,

2
@Zamith Non funziona solo dopo aver chiamato git fetchsubito prima?
Walter Roman,

1
Non immediatamente, ma sì, devi avere un riferimento a quel ramo sul tuo repository locale, che si verifica ogni volta che chiami git fetcho git pull. Non ho mai scoperto che questo sia un problema, però.
Zamith,

10
git branch --set-upstream-to=origin/master<branch_name>

9

Uso questo alias Git invece di copiare / incollare il suggerimento da Git ogni volta: https://gist.github.com/ekilah/88a880c84a50b73bd306

Sorgente copiata di seguito (aggiungi questo al tuo ~/.gitconfigfile):

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

7

È possibile impostare un alias davvero valido in grado di gestirlo senza la sintassi eccessivamente dettagliata.

Ho il seguente alias in ~/.gitconfig:

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

Dopo aver effettuato il commit su un nuovo ramo, puoi inviare il tuo nuovo ramo semplicemente digitando il comando:

git po

perchè po? push origin? cosa succede se questo viene eseguito più volte?
Arnold Roa,

Sì, come nell'origine push. Non succede nulla se viene eseguito più volte. Ho anche un git push -falias impostato su git pf, quindi lo uso una volta che l'origine è già stata spinta.
123

vedi il commento di djanowski , puoi usarlo direttamenteHEAD
arhak,

3

Per coloro che cercano un alias che funziona git pull, questo è quello che uso:

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

Ora ogni volta che ottieni:

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

Corri:

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

E sei a posto


2

Perché git ha la straordinaria capacità di spingere / trascinare diversi rami in diversi repository "a monte". Puoi persino usare repository separati per spingere e tirare - sullo stesso ramo. Questo può creare un flusso distribuito a più livelli, posso vederlo essere utile su progetti come il kernel Linux. Git è stato originariamente costruito per essere utilizzato su quel progetto.

Di conseguenza, non fa ipotesi su quale repository deve essere monitorato dal proprio ramo.

D'altra parte, la maggior parte delle persone non usa git in questo modo, quindi potrebbe essere un buon caso per un'opzione predefinita.

Git è generalmente di basso livello e può essere frustrante. Tuttavia ci sono GUI e dovrebbe essere facile scrivere script di supporto se si desidera ancora usarlo dalla shell.



0

Ho scoperto di nuovo a legitcausa di questo problema (solo OS X). Ora tutto ciò che uso durante la ramificazione sono questi due comandi:

legit publish [<branch>] Pubblica il ramo specificato sul telecomando. (alias:pub )

legit unpublish <branch> Rimuove il ramo specificato dal telecomando. (alias: unp)

SublimeGit viene fornito con il legitsupporto di default, il che rende l'intera routine di ramificazione facile come premere Ctrl-b.


0

Usiamo phabricator e non spingiamo usando git. Ho dovuto creare alias bash che funziona su Linux / mac

vim ~/.bash_aliases

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

Salva

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

0

Ecco un alias bash per git push, che è sicuro da eseguire per ogni push e passerà automaticamente dall'impostazione a monte per la prima push e poi da quelle normali.

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

Posta originale

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.