Извлечение версии сборки приложения из `git description` - как получить относительно простую строку?
ОБНОВИТЬ
Я вижу, что этот вопрос стал несколько популярным. Прошло уже много лет с моего по-настоящему приятного использования Git, и с тех пор я многому научился. Пожалуйста, прочитайте последний абзац, прежде чем продолжать рассказывать о своих приключениях в Git, с тем, что вы узнали из этого Q&A.
Я хочу составить версию сборки приложения, которая будет автоматически получена из имени ветви GIT, на которой я работаю (при сборке), и количества коммитов с момента отклонения ветви. Я считаю, что это будет уникальным для любого коммита в моем GIT-репозитории? Имена ветвей уникальны, а коммиты связаны друг с другом вдоль ветки? Если и когда я отмечу коммит, у меня также может быть префикс версии с этим тегом.
В пути git describe
делает то, что я хочу, но он не включает имя ветви, на которой я нахожусь, и включает сокращенный хэш commit SHA-1, который мне не нужен, так как он ничего не добавляет к энтропии строки и может быть избыточный (я могу ошибаться здесь, поэтому, пожалуйста, поправьте меня).
Какие у меня варианты? И я вообще думаю в правильном направлении? Я просто немного устал от добавления цифр к версиям, когда у меня есть более важные вещи, связанные с разработкой программного обеспечения.
Кстати, я никогда не строю с грязным рабочим деревом. Т.е. я всегда фиксирую изменения в репозитории перед созданием публичного релиза.
Теперь я знаю, что ветви Git являются просто ссылками на коммиты, и поэтому многие ветви (и теги!) Могут указывать на один коммит. Следовательно, вопрос "к какой ветви принадлежит этот коммит / принадлежит" лежит не совсем у Git. Git отслеживает "текущую" ветку, в которой вы находитесь - ту, которую он для вас извлек - но в то же время любое количество других веток может указывать на тот же коммит, и, возможно, ни одна ветка не может быть выбрана как "основной", если вы не хотите иметь в виду тот, который в настоящее время извлечен на диск. Пожалуйста, прочитайте следующий ответ на этой странице для уточнения.
4 ответа
В git вы должны понимать, что ветки - это просто фиксация закладок. Тот факт, что вы были на foo
ветвь, когда вы сделали 0deadbeef
коммит не имеет значения для самого коммита; ветвь не является частью его идентичности.
(Mercurial вписывает имя ветки в коммит. Во многих отношениях это хуже, как объясняет Дастин Саллингс.)
Даже если предположить, что git describe
будет просто использовать текущую извлеченную ветку - если у вас есть история слияния, может быть несколько путей, ведущих к одному и тому же самому последнему теговому коммиту, который git describe
будет использовать. Так что нет даже какой-то одной ветви.
Еще одно примечание: вы можете возразить, что даже если "третий коммит из тега X" в общем случае неоднозначен, git describe
Можно просто посмотреть на график и выяснить, является ли он неоднозначным, а если нет, пропустить хэш. Однако ничто не может помешать кому-либо начать ветку поверх этого тега позже - так что тогда ваш describe
Строка станет неоднозначной задним числом.
Суть в том, что единственным однозначным идентификатором коммита является его хеш. Так что это должно быть там. Какие git describe
он добавляет некоторую избыточную (а в случае с номером коммита неоднозначную) информацию, которая делает описание более полезным для пространственного / реляционного понимания, с которым люди ориентируются в рамках модели Git.
Вот что я использую:
echo "`git symbolic-ref HEAD 2> /dev/null | cut -b 12-`-`git log --pretty=format:\"%h\" -1`"
Это производит что-то вроде:
master-6de772e
Как отметил Аристотель, на самом деле SHA-1 сам по себе - это все, что необходимо и достаточно для обеспечения однозначного тега сборки, а также полной информации, касающейся исторического контекста развития. Все остальное является избыточным в том смысле, что любая информация, которую они предоставляют, может быть получена или получена из SHA-1. Тем не менее, людям может понравиться дополнительная контекстная информация о фактической ветви, которая сразу же становится очевидной (или, по крайней мере, это делает этот человек), и, следовательно, включение названия ветви в метку. По этой причине (т.е. непосредственный анализ информации человеком) большинство моих проектов также используют более длинное "описание" идентификатора сборки, которое включает дату и время фиксации, на которой была основана сборка, в дополнение к метке идентификатора сборки. дано выше.
Официальные выпуски должны иметь тег с номером их версии. В этом случае я предлагаю следующий подход:
- Если текущий коммит имеет тег, используйте этот тег
- Если тег недоступен, используйте имя ветви и ключ SHA1
Эта единственная команда должна работать:
git describe --exact-match 2> /dev/null || echo "`git symbolic-ref HEAD 2> /dev/null | cut -b 12-`-`git log --pretty=format:\"%h\" -1`"
git describe --long
будет всегда выводить номер версии следующим образом: v1.2-10-gdeadbee, что означает 10-й коммит с аннотированного тега 'v1.2', который указывает на коммит с укороченным SHA-1 'deadbee'. Так что все, что вам нужно сделать, это пометить начало ветви (точка ветвления ветви), например <branch>-start
,
Сокращенный хэш SHA-1 коммита требуется для различения неоднозначных ситуаций, потому что "3-й коммит, т. К. Тег" x "" (например) не уникально различает коммит; может быть более одного коммита, который соответствует упомянутому описанию при наличии нелинейного, ветвистого развития. Например, в ситуации, показанной на диаграмме ASCII-искусства ниже, оба коммита, отмеченные *, соответствуют описанию "3-й коммит с тега" x "".
/-.---*---.- \ / \.--- х ---.---.---*---.---M---.<--- филиал
Обратите внимание, что в случае "слияния", как показано выше, вы не можете использовать имя ветви, чтобы различать эти два коммита с одинаковым описанием.
Итак, что вы должны сделать, это взять git describe --long
выход (--long
здесь есть опция, позволяющая избежать неоднозначностей при разборе, см. man-страницу git description), проанализировать ее и добавить информацию о текущей ветке (например, из git symbolic-ref HEAD
не от приклеивания git branch
выходной) сам.