Зачем мне все время делать `--set-upstream`?


1469

Я создаю новую ветку в Git:

git branch my_branch

Нажмите это:

git push origin my_branch

Теперь скажите, что кто-то сделал некоторые изменения на сервере, и я хочу вытащить origin/my_branch. Я делаю:

git pull

Но я получаю:

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.

Я узнал, что могу заставить его работать с:

git branch --set-upstream my_branch origin/my_branch

Но зачем мне это делать для каждой создаваемой мной ветки? Разве не очевидно , что если я нажимаю my_branchна origin/my_branch, то я хотел бы, чтобы тянуть origin/my_branchв my_branch? Как я могу сделать это поведение по умолчанию?


21
Значение по умолчанию для branch.autosetupmergeозначает, что восходящая конфигурация для новой ветви устанавливается только автоматически при создании ветви из ветви удаленного отслеживания (например <remote-name>/<branch-name>) (см. Git-config (1) ). Вы, вероятно, создаете свои филиалы из существующих локальных филиалов. Если вы эффективно разветвляетесь прямо из кончика удаленной ветки (несмотря на то, что находитесь в локальной ветке), то вы можете использовать git branch my_branch <remote-name>/<branch-name>для автоматической настройки исходной конфигурации.
Крис Джонсен

20
К вашему сведению, этот --set-upstreamвариант устарел. Вы должны использовать --trackили --set-upstream-toвместо.
Шон Боб

139
если --set-upstreamэто устарело, то, возможно, разработчики git должны удалить его из справочного сообщения, которое отображается, когда вы запускаете git pushбез параметров и не установлен апстрим?
Кристофер Хантер

17
@ChristopherHunter Прошло больше года с момента вашего комментария, и он все еще говорит это. Это просто неаккуратная обратная связь или, может быть, есть технически мудрая причина, чтобы держать это, о чем мы не знаем?
Конрад Вилтерстен

15
@ChristopherHunter git branch --set-upstreamустарела. git push --set-upstreamне является.
Брайан Гордон

Ответы:


1538

Ярлык, который не зависит от запоминания синтаксиса для git branch --set-upstream 1 , должен сделать:

git push -u origin my_branch

... в первый раз, когда вы нажимаете эту ветку. Или, чтобы перейти к текущей ветви к ветви с тем же именем (удобно для псевдонима):

git push -u origin HEAD

Вам нужно использовать -uтолько один раз, и это устанавливает связь между вашей веткой и филиалом так originже, как это git branch --set-upstreamделается.

Лично я думаю, что было бы хорошо установить эту связь между вашей веткой и одной удаленно. Обидно, что правила для git pushи разныеgit pull .


1 Это может звучать глупо, но я очень часто забываю указывать текущую ветку, предполагая, что это по умолчанию - это не так, и результаты являются наиболее запутанными :)

Обновление 2012-10-11 : Видимо, я не единственный, кому легко ошибиться! Спасибо VonC за указание, что git 1.8.0 представляет более очевидное git branch --set-upstream-to, что может быть использовано следующим образом, если вы находитесь на ветке my_branch:

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

... или с короткой опцией:

git branch -u origin/my_branch

Это изменение и его обоснование описаны в примечаниях к выпуску git 1.8.0, кандидат на выпуск 1 :

Было заманчиво сказать git branch --set-upstream origin/master, но это говорит Git организовать локальную ветвь origin/masterдля интеграции с текущей проверенной ветвью, что весьма маловероятно для того, что имел в виду пользователь. Опция устарела; используйте вместо этого новую --set-upstream-to(с короткой и сладкой -u) опцию.


95
Также обратите внимание, что даже если вы забудете при -uпервом нажатии, вы можете снова запустить push с этим флагом, и он начнет отслеживание.
Хенрик Н

70
Ни один из них не удовлетворяет сценарию использования git push без аргументов. Остается, что мне все еще нужно помнить «git push -u origin my-branch» при первом перемещении моей новой ветки на удаленный.
Карл Язычник,

19
Я тоже ненавижу вспоминать этот синтаксис, поэтому я создал следующий псевдоним:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
lillialexis

99
Это все хорошо, но я все еще думаю, что жалоба ФП действительна. Вы запускаете локальную ветку, работаете над ней, отправляете ее в источник, чтобы поделиться (без аргументов); почему это не должно установить вверх по течению? По какой-то причине желательно НЕ устанавливать восходящий поток при отправке новой ветви на удаленный компьютер?
GaryO

23
Совершенно не стоит тратить время на разработку. Почему он просто не делает это автоматически?
Судо

1347

Вы можете сделать это с меньшим количеством печати. Во-первых, измените способ работы push:

git config --global push.default current

Это будет выводить origin my_branchчасть, таким образом, вы можете сделать:

git push -u

Который будет создавать удаленную ветку с тем же именем и отслеживать ее.


4
Почему Git Infer может originработать git push -uдля вновь созданной ветви во вновь созданном репозитории? Предполагается ли, что репозиторий был клонирован, поэтому текущая ветвь имеет свой удаленный набор origin?
Петр Доброгост

74
Это должно быть по умолчанию. Так много вещей в git могут быть более удобными для пользователя, если он просто поставляется с лучшими настройками по умолчанию.
phreakhead

13
Помните, что «current» немного небезопаснее, чем «простой», чтобы сделать то же самое, см. Stackoverflow.com/questions/23918062/…
Air

30
Это так, но затем, когда вы попытаетесь, pullвам придется указать, откуда. В -uустанавливает отслеживание ветви между происхождением и вашим местными репо.
Замит

7
Хотя это и немного удобно, это все же требует, чтобы для первого и единственного запускалась другая команда, pushчто лишает смысла весь этот вопрос. Короче говоря, нет хорошего ответа. То, что разработчики Git настаивают на сохранении этого опыта Awkward User eXperience (AUX) перед лицом инакомыслия широко распространенного сообщества, ... поучительно. И обескураживает. (Главным образом обескураживающий.)
Сесил Карри

87

Вы можете просто

git checkout -b my-branch origin/whatever

на первом месте. Если вы установите branch.autosetupmergeили branch.autosetuprebase(мой любимый) в always(по умолчанию true), my-branchбудет автоматически отслеживать origin/whatever.

См git help config.


5
Это приводит к «фатальному: невозможно обновить пути и переключиться на ветку« my-branch »одновременно».
Карл Язычник

12
Кстати, я обычно просто git checkout -t origin/whatever, который также выбирает whateverв качестве нового филиала имя. Очень удобно!
cdunn2001

2
@cdunn Этот идеал, но вряд ли соответствует. Флаг должен называться -u/ --set-upstream.
Тобу

1
git checkout -t origin/whateverу меня не работает при попытке создать новую ветку:fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky

1
git checkout -b my-branch origin/whateverтакже имеет ту же ошибку (я пытаюсь создать новую ветку, которая не существует на локальном или удаленном): fatal: Cannot update paths and switch to branch 'whatever' at the same time.
wisbucky

81

Это мое самое распространенное использование для 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.
...

Кроме того, весело вводить ругательства в вашем терминале.


Это необходимо перенести на Windows (или хотя бы git-bash).
BrianHVB

1
хорошо, это маленькое открытие только что сделало мой день. спасибо
Иван Дерст

Великолепный инструмент, спасибо!
Юрий

81

Вы можете настроить upstream проще двумя способами. Сначала при создании ветки:

git branch -u origin/my-branch

или после того, как вы создали ветку, вы можете использовать эту команду.

git push -u origin my-branch

Вы также можете разветвляться, проверять и устанавливать upstream с помощью одной команды:

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

Лично я предпочитаю делать это в два этапа:

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

1
Отличный ответ! Адреса обоих распространенных случаев использования. После бега git branch -u origin/my-branchя могу бежать, git pullчтобы сбросить свои изменения.
Бенджамин Аткин

2
"git checkout -b my-branch -t origin / my-branch" это не работает, если 'origin / my-branch' еще не существует.
Спонгман

1
Вы на самом деле можете просто обойтись git checkout -t origin/my-branchбез -b my-branch, он просто автоматически выведет my-branchимя локальной ветви. Однако, как упомянул @Spongman, эта команда не работает, если origin/my-branchона не существует первой.
wisbucky

Да, будет работать @wisbucky, -t работает просто отлично. Что касается меня, то даже через два года после того, как я написал этот ответ, я все же предпочитаю разбивать его на две строки с помощью checkout -b и push -u. Это более явно, и нет ошибки при оформлении заказа -b, когда у меня нет пульта дистанционного управления - что случается довольно часто при экспериментировании :)
Tzen

2
git push -u origin/my-branchтерпит неудачу для меня с fatal: 'origin/my-branch' does not appear to be a git repository. Это работает:git push -u origin my-branch
Stason

48

Ты можешь использовать:

git config --global branch.autosetupmerge всегда

которая будет связывать ветку upstream каждый раз, когда вы создаете или извлекаете новую ветку.

См. Https://felipec.wordpress.com/2013/09/01/advanced-git-concepts-the-upstream-tracking-branch/

Это также работает branch.autosetuprebase, если вы следуете более ориентированному на перебазирование рабочему процессу, но не используете его, если не знаете, что делаете, поскольку по умолчанию ваше поведение извлечения перебазируется, что может привести к странным результатам.


8
Не работает, я все еще получаю --set-upstreamсообщение
Дориан

2
@Dorian, вы должны установить это, прежде чем создавать ветку. См stackoverflow.com/a/9753268/263998
cdunn2001

8
но это не устанавливает отслеживающую ветвь как удаленную с той же ветвью, но с текущей локальной ветвью .. поэтому, когда вы делаете push, она будет пытаться переместиться в локальную ветвь, которой вы были до создания новой ветви ..
Арнольд Роа

1
Это даже страннее, чем по умолчанию. Если вы основываете работу на ветке, она действует очень странно.
Бифстер

1
Будьте осторожны с этой настройкой! После установки вы получаете это поведение. 1. Переключитесь на master. 2. Беги git checkout -b new_branch. 3. Добавьте коммит в эту ветку. 4 git push origin new_branch.. Это подталкивает коммит к masterветви на источнике (а не к новой ветке с именем origin new_branch).
stwr667

38

Кстати, ярлык для отправки текущей ветки на удаленный компьютер с таким же именем:

$ git push -u origin HEAD

22

Я лично использую следующие псевдонимы в Bash

в файле ~ / .gitconfig

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

и в файле ~ / .bashrc или ~ / .zshrc

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

1
Мне нужно было только hcange .gitconfig, тогда я мог использовать команду, git pushupкоторая всегда выталкивает текущую ветвь к источнику. Я всегда могу просто использовать git pushupвместо git push👍
thespacecamel

18

Если ниже не работает:

git config --global push.default current

Вам также следует обновить локальную конфигурацию вашего проекта, так как возможно ваш проект имеет локальные конфигурации git:

git config --local push.default current

2
Больше объяснений было бы здорово. Что делает первая строка?
Papillon

3
Этот ответ тот, который чувствует себя законным. Все, кто предлагает псевдонимы, являются тупыми обходными путями. А другие, оправдывающие запоминание длинных последовательностей команд, педантичны.
MarkHu

10

Вы также можете явно указать git pull, какую удаленную ветку извлекать (как это упоминается в сообщении об ошибке):

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

Однако будьте осторожны с этим: если вы находитесь в другой ветке и выполняете явное извлечение, ссылка, которую вы извлекаете, будет объединена с ветвью, в которой вы находитесь!


10

Для чего стоит, если вы пытаетесь отследить ветку, которая уже существует на удаленном компьютере (например, origin / somebranch), но еще не проверила ее локально, вы можете сделать:

$ git checkout --track origin/somebranch

Примечание: «-t» - это сокращенная версия опции «--track».

Это создает ту же ассоциацию сразу.


5
Вы можете просто оформить заказ в филиал. Так git checkout somebranchэквивалентно.
Замит

2
@ Zamith Разве это не работает только после того, как позвонил git fetchсразу?
Вальтер Роман,

1
Не сразу, но да, вам нужно иметь ссылку на эту ветку в вашем локальном репо, что происходит всякий раз, когда вы звоните git fetchили git pull. Я никогда не считал это проблемой.
Zamith

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

9

Я использую этот псевдоним Git вместо копирования / вставки предложения из Git каждый раз: https://gist.github.com/ekilah/88a880c84a50b73bd306

Источник скопирован ниже (добавьте это в ваш ~/.gitconfigфайл):

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

7

Вы можете установить действительно хороший псевдоним, который может справиться с этим без слишком подробного синтаксиса.

У меня есть следующий псевдоним в ~/.gitconfig:

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

Сделав коммит в новой ветке, вы можете нажать новую ветку, просто набрав команду:

git po

почему po? push origin? что произойдет, если это выполняется несколько раз?
Арнольд Роа

Да, как в толковом происхождении. Ничего не происходит, если он запускается несколько раз. У меня также есть git push -fпсевдоним git pf, так что я использую его, как только источник уже выдвинут.
123

см . комментарий Джановски , вы можете использовать напрямуюHEAD
архак

3

Для тех, кто ищет псевдоним, с которым git pullя работаю, вот что я использую:

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

Теперь, когда вы получаете:

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

Просто беги:

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

И ты хорош идти


2

Потому что git обладает отличной способностью вставлять / извлекать разные ветки в разные «исходящие» репозитории. Вы можете даже использовать отдельные репозитории для толкания и вытягивания - в одной и той же ветке. Это может создать распределенный многоуровневый поток, и я вижу, что это полезно в таких проектах, как ядро ​​Linux. Git был изначально построен для использования в этом проекте.

Как следствие, это не делает предположения о том, какое хранилище должно отслеживать ваше отделение.

С другой стороны, большинство людей не используют git таким образом, так что это может быть хорошим вариантом для варианта по умолчанию.

Git, как правило, довольно низкоуровневый, и это может разочаровать. Тем не менее, есть GUI, и должно быть легко писать вспомогательные скрипты, если вы все еще хотите использовать его из оболочки.



0

Я вроде заново обнаружил legitиз-за этой проблемы (только OS X). Теперь все, что я использую при ветвлении, это две команды:

legit publish [<branch>] Публикует указанную ветку на удаленной. (псевдоним: pub)

legit unpublish <branch> Удаляет указанную ветку с пульта. (псевдоним: unp)

SublimeGit поставляется с legitподдержкой по умолчанию, что делает всю процедуру ветвления такой же простой, как нажатие Ctrl-b.


0

Мы используем фабрикатор и не используем git. Мне пришлось создать псевдоним bash, который работает на Linux / Mac

vim ~/.bash_aliases

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

спасти

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

0

Вот псевдоним bash для git push, который безопасно запускать для каждого push и будет автоматически переключаться между настройкой upstream для первого push и затем выполнением обычных push после этого.

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

Оригинальный пост

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.