Git --force-with-lease с + в филиале (refspec)
На текущем Git, есть ли существенная разница между git push --force-with-lease origin +somebranch
, git push --force-with-lease origin somebranch
а также git push origin +somebranch
(без плюса)? Все три, кажется, делают то же самое.
Я пытался искать документацию. Я пытался взглянуть на refspec в документации, но я не знаю, есть ли разница, и если да, то какой из них лучше выбрать по умолчанию, когда я хочу перейти на рабочую ветку через git pull --rebase origin master
, например.
2 ответа
Это хороший вопрос; документация немного двусмысленная, а источник очень запутанный (фактическое применение флагов силы разбросано).
Один ответ достаточно ясен. Вот что git push
Документация гласит, с моим жирным шрифтом добавлено:
--[no-]force-with-lease
--force-with-lease=<refname>
--force-with-lease=<refname>:<expect>
Обычно "git push" отказывается обновлять удаленную ссылку, которая не является предком локальной ссылки, используемой для ее перезаписи.
Эта опция отменяет это ограничение, если текущее значение удаленного ref является ожидаемым значением. иначе "git push" не работает.
Представьте, что вы должны перебазировать то, что уже опубликовали. Вам придется обойти правило "must fast-forward", чтобы заменить историю, которую вы первоначально опубликовали, перебазированной историей. Если во время перебазирования кто-то еще построил вашу исходную историю, верхушка ветки на пульте может продвинуться вперед с ее фиксацией, и слепое нажатие --force потеряет ее работу.
Эта опция позволяет вам сказать, что вы ожидаете, что обновляемая история - это то, что вы перебазировали и хотите заменить. Если удаленная ссылка все еще указывает на указанный вами коммит, вы можете быть уверены, что другие люди ничего не сделали с этой ссылкой. Это похоже на взятие "аренды" для ссылки без явной блокировки, и удаленная ссылка обновляется, только если "аренда" все еще действительна.
Один только -force-with-lease, без указания деталей, защитит все удаленные ссылки, которые будут обновлены, требуя, чтобы их текущее значение было таким же, как у ветви удаленного отслеживания, которую мы имеем для них.
--force-with-lease =
, без указания ожидаемого значения, защитит именованный ref (один), если он будет обновлен, требуя, чтобы его текущее значение было таким же, как в ветви удаленного отслеживания мы за это. --force-with-lease =
:<Ожидается> будет защищать именованный ref (один), если он будет обновлен, требуя, чтобы его текущее значение было таким же, как указанное значение (которое разрешено отличаться от ветки удаленного отслеживания, которую мы используем для refname, или у нас даже не должно быть такой ветки удаленного отслеживания, когда используется эта форма). Обратите внимание, что все формы, кроме --force-with-lease =
:<Ожидается>, которые явно указывают ожидаемое текущее значение ссылки, все еще являются экспериментальными, и их семантика может измениться, когда мы приобретем опыт работы с этой функцией. "--no-force-with-lease" отменит все предыдущие --force-with-lease в командной строке.
Следовательно, если опция1 сравнения и обмена поддерживается транспортом, и вы написали --force-with-lease
и не --no-force-with-lease
, то все обновления, принудительные или нет, используют режим аренды.
--no-force-with-lease
Однако очищает накопленный push_cas_option
структура, и это не сразу очевидно для меня, когда эти накопленные значения применяются к каждой refspec.
Использование явного <refname>
также четко защищает только одну ссылку, независимо от того, установлен ли для нее какой-либо флаг силы.
Что именно происходит в том случае, если базовому транспорту не хватает поддержки сравнения и обмена, мне тоже не ясно. К счастью, Git-серверы GitHub поддерживают его, что отвлекает внимание, если вы имеете в виду GitHub.
1 Внутренне исходный код Git использует макрос CAS_OPT_NAME
: функция force-with-lease основана на инструкциях современных процессоров сравнения и замены, которые атомарно проверяют, установлена ли некоторая переменная2 на прогнозируемое значение, заменяя ее новым значением, если таковое есть, и также возвращая в некоторая форма, фактическое значение, найденное в переменной.
Это может установить коды условий, если в архитектуре ЦП используются коды условий, но в большинстве, если не во всех случаях, вы получаете старое значение, чтобы при необходимости можно было повторить попытку сравнения и замены. Например, чтобы реализовать атомарный add-one, вы можете выполнить цикл: load r1,(r0); label: add r1,1,r2; cas r1,r2,(r0); bne label
; реализовать атомарный тест-и-набор бита 2: load r1,(r0); label: or r1,4,r2; cas r1,r2,(r0); bne label
; и так далее. Этот метод используется, например, в системах Intel Pentium и SPARC.
Некоторые процессоры используют механизм кэширования. Если кэш, ближайший к ЦП, имеет общие и эксклюзивные режимы (например, MESI или MOESI), мы можем использовать инструкцию "load connected" или "load locked", за которой следует команда "store conditional". Условное хранилище завершается успешно, только если строка кэша все еще принадлежит только текущему ЦП. В этом случае мы должны заново выполнить начальную блокированную загрузку переменной, и наши циклы будут выглядеть примерно так: label: ll r1,(r0); add 1,r1; sc (r0),r1; bne label
, Это используется в архитектурах PowerPC и MIPS.
2 Обычно рассматриваемая переменная представляет собой область памяти, часто с ограничениями выравнивания, даже на процессорах, которые номинально поддерживают невыровненную память. Например, в Intel Haswell инструкция сравнения и замены 8-байтовых будет выполняться до конца на 4-байтовой границе, но на самом деле она не будет атомарной. Я обнаружил, что это трудный путь, когда распределитель памяти коллеги обеспечивает только 4-байтовое выравнивание.:-)
который бы предпочел по умолчанию, когда мне нравится тянуть к работе через ветку
git pull --rebase origin master
?
Я сообщил о force-with-lease
в 2013 году для git 1.8.5 и в марте 2016 года для git 2.8".
Я бы сказал... ни один из них.pull --rebase
сделано для того, чтобы избежать необходимости толкать (с арендой или без нее) что-либо.
Я просто установил ( начиная с git 2.6)
git config pull.rebase true
git config rebase.autoStash true
Это позволяет мне сделать несколько простых git pull
с последующим простым git push
(без принудительного толчка)