push --force-with-lease по умолчанию

130

Я только что узнал о git push --force-with-lease . Это довольно круто. Но, конечно, я не так часто использую силу, и поэтому я беспокоюсь, что могу забыть об этой замечательной функции, когда она мне понадобится в следующий раз.

Есть ли способ настроить git, который git push -fбудет использоваться автоматически, --force-with-leaseесли я намеренно не переопределю его с помощью--no-force-with-lease ?

(Я не могу представить, что когда-нибудь захочу применить силу без аренды!)

Дан Фабулич
источник

Ответы:

141

AFAIK нет конфигурации, чтобы указать git всегда использовать force-with-leaseвместо force. Кажется, это хороший пример запроса функции; если у вас нет проблем с погружением в базу кода git, вы можете реализовать ее самостоятельно и отправить на проверку.

ИЗМЕНИТЬ В нынешнем виде это все еще актуально в апреле 2019 года.

До тех пор единственный вариант, который я вижу, - как это часто бывает, - создать alias который служит этой цели.

Создать псевдоним

Чтобы создать псевдоним git config --global alias.<alias-name> <command>, в нашем случае я бы предложил нечто подобное.

git config --global alias.pushf "push --force-with-lease"

Это создаст запись в вашем глобальном .gitconfigфайле (который обычно находится в вашем домашнем каталоге ). После этого вы можете просто использовать git pushfдля принудительной аренды .

Запачкать руки

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

Вы можете найти все эти и другие ссылки на официальной странице сообщества .

Саша Волк
источник
25
Замечание о том, что это не особенность: общий аргумент против переписывания стандартных команд («push --force») состоит в том, что вы привыкаете к ним, забываете их происхождение и однажды случайно используете их таким образом в новой системе. Многое , как сглаживание , rmчтобы rm -iв вашем .bashrc; однажды вы забудете и удалите важный файл на сервере.
Использование
2
Личный анекдот / предостережение: я пробовал использовать псевдоним, pushfно всегда дважды проверял, что я не выполняю push -f, из-за того, что он похож на псевдоним. Некоторые члены команды все push -fравно использовали , думая, что псевдоним был просто косметическим сокращением для него. В конце концов, мы заменили более безопасную форму псевдонимом pushflи перестали об этом беспокоиться.
кельвин
31

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

Git 2.13 (второй квартал 2017 г.) объясняет, почему нет «защиты» от того, чтобы этот параметр push был забыт, потому что даже если вы не забудете его на git pushуровне, его все равно можно будет проигнорировать.

См. Коммит f17d642 (19 апреля 2017 г.), сделанный var Arnfjör Bjarmason ( avar) .
(Объединено Junio ​​C Hamano - gitster- в коммите 46bdfa3 , 26 апреля 2017 г.)

push: документ и тест --force-with-lease с несколькими пультами

Документируйте и тестируйте случаи, когда два пульта дистанционного управления указывают на один и тот же URL-адрес, а фоновая выборка и последующие git push --force-with-leaseне должны затирать необновленные ссылки, которые мы не получили.

Некоторые редакторы, такие как Microsoft VSC, имеют функцию автоматической загрузки в фоновом режиме, это позволяет обойти защиту, предлагаемую --force-with-lease&--force-with-lease=<refname> , как указано в добавляемой здесь документации.

Итак, документация наgit push данный момент включает:

Общее замечание по безопасности: предоставление этой опции без ожидаемого значения, т.е. как --force-with-leaseили --force-with-lease=<refname> очень плохо взаимодействует с чем-либо, что неявно запускается git fetchна удаленном компьютере, чтобы быть отправленным в фоновом режиме, например, git fetch origin в ваш репозиторий в cronjob.

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

Если ваш редактор или какая-либо другая система работает git fetchв фоновом режиме, для вас способ смягчить это просто настроить другой пульт:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

Теперь, когда фоновый процесс запускается, git fetch originссылки на origin-pushне будут обновляться, и, таким образом, такие команды, как:

git push --force-with-lease origin-push

Сбой, если вы не запустите вручную git fetch origin-push.
Этот метод, конечно, полностью побежден чем-то, что работает git fetch --all, в этом случае вам нужно будет либо отключить его, либо сделать что-то более утомительное, например:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

Т.е. создайте baseтег для версий вышестоящего кода, которые вы видели и готовы перезаписать, затем переписать историю и, наконец, принудительно принудительно изменить изменения, masterесли удаленная версия все еще работает base, независимо от того, какая локальная версия remotes/origin/masterбыла обновлена ​​в задний план.

VonC
источник
30

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

Всякий раз, когда я пытаюсь это сделать git push -f, я вижу следующее:

⚡ git push -f
use this instead so you don't cause race conditions in the 
repo: git push --force-with-lease

Некоторые преимущества этого скрипта:

  • он приучает меня к привычному использованию --force-with-lease, поэтому меня не волнуют, когда я ошибаюсь
  • если по какой-то причине нам действительно нужно принудительно нажимать, git push --force будет работать.

Как это реализовать:

  1. создать собственный скрипт, который будет передавать любые параметры в git, кроме -f
  2. псевдоним этого скрипта, поэтому мы используем его вместо git

Эти инструкции предполагают, что Linux или Mac работает под управлением bash. Я не пробовал это с zsh или Windows, но полагаю, что там тоже будет работать.

~/.bash_profile:

alias git=~/.git_wrapper.sh

~./git_wrapper.sh:

#!/bin/bash
for arg in "$@"; do
    if [ "$arg" = "push" ]; then
        ispush=1
    elif [ "$ispush" = 1 -a "$arg" = '-f' ]; then
        echo "use this instead so you don't cause race conflicts in the repo: git push --force-with-lease"
        exit 1
    fi
done

git "$@"

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

Джессика Найт
источник
17
Это кажется удобным. +1. Может быть, заменить «эй идиот» на «эй, ты нежная, но простая душа» или что-то в этом роде;)
VonC
5

Для людей, использующих OMYZSH, вы можете просто использовать ggfl.

никола
источник
3

Я хочу напомнить , что я не должен использовать -f, но я не хочу вводить в заблуждение , полагая , что -fсредства --force-with-lease. Итак, это мое мнение:

git() {
  if [[ $@ == 'push -f'* ]]; then
    echo Hey stupid, use --force-with-lease instead
  else
    command git "$@"
  fi
}

Добавьте в свой .bash_profile, .bashrcили .zshrc.

neu242
источник
1

Вы можете создать функцию bash, которая заменяет gitи использует --force-with-leaseвместо--force

# replaces `git push --force` with `git push --force-with-lease`
git() {
  if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then
    command git push --force-with-lease
  else
    command git "$@"
  fi
}

или в одной строке:

git() { if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then command git push --force-with-lease; else command git "$@"; fi; }

Просто добавьте его в свой ~/.bashrcили ~/.zshrc.

paulodiovani
источник