Подтвердить что ты не робот

Как я могу переписать python __version__ с помощью git?

Я хотел бы определить переменную __version__ в моем модуле, которая должна автоматически обновляться при git commit аналогично тому, что делают ключевые слова SVN. Есть ли способ добиться этого в Git? У кого-нибудь есть рабочий пример?

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

Редактировать: Моя конкретная проблема заключается в том, что мне нужно запустить симуляции, результаты которых зависят от точной версии скрипта симуляции. Поэтому каждый раз мне приходится хранить номер версии вместе с результатами моделирования. Если оба из них не синхронизированы, это может иметь очень печальные последствия.

4b9b3361

Ответ 1

Лучше сделать это как часть вашей упаковки, а не после каждой фиксации.

Существует два основных параметра:

  • Используйте git-archive для упаковки и используйте export-subst. К сожалению, вещи, которые вы можете заменить, ограничены заполнителями от git log --format=.... Например, вы можете написать __version__ = $Format:%H$ в свой файл, поместить <filename> export-subst в свои .gitattributes, а при запуске git archive это будет изменено на полный хэш фиксации, с которой вы архивируете. Это именно то, о чем вы просите, но я предпочитаю следующий вариант.

  • Сделайте это самостоятельно как часть процесса упаковки (часто это процесс сборки для скомпилированных пакетов) и используйте git describe. Это даст вам приятную симпатичную строку, например v1.7.4.1-59-ge3d3f7d, что означает, что "59 завершает тег v1.7.4.1, при фиксации ge3d3f7d", который затем можно вставить как можно скорее в нужное место в вашем коде при создании пакета/сборки. Это то, что делает сам Git; результат сбрасывается в файл, содержимое которого считывается в make файл, а затем передается в сборку с помощью препроцессора -D и помещается в различные имена файлов (например, tar-архив) напрямую.

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

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

Ответ 2

Вот рабочий пример этой функции с git из-за Брайана Уорнера:

исходный код:

https://github.com/warner/python-ecdsa/blob/9e21c3388cc98ba90877a1e4dbc2aaf66c67d365/setup.py#L33

Я предполагаю, что его реализация была вдохновлена ​​подобной вещью с darcs, с которой мы с ним ранее работали:

README

http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.txt

исходный код:

http://tahoe-lafs.org/trac/darcsver/browser/trunk/darcsver/darcsvermodule.py?rev=114#L69

Ответ 3

Для тех, кто нашел этот вопрос в 2018 году, вы также можете использовать Versioneer. После включения он автоматически устанавливает version в setup.py и __version__ в вашем модуле на основе последнего тега Git во время сборки.

Например, если вы создаете свой проект с тегом 1.0.0, Versioneer установит версию проекта на 1.0.0. Если вы сделаете еще два коммита, отредактируете некоторые без регистрации и соберете, Versioneer установит версию на что-то вроде 1.0.0+2.g1076c97.dirty.

Конечно, вы можете настроить, какие теги Versioneer распознает как теги версии.

Это также то, как крупные проекты, такие как pandas и matplotlib, обрабатывают свои версии.

Ответ 4

Взгляните на раздел "Расширение ключевых слов" в книге прогитов, глава 7.2: http://progit.org/book/ch7-2.html

Ответ 5

Другая возможность, кроме Versioneer, - это setuptools_scm.

Я успешно реализовал что-то очень похожее на OP, добавив следующее в setup.py (или изменив его соответствующим образом):

from setuptools import setup
setup(
    ...,
    use_scm_version=True,
    setup_requires=['setuptools_scm'],
    ...,
)

и, чтобы автоматически обновлять __version__, добавил это в __init__.py моего пакета:

from pkg_resources import get_distribution, DistributionNotFound
try:
    __version__ = get_distribution(__name__).version
except DistributionNotFound:
    # package is not installed
    pass