TLDR: добавляйте дату и время и фиксируйте хэш в форме vX.X.X-datetime-hash при каждом нажатии с помощью следующей команды.

git tag -a $(git describe --exclude "v*-*-*" --tags --abbrev=0)-$(date +"%Y%m%d%H%M%S")-$(git rev-parse --short=12 HEAD) -m "\n$(git log --oneline $(git describe --tags --abbrev=0 @^)..@)" && git push origin --tags

Теперь немного более длинная версия с немного большей информацией…

Одна из интересных вещей, которые я узнал из экосистемы golang, заключается в том, что строгая маркировка semver не является обязательным требованием; вообще везде. Например, довольно часто можно увидеть такие записи в go.mod (эквивалентно package.json для JS и requirements.txt в python).

require (
    golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e
    golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d
)

где datetime и git hash используются для отслеживания с исправлением v0.0.0. Эта идея включения времени и хэша на самом деле очень полезна, когда речь идет о нативных разработках в облаке, поскольку довольно часто нам нужно перестроить новый образ докера и протолкнуть тег. Погуглив пару минут, мы уже нашли решение на github: autotag. К сожалению, настройка этого оказалась более болезненной, чем мы можем терпеть, когда вы создаете агенты, запускающие kubernetes через Jenkins. В итоге мы использовали этот однострочный код на одном из шагов CI.

git tag -a $(git describe --exclude "v*-*-*" --tags --abbrev=0)-$(date +"%Y%m%d%H%M%S")-$(git rev-parse --short=12 HEAD) -m "\n$(git log --oneline $(git describe --tags --abbrev=0 @^)..@)"

где он добавляет тег к соответствующему сообщению фиксации. Новый тег имеет форму vX.X.X-datetime-hash, а vX.X.X является последним тегом этой формы. Точнее говоря, если мы никогда не столкнемся с кем-то, он останется неизменным навсегда. Компонент datetime включает в себя второй, а хеш фиксации ограничен первыми 12 символами. Сообщение фиксации тега включает все сообщения фиксации, начиная с последнего тега, с новой строкой в ​​начале. Это безопасная операция, если параллельные сборки на одном и том же коммите отключены. В качестве альтернативы вы можете выбрать отправку только основных, а не функциональных ветвей.

Для локальной разработки и самого пользователя OMZ (с плагином git) я также добавил псевдоним, который сочетает строку тега create выше и нажатие тега как gpt. Каждое нажатие теперь автоматически помечается и создается новый образ докера. Для систем, которые могут использовать этот тип управления версиями, мы можем даже начать импортировать ветки функций внешних библиотек с помощью этого типа тегов.

alias gpt='git tag -a $(git describe --exclude "v*-*-*" --tags --abbrev=0)-$(date +"%Y%m%d%H%M%S")-$(git rev-parse --short=12 HEAD) -m "\n$(git log --oneline $(git describe --tags --abbrev=0 @^)..@)" && git push origin --tags'

Существует небольшой конфликт, где gpt на самом деле является дисковой утилитой, но для большинства людей это, вероятно, не проблема, и плагин OMZ в любом случае имеет тенденцию создавать много конфликтов. В качестве альтернативы более плавным переходом было бы переопределить один из существующих псевдонимов, например gp, который является просто git push.