Как я могу заполнить git commit ID в файл, когда я совершаю коммит?
Я хотел бы создать git-Хук(Ы), который будет заполнять идентификатор фиксации фиксации, которую я собираюсь сделать в файл (в основном подстановку переменных) в моем исходном коде. Возможно ли это с Git? Или тот факт, что, разрешив переменную в Git id, я собираюсь изменить sha 1, тем самым завершая проблему "курица или яйцо".
9 ответов:
Решение, которое я использовал для подобной ситуации, таково:
- поместите строку
$Id$куда-нибудь в файл, который вы хотите идентифицировать (например,test.html), вероятно, в комментарий или другой нефункциональный раздел файла, где это не вызовет проблем.- в вашем файле
.gitattributesотметьте соответствующий файл ключевым словомident(например,*.html ident).Результатом этого является то, что когда
git checkoutкопирует файл из базы данных объектов в ваш рабочий каталог, он разворачивает строку$Id$для чтения$Id: <sha-1 of file>$, аgit addобращает это преобразование, когда вы хотите его проверить, поэтому версии этого файла в базе данных объектов всегда содержат только$Id$, а не развернутые формы.Это начало, но, к сожалению, найти коммит, содержащий файл с определенным хэшем, не так просто, и не обязательно один к одному. Поэтому, кроме того, я также помечаю эти файлы атрибутом
export-subst(например,*.html ident export-substв.gitattributes) и добавляю дополнительную строку, как и$Format:%ci$ ($Format:%h$)где-то в файле.
git checkoutиgit addне влияет на эти теги, поэтому версии в моем репозитории всегда имеют именно эту строку. Чтобы расширить эти теги, вы должны использоватьgit archiveдля создания смоляного шара (или .zip) конкретной версии вашего проекта, которую вы затем используете для развертывания этой версии - вы не сможете просто скопировать файлы илиmake installили что-то еще, так какgit archive- это единственное, что расширит эти теги.Два тега I приведем в качестве примера expand to
YYYY-MM-DD HH:MM:SS +TZOFFSET (HASH), гдеHASHв данном случае является фактическим хэшем фиксации, так что это более полезно.Вы можете найти другие потенциально полезные спецификаторы
$Format:$на странице справкиgit logпод спецификаторами--pretty-format.
Вы можете создать фильтр, который делает подстановку на файлы при фиксации и извлечении. Они называются "грязными" и "чистыми" фильтрами, и их работа контролируется через
.gitattributes. Например:*.c filter=yourfilterЭто предписывает выполнить
yourfilterфильтр для всех.cфайлы. Затем вы должны сказать git, чтоyourfilterозначает:git config --global filter.yourfilter.clean script1 git config --global filter.yourfilter.smudge script2Затем вы напишете скрипт (sed, Perl, Python или что-нибудь еще), чтобы заменить выражение типа
$LastSha$на$LastSha: <sha>$на checkout ("smudge"). Другой сценарий переворачивается расширение перед фиксацией ("чистый".)Найдите в Pro Git book "расширение ключевых слов" для подробного примера.
Невозможно сделать то, что вы хотите: хэш SHA-1 коммита вычисляется по всему снимку репозитория, включая каждый файл - член, поэтому есть проблема курицы и яйца-чтобы вычислить хэш коммита, вам нужно знать содержимое всех файлов, которые его составляют.
Это можно сделать с помощью крючка
post-commit. Вот выдержка из сайта git-scmПосле завершения всего процесса фиксации запускается крюк post-commit. Он не принимает никаких параметров, но вы можете легко получить последний коммит, запустив git log -1 HEAD. Как правило, этот скрипт используется для уведомления или чего-то подобного.
Это был бы случай получения вывода
git log -1 HEAD, а затем с помощью инструмента, такого какsed, чтобы заменить переменные в вашем файле. Однако это изменяет ваш рабочий каталог, и если вы не собираетесь выбросить эти изменения, то в конечном итоге вы получите постоянно измененный рабочий каталог.Если вы просто хотите использовать текущий хэш фиксации в переменной где-то в коде, вы можете просто выполнить
git log -1 HEADилиcat .git/HEADи сохранить выходные данные в переменнойЕсли вам нужен только идентификатор (хэш), как в заголовке вопроса, Вы можете использовать флаг
--format.git log -1 HEAD --format=%H
Хорошо, вдохновленный ответом Джона Кэрнса, я придумал этот маленький фрагмент, который вы могли бы поместить в свой файл Makefile.
Это не совсем общее решение, но оно может пригодиться. Я знаю одно-два места, где буду пользоваться им.version.h: git log -n 1 --format=format:"#define GIT_COMMIT \"%h\"%n" HEAD > $@
Ключ здесь заключается в том, чтобы поместить ваш идентификатор ревизии в какой-то файл, который Git не волнует. Вот фрагмент из одного из моих проектов:
. . . AssemblyCS="Properties/AssemblyInfo.cs" rev="$(git log -n 1 --date=short --format=format:"rev.%ad.%h" HEAD)" sed "$AssemblyCS" . . .Этот скрипт выполняется как часть моего процесса сборки (он также может быть крюком после фиксации). В этом случае
Properties/AssemblyInfo.csнаходится в.gitignore, тогда какProperties/AssemblyInfo.cs.inнаходится под управлением версий. Сборка использует файл.cs, который содержит идентификатор ревизии, который заканчивается в развернутом исполняемом файле.
Как уже упоминалось, вы не можете поместить SHA-1 самого коммита в файл во время того же самого коммита. В любом случае это будет иметь ограниченное применение, так как, глядя на два файла, вы не сразу сможете определить, какой из них более новый.
Таким образом, фактически существует способ автоматически помещать информацию отслеживания версий в зафиксированные файлы. Я сделал это для моего текущего проекта (FrauBSD; развилка FreeBSD, над которой я работаю).
Я достиг этого не с помощью Git-атрибутов фильтр. В то время как фильтры git-атрибутов позволяют легко достичь противоположного (поместить информацию в файл(ы) при проверке), я хотел расширить определенные ключевые слова во время фиксации, чтобы данные попали в репозиторий (например, после "git push origin master", github показывает расширенные значения в зафиксированном файле(ах)). Достижение последнего оказалось чрезвычайно трудным с помощью фильтра git-атрибутов именно потому, что простой "git diff" вызовет фильтр.чистый атрибут и, как было то проблема в моем случае, если вы вводите информацию о дате/времени в расширение, изменение значения каждый раз, когда вы выполняете "git diff", нежелательно и неприемлемо.
Таким образом, я разработал крюк предварительной фиксации и крюк commit-msg, которые, действуя вместе, решают проблему того, как (в частности, в случае FrauBSD) заменить следующее В зафиксированных файлах:
$FrauBSD$
С чем-то похожим на следующее Перед регистрацией (расширенные значения идут вверх по течению для других к кассе):
$FrauBSD: путь_к_файлу гггг-ММ-ДД чч:мм:ЗЗ GMTOFFSET коммиттер $
Когда кто-либо просматривает файл на github или выполняет проверку или слияние файла(ов), расширенная информация идет вместе с поездкой.
Примечание: расширенное значение никогда не изменится, если не будет другого (несвязанного) изменения, сопровождающего, соответственно.
Например, смотрите следующий коммит, в котором я просто удаляю конечную новую строку файла. Фиксация содержит как удаление заключительной новой строки, а также переход к дате / времени в ключевом слове $FrauBSD$:
Https://github.com/freebsdfrau/FrauBSD/commit/060d943d86bb6a79726065aad397723a9c704ea4
Чтобы произвести этот коммит, я сделал то, с чем большинство разработчиков [git] знакомы:
- vi лицензия
- Shift-G # перейти к концу файла
- dd # удалить текущую строку
- ZZ # сохранить файл и выйти
- git diff # diff показывает удаление трейлинга новая строка Примечание: diff, совсем не показывают изменения в размере FrauBSD$ значение [еще]
- git add LICENSE
- git diff # nothing (нет нестагнированных изменений)
- git diff -- cached # diff показывает удаление заключительной новой строки Примечание: diff [по-прежнему] не показывает изменение $FrauBSD$ value
- статус git # показывает измененную лицензию
- появляется git commit # $ EDITOR
- Ctrl-Z # поместить $EDITOR в фоновый режим, чтобы мы могли исследовать
- git diff -- кэшируется # дифф [теперь] показывает $FrauBSD$ обновление, а также удаление пустую строку
- fg # resume $EDITOR
- : q! # выйти из редактора без изменений Примечание: поскольку вы прервали фиксацию, $FrauBSD$ была возвращена
- git diff --cached # diff [again] показывает только удаление последней строки
- git commit # на этот раз мы не будем прерывать
- BumpZZ # вставить "Bump", сохранить и выйти
- файл зафиксирован как есть
Примечание: ничего не нужно делать с файлом post-commit
Это потому, что у меня есть следующие файлы в моем проекте:
- .в Git/крюки/предварительной фиксации (символическую ссылку ../../.крючки / предварительная фиксация)
- .git / hooks / commit-msg (символьная ссылка на ../../.крючки / commit-msg)
- .крючки / предварительная фиксация
- .крючки / commit-msg
- .фильтры / fraubsd-ключевые слова
Начальные редакции, которые вы можете получить здесь:
" добавление крючков / фильтров для предварительной фиксации смазывание "
Https://github.com/freebsdfrau/FrauBSD/commit/63fa0edf40fe8f5936673cb9f3e3ed0514d33673
Примечание: фильтры используются крючками (не используются в Git-атрибутах).
И обновление здесь:
Https - / / github. com / freebsdfrau / FrauBSD / commit/b0a0a6c7b2686db2e8cdfb7253aba7e4d7617432
Или вы можете просмотреть заголовки редакций здесь:
Протокол HTTPS-//гитхабе.ком/freebsdfrau/FrauBSD/дерево/оригинал/.фильтры
Протокол HTTPS-//гитхабе.ком/freebsdfrau/FrauBSD/дерево/оригинал/.крючки
Примечание: двоеточие изменено на-In выше url, так что я могу разместить более 2 ссылок (так как репутация низкая)
Наслаждайтесь, FreeBSDFrau
Я искал что-то похожее, в том, что я хотел уникальную переменную, которую я мог бы добавить к концу файлов ресурсов (например, CSS/JS) в нашем интерфейсе, что позволило бы нам установить очень долгое время кэша, чтобы уменьшить пропускную способность и увеличить производительность, но легко заставить их перезагружаться после любой фиксации. По сути, управление версиями файлов, но полностью автоматизировано. Мне было все равно, что он был самым последним, пока он был уникальным, автоматизированным и последовательным во всем нашем приложении. сервера.
Наш сценарий развертывания просто использует 'git clone', чтобы вытащить копию самого последнего кода на наши серверы приложений ,но мы ограничиваем доступ через.htaccess для этих файлов и каталогов.
Каталог
Я предполагаю, что вы можете сделать это на любом языке сценариев, но в нашем случае, PHP, я сделал это так.../.git/содержит файл с именемORIG_HEAD, который обновляется после любого слияния (или любой другойопасной операции) с идентификатором фиксации его предшественника. Поскольку мы используем git flow, это идеально, потому что он обновляется каждый раз, когда мы нажимаем либоrelease, либоfixна master ветвление и развертывание.define("MY_VERSION",substr(file_get_contents(realpath(__DIR__.'/../.git/ORIG_HEAD')),0,3));Ваш путь, очевидно, должен быть изменен для ваших собственных целей, но это приводит к 3 char достаточно уникальный идентификатор для наших целей, который теперь добавляется к концу URL-адреса нашего ресурса.
Надеюсь, что это поможет кому-то в такой же ситуации.
Я искал ответ на этот вопрос. Идентификатор фиксации уже записан в файл, который вам просто нужно знать, где искать. После совершения коммита в главной ветви вы можете найти хэш коммита по адресу
./.git/refs/heads/masterТак что в нашем решении непрерывной доставки (он загружает .git папку вместе с исходным кодом) мы можем простоcat ./.git/refs/heads/${BRANCH}чтобы связать текущий хэш коммита с нашей сборкой
Comments