Dlaczego muszę cały czas robić `--set-upstream`?

1466

Tworzę nowy oddział w Git:

git branch my_branch

Popchnij:

git push origin my_branch

Teraz powiedz, że ktoś dokonał pewnych zmian na serwerze, a ja chcę z niego skorzystać origin/my_branch. Ja robię:

git pull

Ale dostaję:

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.

Nauczyłem się, że mogę sprawić, by działał z:

git branch --set-upstream my_branch origin/my_branch

Ale dlaczego muszę to robić dla każdej tworzonej gałęzi? Czy to nie jest oczywiste, że jeśli pcham my_branchsię origin/my_branch, a potem chciałbym ciągnąć origin/my_branchsię my_branch? Jak mogę ustawić to jako domyślne zachowanie?

Ram Rachum
źródło
21
Domyślna wartość branch.autosetupmergeoznacza, że ​​konfiguracja początkowa dla nowej gałęzi jest ustawiana automatycznie tylko podczas tworzenia gałęzi ze zdalnej gałęzi śledzenia (np. <remote-name>/<branch-name>) (Patrz git-config (1) ). Prawdopodobnie tworzysz swoje oddziały z istniejących oddziałów lokalnych. Jeśli skutecznie rozgałęziasz się bezpośrednio z wierzchołka gałęzi zdalnej (pomimo tego, że jesteś w gałęzi lokalnej), możesz użyć git branch my_branch <remote-name>/<branch-name>do automatycznego skonfigurowania konfiguracji nadrzędnej.
Chris Johnsen
20
FYI, --set-upstreamopcja jest przestarzała. Powinieneś użyć --tracklub --set-upstream-tozamiast tego.
Sean the Bean
139
jeśli --set-upstreamjest przestarzałe, to być może deweloperzy git powinni usunąć go z komunikatu pomocy, który wyświetla się, gdy uruchamiasz git pushsię bez opcji i nie jest ustawiony żaden upstream?
Christopher Hunter
17
@ChristopherHunter Minął ponad rok od twojego komentarza i nadal tak jest. Czy to tylko niechlujna informacja zwrotna, czy może istnieje jakiś rozsądny technicznie powód, aby nie ujawniać tego, o czym nie wiemy?
Konrad Viltersten
15
@ChristopherHunter git branch --set-upstreamjest przestarzały. git push --set-upstreamnie jest.
Brian Gordon,

Odpowiedzi:

1538

Skrót, który nie zależy od zapamiętania składni dla git branch --set-upstream 1, polega na:

git push -u origin my_branch

... za pierwszym razem, kiedy naciskasz tę gałąź. Lub, aby wypchnąć do bieżącej gałęzi do gałęzi o tej samej nazwie (przydatne dla aliasu):

git push -u origin HEAD

Musisz użyć -utylko raz, a to ustanawia powiązanie między twoim oddziałem a oddziałem originw taki sam sposób, jak git branch --set-upstreamrobi.

Osobiście uważam, że dobrze jest jawnie skonfigurować powiązanie między oddziałem a oddziałem na pilocie. Szkoda tylko, że zasady są różne dla git pushigit pull .


1 Może to zabrzmieć głupio, ale bardzo często zapominam podać bieżącą gałąź, zakładając, że jest to domyślna - nie jest, a wyniki są najbardziej mylące :)

Aktualizacja 11.10.2012 : Najwyraźniej nie jestem jedyną osobą, która łatwo się pomyliła! Dzięki VonC za zwrócenie uwagi na to, że git 1.8.0 wprowadza bardziej oczywiste git branch --set-upstream-to, których można użyć w następujący sposób, jeśli jesteś na gałęzi my_branch:

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

... lub z krótką opcją:

git branch -u origin/my_branch

Ta zmiana wraz z uzasadnieniem została opisana w uwagach do wydania dla git 1.8.0, kandydat do wydania 1 :

Kuszące było powiedzenie git branch --set-upstream origin/master, ale to mówi Gitowi, aby zorganizował lokalny oddział w origin/mastercelu integracji z aktualnie wyewidencjonowanym oddziałem, co jest bardzo mało prawdopodobne, co miał na myśli użytkownik. Opcja jest przestarzała; zamiast tego użyj nowej --set-upstream-to(z krótką i słodką -u) opcji.

Mark Longair
źródło
95
Zauważ też, że nawet jeśli zapomnisz -upierwszego naciśnięcia, możesz ponownie uruchomić push z tą flagą i rozpocznie się śledzenie.
Henrik N
70
Żadne z nich nie spełnia przypadku użycia git push bez argumentów. Pozostaje, że wciąż muszę pamiętać, aby po raz pierwszy przenieść nowy oddział do pilota, „git push -u origin my-branch”.
Karl the Pagan
19
Nienawidzę też pamiętać o tej składni, więc utworzyłem następujący alias:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
lillialexis,
99
Wszystko w porządku, ale nadal uważam, że skarga OP jest ważna. Zaczynasz lokalny oddział, pracujesz nad nim, wypychasz go do źródła, aby go udostępnić (bez argumentów); dlaczego to nie powinno ustawić upstream? Czy faktycznie z jakiegoś powodu pożądane jest NIE ustawianie upstream podczas wypychania nowej gałęzi do pilota?
GaryO
23
Całkowicie nie warty czasu deweloperów. Dlaczego nie robi to po prostu automatycznie?
sudo
1346

Możesz to zrobić przy mniejszym pisaniu. Najpierw zmień sposób działania push:

git config --global push.default current

Spowoduje to wywnioskowanie origin my_branchczęści, dzięki czemu możesz:

git push -u

Które utworzą zdalną gałąź o tej samej nazwie i będą ją śledzić.

Zamith
źródło
4
Dlaczego Git może wywnioskować, originkiedy działa git push -udla nowo utworzonego oddziału w nowo utworzonym repozytorium? Czy założenie, że repozytorium zostało sklonowane, tak że bieżąca gałąź ma swój zdalny zestaw origin?
Piotr Dobrogost
73
To powinno być domyślne. Tak wiele rzeczy w git może być bardziej przyjaznych dla użytkownika, jeśli jest dostarczany z lepszymi ustawieniami domyślnymi.
phreakhead
13
Pamiętaj, że „prąd” jest nieco mniej bezpieczny niż używanie „prostego” do robienia tego samego, zobacz stackoverflow.com/questions/23918062/…
Air
30
Tak, ale kiedy spróbujesz pull, musisz określić, skąd. W -ukonfiguruje śledzenie gałęzi między pochodzenia i lokalnego repo.
Zamith
7
Chociaż jest to marginalnie wygodne, wciąż wymaga to uruchomienia innego polecenia dla pierwszego i jedynego push- co pokonuje cały sens tego pytania. Krótko mówiąc, nie ma dobrej odpowiedzi. To, że programiści Git nalegają na zachowanie tego niezręcznego użytkownika eXperience (AUX) w obliczu powszechnego sprzeciwu społeczności, jest ... pouczające. I zniechęcające. (Przeważnie zniechęcające.)
Cecil Curry
87

Możesz po prostu

git checkout -b my-branch origin/whatever

na pierwszym miejscu. Jeśli ustawisz branch.autosetupmergelub branch.autosetuprebase(moje ulubione) na always(domyślnie jest true), my-branchbędzie automatycznie śledzić origin/whatever.

Zobaczyć git help config.

cdunn2001
źródło
5
Powoduje to „błąd krytyczny: nie można zaktualizować ścieżek i jednocześnie przejść do gałęzi„ moja gałąź ”.
Karl the Pagan
12
Nawiasem mówiąc, zwykle po prostu git checkout -t origin/whatever, który wybiera również whateverjako nową nazwę oddziału. Bardzo wygodne!
cdunn2001
2
@cdunn Ten jest idealny, ale prawie niespójny. Flaga powinna się nazywać -u/ --set-upstream.
Tobu,
1
git checkout -t origin/whatevernie działa dla mnie, gdy próbuję utworzyć nowy oddział:fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
1
git checkout -b my-branch origin/whateverma również ten sam błąd (próbuję utworzyć nowy oddział, który nie istnieje na lokalnym lub zdalnym): fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky
81

Możesz ustawić upstream prościej na dwa sposoby. Najpierw podczas tworzenia oddziału:

git branch -u origin/my-branch

lub po utworzeniu oddziału możesz użyć tego polecenia.

git push -u origin my-branch

Możesz także rozgałęzić się, sprawdzić i skonfigurować w jednym poleceniu:

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

Osobiście wolę to zrobić w dwuetapowym poleceniu:

git checkout -b my-branch
git push -u origin my-branch
Tzen
źródło
1
Świetna odpowiedź! Rozwiązuje oba typowe przypadki użycia. Po uruchomieniu git branch -u origin/my-branchmogę uruchomić, git pullaby zapisać zmiany.
Benjamin Atkin
2
„git checkout -b my-branch -t origin / my-branch” to nie działa, jeśli „origin / my-branch” jeszcze nie istnieje.
Spongman
1
W rzeczywistości możesz po prostu git checkout -t origin/my-branchzrezygnować z -b my-branch, po prostu automatycznie wnioskuje my-brancho nazwę lokalnego oddziału. Jednak, jak wspomniano @Spongman, to polecenie nie działa, jeśli origin/my-branchnie istnieje najpierw.
wisbucky
Tak, będzie działać @wisbucky, -t działa dobrze. Jednak osobiście, nawet dwa lata po napisaniu tej odpowiedzi, nadal wolę podział na dwie linie za pomocą check -b i push -u. Jest bardziej wyraźny i nie ma błędu przy kasie -b gdy nie mam pilota - co zdarza się dość często podczas eksperymentowania :)
Tzen
2
git push -u origin/my-branchzawodzi dla mnie z fatal: 'origin/my-branch' does not appear to be a git repository. Działa to:git push -u origin my-branch
kamieniarz
80

To moje najczęstsze zastosowanie w 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.
...

Również fajnie jest pisać przekleństwa w swoim terminalu.

Tamlyn
źródło
Musi to zostać przeniesione do systemu Windows (lub przynajmniej git-bash).
BrianHVB
1
Cóż, to małe odkrycie sprawiło, że mój dzień. dziękuję
Ivan Durst,
Wspaniałe narzędzie, dzięki!
Yurii
48

Możesz użyć:

git config --global branch.autosetupmerge zawsze

który połączy gałąź nadrzędną za każdym razem, gdy tworzysz lub kasujesz nową gałąź.

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

Działa to również w przypadku branch.autosetuprebase, gdy postępujesz zgodnie z procesem bardziej skoncentrowanym na bazowaniu, ale nie używaj tego, chyba że wiesz, co robisz, ponieważ spowoduje to zmianę domyślnego zachowania podczas ściągania, co może powodować dziwne wyniki.

Daniel
źródło
8
Nie działa, wciąż otrzymuję --set-upstreamwiadomość
Dorian
2
@Dorian, Musisz to ustawić przed utworzeniem oddziału. Zobacz stackoverflow.com/a/9753268/263998
cdunn2001
8
ale to nie ustawia gałęzi śledzenia jako zdalnej z tą samą gałęzią, ale bieżącej gałęzi lokalnej. więc kiedy ją wypchniesz, spróbujesz przełączyć na gałąź LOKALNĄ, którą byłeś przed utworzeniem nowej gałęzi.
Arnold Roa
1
To ma nawet dziwniejsze zachowanie niż domyślne. Jeśli opierasz pracę poza gałęzią, działa to naprawdę dziwnie.
Beefster
1
Uważaj z tym ustawieniem !! Po ustawieniu otrzymasz takie zachowanie. 1. Przełącz na master. 2. Uruchom git checkout -b new_branch. 3. Dodaj zatwierdzenie do tej gałęzi. 4 git push origin new_branch. To wypycha, które zatwierdzają do mastergałęzi na początku (zamiast do nowej gałęzi nazywa się new_branch).
stwr667,
38

Nawiasem mówiąc, skrót do wypychania bieżącej gałęzi do pilota o tej samej nazwie:

$ git push -u origin HEAD
djanowski
źródło
22

Osobiście używam tych następujących aliasów w bash

w pliku ~ / .gitconfig

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

oraz w pliku ~ / .bashrc lub ~ / .zshrc

alias gpo="git pushup"
alias gpof="gpo -f"
alias gf="git fetch"
alias gp="git pull"
Amrit Shrestha
źródło
1
Musiałem tylko zmienić .gitconfig, a potem mogłem użyć polecenia, git pushupktóre zawsze wypycha bieżącą gałąź do źródła. Zawsze mogę po prostu użyć git pushupzamiast git push👍
thespacecamel
18

Jeśli poniższe nie działa:

git config --global push.default current

Powinieneś także zaktualizować lokalną konfigurację swojego projektu, ponieważ jest to możliwe, że Twój projekt ma lokalne konfiguracje git:

git config --local push.default current
youngrrrr
źródło
2
Więcej wyjaśnień byłoby świetnych. Co robi pierwsza linia?
papillon
3
Ta odpowiedź jest prawidłowa. Wszyscy, którzy proponują pseudonimy, są głupimi obejściami. Inne uzasadniające zapamiętywanie długich sekwencji poleceń są pedantyczne.
MarkHu,
10

Możesz także wyraźnie powiedzieć git pull, którą gałąź zdalną należy pobrać (jak wspomniano w komunikacie o błędzie):

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

Bądź jednak ostrożny: jeśli jesteś w innej gałęzi i wykonujesz wyraźne ściąganie, ściągnięty refspec zostanie scalony w gałęzi, w której się znajdujesz!

mtbkrdave
źródło
10

Jeśli chodzi o to, co jest warte, jeśli próbujesz śledzić gałąź, która już istnieje na pilocie (np. Origin / somebranch), ale nie sprawdziłeś jej jeszcze lokalnie, możesz:

$ git checkout --track origin/somebranch

Uwaga: „-t” jest skróconą wersją opcji „--track”.

To ustanawia to samo skojarzenie od samego początku.

mattacular
źródło
5
Możesz po prostu przejść do kasy w oddziale. To git checkout somebranchjest równoważne.
Zamith
2
@Zamith Czy to nie działa tylko po wcześniejszym zadzwonieniu git fetch?
Walter Roman
1
Nie od razu, ale tak, musisz mieć odniesienie do tego oddziału w lokalnym repozytorium, co dzieje się za każdym razem, gdy dzwonisz git fetchlub git pull. Jednak nigdy nie uważałem tego za problem.
Zamith,
10
git branch --set-upstream-to=origin/master<branch_name>

źródło
9

Używam tego aliasu Git zamiast kopiować / wklejać sugestię z Git za każdym razem: https://gist.github.com/ekilah/88a880c84a50b73bd306

Źródło skopiowane poniżej (dodaj to do ~/.gitconfigpliku):

[alias]
  pushup = "!gitbranchname() { git symbolic-ref --short HEAD; }; gitpushupstream() { git push --set-upstream origin `gitbranchname`; }; gitpushupstream"
manroe
źródło
7

Możesz ustawić naprawdę dobry alias, który poradzi sobie z tym bez nadmiernie pełnej składni.

Mam następujący alias w ~/.gitconfig:

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

Po zatwierdzeniu nowego oddziału możesz wypchnąć nowy oddział, po prostu wpisując polecenie:

git po
123
źródło
dlaczego po? push origin? co się stanie, jeśli zostanie uruchomione wiele razy?
Arnold Roa,
Tak, jak w przypadku wypychania. Nic się nie dzieje, jeśli jest uruchamiane wiele razy. Mam również git push -fskonfigurowany alias git pf, więc używam go, gdy źródło zostało już wypchnięte.
123
patrz komentarz djanowskiego , możesz bezpośrednio użyćHEAD
arhak 10.10.17
3

Dla tych, którzy szukają działającego aliasu, git pullużywam tego:

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

Teraz, gdy otrzymasz:

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

Po prostu biegnij:

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

I możesz już iść

jchavannes
źródło
2

Ponieważ git ma fajną zdolność do wypychania / ciągnięcia różnych gałęzi do różnych repozytoriów „upstream”. Możesz nawet użyć osobnych repozytoriów do pchania i ciągnięcia - na tej samej gałęzi. Może to stworzyć rozproszony, wielopoziomowy przepływ. Widzę, że jest to przydatne w projektach takich jak jądro Linuksa. Git został pierwotnie zbudowany do użytku w tym projekcie.

W rezultacie nie zakłada się, które repo powinno śledzić Twoja gałąź.

Z drugiej strony większość ludzi nie korzysta z git w ten sposób, więc może to stanowić uzasadnienie dla opcji domyślnej.

Git jest ogólnie dość niski i może być frustrujący. Istnieją jednak GUI i pisanie skryptów pomocniczych powinno być łatwe, jeśli nadal chcesz korzystać z powłoki.

Rolf
źródło
2

Możesz też zrobić git push -u origin $(current_branch)

ourmaninamsterdam
źródło
0

Ponownie odkryłem legit powodu tego problemu (tylko OS X). Teraz podczas rozgałęziania używam tylko tych dwóch poleceń:

legit publish [<branch>] Publikuje określoną gałąź do zdalnego. (Alias:pub )

legit unpublish <branch> Usuwa określoną gałąź ze zdalnego. (ps: unp)

SublimeGit jest domyślnie wyposażony w legitobsługę, która sprawia, że ​​cała procedura rozgałęziania jest tak prosta, jak naciśnięcie Ctrl-b.

Benny K.
źródło
0

Używamy fabrykatora i nie używamy git. Musiałem stworzyć alias bash, który działa na Linux / Mac

vim ~/.bash_aliases

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

zapisać

source ~/.bash_aliases
new_branch test #instead of git checkout -b test
git pull
om471987
źródło
0

Oto alias bash dla git push, który można bezpiecznie uruchamiać dla każdego pusha i automatycznie przełącza się między ustawieniem w górę dla pierwszego pusha, a następnie wykonywaniem normalnych pushów po tym.

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

Oryginalny post

Loren
źródło