Как я могу заполнить git commit ID в файл, когда я совершаю коммит?



Я хотел бы создать git-Хук(Ы), который будет заполнять идентификатор фиксации фиксации, которую я собираюсь сделать в файл (в основном подстановку переменных) в моем исходном коде. Возможно ли это с Git? Или тот факт, что, разрешив переменную в Git id, я собираюсь изменить sha 1, тем самым завершая проблему "курица или яйцо".

779   9  
git

9 ответов:

Решение, которое я использовал для подобной ситуации, таково:

  1. поместите строку $Id$ куда-нибудь в файл, который вы хотите идентифицировать (например, test.html), вероятно, в комментарий или другой нефункциональный раздел файла, где это не вызовет проблем.
  2. в вашем файле .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] знакомы:

  1. vi лицензия
  2. Shift-G # перейти к концу файла
  3. dd # удалить текущую строку
  4. ZZ # сохранить файл и выйти
  5. git diff # diff показывает удаление трейлинга новая строка Примечание: diff, совсем не показывают изменения в размере FrauBSD$ значение [еще]
  6. git add LICENSE
  7. git diff # nothing (нет нестагнированных изменений)
  8. git diff -- cached # diff показывает удаление заключительной новой строки Примечание: diff [по-прежнему] не показывает изменение $FrauBSD$ value
  9. статус git # показывает измененную лицензию
  10. появляется git commit # $ EDITOR
  11. Ctrl-Z # поместить $EDITOR в фоновый режим, чтобы мы могли исследовать
  12. git diff -- кэшируется # дифф [теперь] показывает $FrauBSD$ обновление, а также удаление пустую строку
  13. fg # resume $EDITOR
  14. : q! # выйти из редактора без изменений Примечание: поскольку вы прервали фиксацию, $FrauBSD$ была возвращена
  15. git diff --cached # diff [again] показывает только удаление последней строки
  16. git commit # на этот раз мы не будем прерывать
  17. BumpZZ # вставить "Bump", сохранить и выйти
  18. файл зафиксирован как есть

Примечание: ничего не нужно делать с файлом 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 для этих файлов и каталогов.

Каталог /.git/ содержит файл с именем ORIG_HEAD, который обновляется после любого слияния (или любой другойопасной операции) с идентификатором фиксации его предшественника. Поскольку мы используем git flow, это идеально, потому что он обновляется каждый раз, когда мы нажимаем либо release, либо fix на master ветвление и развертывание.

Я предполагаю, что вы можете сделать это на любом языке сценариев, но в нашем случае, PHP, я сделал это так...
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

    Ничего не найдено.