В git плохая идея создать тег с тем же именем, что и удаленная ветка?

20

У меня есть проект с моделью git-ветвления, который примерно соответствует модели gv-потока nvie .

Наши ветки релизов названы в формате SemVer , напримерv1.5.2

Как только ветвь релиза получает зеленый свет для производства, мы закрываем ветвь, объединяя ее с master, применяя тег, а затем удаляя ветку.

Поскольку мы немедленно удаляем ветку релиза, мы используем один и тот же идентификатор для маркировки ветки, например v1.5.2

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

$ git checkout master
$ git merge v1.5.2
$ git tag -a v1.5.2 -m "Version 1.5.2 - foo bar, baz, etc"
$ git branch -d v1.5.2
$ git branch -dr origin/v1.5.2
$ git push origin :v1.5.2
$ git push
$ git push --tags

Похоже, что это работает в большинстве случаев, однако это вызывает проблему в сценарии, когда другой экземпляр git-репо (например, другая машина разработки или промежуточная среда) имеет локальную проверку ветки v1.5.2.

Команда git push origin :v1.5.2удалит ветку на удаленном компьютере, но не удалит локальную версию ветки (если она существует) во всех репозиториях.

Это приводит к неоднозначной ссылке при попытке оформить заказ v1.5.2в этих репозиториях:

$ git checkout v1.5.2
warning: refname 'v1.5.2' is ambiguous.

Можно ли этого избежать без использования другого синтаксиса для ветвей, например release-v1.5.2, или v1.5.2-rc?

Или это неизбежно, и, следовательно, принципиально плохая идея создать тег с тем же именем, что и удаленная ветвь?

tommarshall
источник

Ответы:

19

Если вы абсолютно хотите сохранить эту схему именования, вы можете:

Решите, что вас не волнуют эти предупреждения

То есть, если вы довольны тем, что:

  • git checkout <ref>проверю refs/heads/<ref>более refs/tags/<ref>(см ГИТ-Checkout )
  • другие команды будут использовать refs/tags/<ref>более refs/heads/<ref>(см. gitrevisions )

Например, в этом тестовом репозитории v1.5.2ветвь указывает на фиксацию B, а v1.5.2тег указывает на фиксацию A.

% git log --oneline --decorate
8060f6f (HEAD, v1.5.2, master) commit B
0e69483 (tag: v1.5.2) commit A

git checkout предпочитает названия филиалов:

% git checkout v1.5.2
warning: refname 'v1.5.2' is ambiguous.
Switched to branch 'v1.5.2'
% git log --decorate --oneline -1
8060f6f (HEAD, v1.5.2, master) commit B

но git logбудет использовать имя тега:

% git log --decorate --oneline -1 v1.5.2
warning: refname 'v1.5.2' is ambiguous.
0e69483 (tag: v1.5.2) commit A

Это может сбить с толку.

Обучите людей удалять свои локальные ветви, когда они увидят новый тег

Это может быть трудно / неловко в зависимости от размера вашей организации.

Напишите обертку вокруг "git pull" и "git fetch"

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

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

Benj
источник
Спасибо за ответ. Очень полезно. Ваша первая пуля заявляет, что git checkoutпри наличии неоднозначной ссылки будет отмечен тег над веткой, однако это не то поведение, которое я вижу, ref: gist.github.com/tommarshall/9376724 . Это изменилось в более современной версии git? Есть ли флаг, который я могу установить gitconfig, чтобы получить это поведение?
Томмаршалл
Вы правы, я понял это совершенно неправильно. Сожалею! Я исправил свой ответ и добавил пример.
Бендж
10

Вы можете явно указать, хотите ли вы ветвь или тег, используя полное имя:

 git checkout refs/heads/v1.5.2

или

git checkout refs/tags/v1.5.2
mastahu
источник