Как настроить git push для автоматической настройки восходящего потока без -u?

105

Я хочу git push originавтоматически устанавливать ссылку на восходящий поток, когда я впервые нажимаю локально созданную ветку.

Я знаю об этом git push -u, но я не хочу думать о том, использовал ли я -uраньше или иным образом устанавливал ссылку на восходящий поток. Другими словами, я хочу, git pushчтобы автоматически выполнялся эффект при git push -uлюбом нажатии ветки, которая еще не имеет восходящего потока.

Это возможно? Если для этого требуется псевдоним или служебный сценарий, ничего страшного.

Джон
источник
2
Вы проверили, можно ли использовать параметры push.defaultи branch.<name>.mergeв git-config (1) ?
5
Я push.defaultустановил current- вот как я могу просто сказать git push originбез ссылки или апстрима. Но это не помогает с автоматической настройкой восходящего потока.
Джон

Ответы:

66

Вы можете настроить его с git configпомощью git config --global push.default current.

Документы: https://git-scm.com/docs/git-config/#Documentation/git-config.txt-pushdefault

Андреа Бергонцо
источник
9
У меня есть этот набор - вот как я могу просто сказать git push originбез refspec или апстрима. Но это не помогает с автоматической настройкой восходящего потока.
Джон
У меня работает: +1:
Тим Стрейдхорст
1
Да, как говорит @John, важно помнить, что это не заставляет локальную ветку отслеживать удаленную; он просто создает удаленную ветку с тем же именем, что и локальная.
waldyrious
Достаточно хорошо, если вам просто нужно push, например, только один разработчик в своей ветке, который редактирует только одну копию репо.
superarts.org
29

Поскольку я не думаю, что это возможно с помощью git config, вот что вы можете сделать в bash:

[[ $(git config "branch.$(git rev-parse --abbrev-ref HEAD).merge") = '' ]] && git push -u || git push

Если текущая ветвь имеет ветку удаленного отслеживания, она вызывает, git pushиначе вызывает git push -u

механическая рыба
источник
24
Теперь вы можете это сделать git config --global push.default current.
Андреа Бергонцо
2
@AndreaBergonzo, это единственный хороший ответ для меня, не могли бы вы добавить его в качестве ответа?
pdem
8
@AndreaBergonzo, @pdem - обратите внимание, что push.default=currentтолько создает ветку в удаленном репозитории с тем же именем, что и локальная ветка, но не устанавливает локальную ветку для отслеживания удаленной. Я не уверен, почему это так, но об этом стоит помнить.
waldyrious
23

Примечание: тот факт, что новая политика push по умолчанию " simple" полагается на ветку, имеющую восходящую, означает, что:
установка восходящей ветки рассматривается как добровольный шаг, а не скрытый автоматизированный

Когда " git push [$there]" не говорит, что отправлять, мы до сих пор использовали традиционную семантику "сопоставления" (все ваши ветки были отправлены на удаленный компьютер, если там уже есть ветки с таким же именем).

Мы будем использовать " simple" семантику, которая подталкивает текущую ветвь к ветке с тем же именем, только если текущая ветка настроена на интеграцию с этой удаленной веткой .
Это можно push.defaultизменить с помощью переменной конфигурации предпочтений пользователя " ".


Так построения из mechanicalfish «s ответа , вы можете определить псевдоним, с правом двойных кавычек ( ") экранированы ( \"):

git config alias.pu "![[ $(git config \"branch.$(git rev-parse --abbrev-ref HEAD).merge\") = '' ]] && git push -u || git push"

git pu origin

Sc0ttyD предлагает в комментариях следующий псевдоним:

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

В нескольких строках:

alias gpu='[[ -z $(git config "branch.$(git symbolic-ref --short HEAD).merge") ]] && 
           git push -u origin $(git symbolic-ref --short HEAD) || 
           git push'
VonC
источник
1
Спасибо, что показали, как настроить псевдоним. Я не совсем понимаю связь или актуальность первой части вашего ответа.
Джон
2
@John, моя точка зрения: вы обойдете шаг, который должен быть преднамеренным. Вы можете настроить этот псевдоним, но я хотел объяснить другим читателям, почему существует эта явная -uопция и почему нет конфигурации для автоматической настройки указанной опции (отсюда и псевдоним).
VonC
2
У меня есть список псевдонимов zsh в моем .zshrc. Я изменил этот ответ, чтобы создать следующий псевдоним zsh:alias gpu='[[ -z $(git config "branch.$(git symbolic-ref --short HEAD).merge") ]] && git push -u origin $(git symbolic-ref --short HEAD) || git push'
Sc0ttyD,
2
@ Sc0ttyD Интересно, спасибо. Я включил ваш комментарий в ответ для большей наглядности.
VonC
20

У меня была такая же проблема. Я нашел этот псевдоним (.gitconfig)

[alias] track = "!git branch --set-upstream-to=origin/`git symbolic-ref --short HEAD`"

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

Frexuz
источник
15

Ответы @VonC и @Frexuz полезны, но оба их решения вызывают для меня ошибку. Используя оба их ответа, я сколотил то, что мне подходит:

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

Это приводит к выполнению либо, git push -u origin $BRANCHNAMEлибо git push, в зависимости от того, определено ли его восходящее (свойство branch.$BRANCHNAME.merge).

Для ввода этого псевдонима в командной строке потребуются escape-коды, поэтому, вероятно, проще всего использовать редактор для вставки в правильный файл ( $HOME/.gitconfig(глобальный), .git/config(локальный) или /etc/gitconfig(системный))

отметка
источник
3
Это наиболее простой и полный ответ. Чтобы открыть редактор по умолчанию, не git config --global -e
Адам Толли
5

Я решил эту проблему с помощью этого простого скрипта Bash. Это не будет работать с существующими ветками, но если вы создадите все свои ветки с помощью этой функции, у вас всегда будет автоматически устанавливаться исходная ветка.

function con { git checkout -b $1 && git push --set-upstream origin $1; }

$ 1 представляет собой первый аргумент, который вы передаете после, conтак что это примерно так:

git checkout -b my-new-branch && git push -u my-new-branch

... просто сделав это:

con my-new-branch
JT Jobe
источник
5

Короткий ответ

Если вы действительно хотите быть явным и использовать эту -uопцию при необходимости, но просто не хотите вводить все:

git push -u origin foo

Затем вы можете использовать следующий псевдоним:

[alias]
    push-u = !git push -u origin $(git symbolic-ref --short HEAD)

И просто введите:

git push-u

Длинный ответ

Обычно потребность в -u(сокращении для --set-upstream) возникает тогда, когда мы только что создали новую локальную ветвь и зафиксировали, и мы хотим отправить ее вверх по течению. В удаленном репозитории еще нет новой ветки, поэтому нам нужно указать git, что нужно создать и отслеживать удаленную ветку, прежде чем отправлять фиксацию. Это необходимо только для первого нажатия на ветку. Вот типичный сценарий:

git checkout -b foo         # Create local branch
git commit -m "Foo"         # Create local commit
git push -u origin foo      # Create and track remote branch, and push commit
git commit -m "Bar"         # Create local commit
git push                    # Push commit

Лично мне нравится необходимость явного указания git push -uпри создании удаленной ветки: это довольно важная операция - предоставить миру совершенно новую ветку.

Однако я ненавижу то, что мы должны явно писать git push -u origin foo. Мало того, что печатать это сложно, но, что более важно, это довольно чревато ошибками! При вводе имени ветки легко ошибиться, и новая удаленная ветка не будет иметь то же имя, что и ваша локальная ветка! В большинстве случаев вы действительно хотите, чтобы исходный репозиторий был origin, а восходящая ветка имела то же имя, что и ваша локальная ветка.

Поэтому я использую следующий псевдоним в моем .gitconfig, который является подмножеством отличного ответа, предоставленного Марком :

[alias]
    push-u = !git push -u origin $(git symbolic-ref --short HEAD)

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

git checkout -b foo         # Create local branch
git commit -m "Foo"         # Create local commit
git push-u                  # Create and track remote branch, and push commit
git commit -m "Bar"         # Create local commit
git push                    # Push commit
Борис Дальштейн
источник
3

Просто:

$ alias gush="git push -u origin HEAD"
Джановский
источник
2
Заголовок вопроса: «Как настроить git push для автоматической установки восходящего потока без -u?» Описание: «Знаю git push -u, но ...». Так что это не ответ на вопрос.
Джон
2
@John Я обновил свой ответ, чтобы предложить простой псевдоним.
djanowski
2
@John А теперь ответ на вопрос?
djanowski
1
@ ILI4SK4RIM Спасибо, это безумие, что мой ответ самый простой, но он -1 ¯_ (ツ) _ / ¯
djanowski
2

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

$ git push -u o tab H tab

и автозаполнение даст вам $ git push -u origin HEAD

Чтобы включить autocomplate на OSX создать ~/.git-completition.bashфайл с таким содержимым и добавьте следующие строки в ~/.bash_profileфайл и перезапустите ваш терминал:

# git branch autocomplete
if [ -f ~/.git-completion.bash ]; then
  . ~/.git-completion.bash
fi
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Это влияет и на встроенные терминалы, например, в vscode и т. Д.

газдагерго
источник
1
автозаполнение? git не имеет автозаполнения. В вашей оболочке (bash? Zsh?) Загружен набор правил автозаполнения. Можете ли вы предоставить информацию о том, какой набор правил автозаполнения вы используете и где их взять?
vy32
О, на самом деле спасибо. Я завершил свой ответ с настройками автозаполнения.
gazdagergo
Не зная содержимого вашего файла ~ / .git-Completion.bash, ваш ответ не может быть реализован.
vy32
1
Хорошая точка зрения. Я нашел источник своего git-completition.bashи добавил к своему ответу.
gazdagergo
0

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

gitpush()
{
    git push -v 2>&1 | # perform push command, pipe all output
    tee /dev/tty | # keep output on screen and pipe it forward
    (
     cmd=$(sed -n "s/^.*\(git push --set-upstream origin .*\)$/\1/p");
     [[ -n "${cmd// }" ]] && (echo "> $cmd"; eval $cmd);
    ) # if we get output that matches the command to perform, execute it
}

Вы пожертвуете частью вывода push, но в остальном все работает так, как ожидалось.

Лично я буду использовать ответ JT Jobe .

iamfrank
источник