git checkout -B без сброса или альтернатив? - PullRequest
1 голос
/ 11 апреля 2019

Я хочу использовать команду, которая будет:

  1. Создать новую ветвь, если она не существует.
  2. Оформить ветку, если она существует без каких-либо изменений в ней.

Используемое в настоящее время git checkout -B branchname нарушает второе требование, поскольку оно сбрасывает ветвь до HEAD начальной точки, если ветвь существует.Знаете ли вы какие-либо флаги для checkout / обходные пути / другие команды, которые будут удовлетворять обоим требованиям?

1 Ответ

2 голосов
/ 11 апреля 2019

Нет единственной команды Git, которая будет делать это.

Рекомендованная последовательность команд:

git checkout <name>

, затем , если не удалось:

git checkout -b <name> [<starting-point>]

или (в зависимости от того, какое поведение вы хотите):

git checkout [-b <name>] --track <remote-tracking-name>

, где каждый элемент в угловых скобках представляет что-то, что вы заменяете (например, <name> может быть feature/fast), а каждый элемент в квадратных скобках представляет собой что-то необязательное.

Основная проблема здесь такова:

  • Если вы создаете новое имя ветви , вы должны выбрать, какой коммит будет определять это новое имя ветви. Вы выбираете конкретную отправную точку, предоставляя аргумент <starting-point>; если вы не в состоянии назвать начальную точку, Git будет считать, что вы хотите HEAD в качестве начальной точки.

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

  • Если вы используете существующее имя ветки , вы - согласно вашему заявлению выше - не хотите изменять , который фиксирует его, будет идентифицировать. (В настоящее время у вас нет возможности установить / изменить восходящий канал для существующей ветви, так что конкретный вопрос выпадает из картинки.)

Давайте теперь затронем все побочные проблемы, которые здесь случаются.

С -b, git checkout всегда хочет создать новую ветку

Флаг -b и / или --track сообщает git checkout, что он должен создать новую ветвь и затем переключиться на нее. Если переключение произойдет или произойдет сбой, он должен откатить всю операцию и, в конце концов, не создавать новую ветвь. Так что здесь является отправной точкой. Начальная точка может быть HEAD. Поскольку ветвь new , она еще не имеет восходящего потока, но вы можете указать git checkout to set upstream, используя --track: аргумент --track равен имя восходящего потока (которое должно быть либо именем локальной ветви, либо именем удаленного отслеживания, таким как origin/master).

Если вы указываете флаг -b, вы также указываете имя новой ветви, и, следовательно, это имя новой ветви. Если вы опустите флаг -b, вы должны указать --track и имя удаленного отслеживания: в этом случае имя ветви - это имя, полученное в результате удаления части удаленного отслеживания, например, origin/feature становится feature, поэтому git checkout --track origin/feature означает то же самое, что и git checkout -b feature --track origin/feature.

Если вы указали отправную точку, Git должен будет проверить этот конкретный коммит. Имя начальной точки может быть именем удаленного отслеживания (например, origin/master или origin/feature), или идентификатором хэша коммита, или любым другим, идентифицирующим коммит. В большинстве случаев предоставление имени для удаленного отслеживания в качестве отправной точки эквивалентно предоставлению также аргумента --track, поэтому, если вы не хотите установить восходящий поток, добавьте --no-track. См. git checkout документацию для полного описания.

Без -b, git checkout все еще иногда создает новую ветвь

Когда вы пропустите -b, git checkout <em>name</em> будет сначала проверять, соответствует ли name какой-либо существующей ветви. Если это так, то часть операции декодирования завершена: теперь Git пытается проверить этот конкретный коммит (идентифицированный этой веткой) и, если это удается, присоединяет ваш HEAD к этой ветке, так что вы сейчас на ветке.

Но вы можете написать, например ::

git checkout feat/ure

когда у вас нет ветки с именем feat/ure. В этом случае Git перечислит все ваши имена для удаленного отслеживания, такие как origin/master, upstream/master и т. Д. Если точно один соответствует feat/ure после удаления удаленной части, Git предполагает, что вы имели в виду , чтобы написать:

git checkout --track origin/feat/ure

(или какое-либо другое имя с удаленным пультом).Следовательно, это создаст feat/ure, указывая на такой же коммит как origin/feat/ure, с origin/feat/ure в качестве настройки восходящего потока для новой ветви feat/ure.

Если feat/ure не существует и либо нет, либо слишком много (два или более) имен стилей удаленного слежения feat/ure - например, существуют и origin/feat/ure, и upstream/feat/ure - этот git checkout будет простопотерпите неудачу, и теперь вы должны прибегнуть к одному или нескольким из -b и / или --track.

Другая альтернатива

Если вам не нравятся эти альтернативы, это можно проверить, существует ли имя ветви.Для этого попросите git rev-parse перевести имя, вставив перед ним refs/heads/:

git rev-parse --quiet --verify refs/heads/feat/ure

Если это удастся, он напечатает хэш-идентификатор, к которому разрешается refs/heads/feat/ure, ивыходы с нулевым статусом.Напечатанный идентификатор хэша является кончиком ветви feat/ure, которая поэтому существует.Если это не удается, он ничего не печатает (--quiet --verify) и завершает работу с ненулевым статусом, поэтому feat/ure не существует.Теперь вы можете спокойно попросить создать feat/ure - то есть, при условии, что никто не проник в ваш репозиторий и не создал feat/ure, пока вы просматривали состояние выхода и определяли, что feat/ureне существует (но теперь существует).

В сценарии оболочки это становится:

name=feat/ure
git rev-parse --quiet --verify refs/heads/$name >/dev/null && exists=true || exists=false
if $exists; then git checkout $name; else git checkout -b $name ...additional arguments; fi

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

...