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?


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.


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ć.


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.


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

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.


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.


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

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"

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

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!


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.


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>

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"

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

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ść


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.



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.


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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.