В Git, как я могу записать текущий хеш коммита в файл в том же коммите - PullRequest
109 голосов
/ 09 августа 2010

Я пытаюсь сделать что-то необычное с помощью хитов Git, но я не знаю, как это сделать (или, если это возможно).

Что мне нужно сделать, так это: в каждомcommit Я хочу взять его хеш, а затем обновить файл в коммите с помощью этого хеша.

Есть идеи?

Ответы [ 7 ]

75 голосов
/ 09 августа 2010

Я бы рекомендовал сделать что-то похожее на то, что вы имеете в виду: поместить SHA1 в неотслеживаемый файл, сгенерированный как часть процесса сборки / установки / развертывания. Это, очевидно, легко сделать (git rev-parse HEAD > filename или, возможно, git describe [--tags] > filename), и при этом не нужно делать ничего сумасшедшего, например, получить файл, отличный от того, что отслеживает git.

Ваш код может затем ссылаться на этот файл, когда ему нужен номер версии, или процесс сборки может включить информацию в конечный продукт. Последнее на самом деле - то, как сам git получает свои номера версий - процесс сборки извлекает номер версии из репозитория, а затем встраивает его в исполняемый файл.

12 голосов
/ 25 января 2013

Кто-то указал мне на раздел "man gitattributes" для symb, который имеет следующий вид:

идент

Когда для идентификатора атрибута указан путь, git заменяет $ Id $в объекте blob с $ Id:, за которым следует 40-символьное имя объекта шестнадцатеричного двоичного объекта, а затем знак доллара $ при оформлении заказа.Любая последовательность байтов, начинающаяся с $ Id: и заканчивающаяся $ в файле рабочего дерева, заменяется на $ Id $ при регистрации.

Если подумать, это то, что CVS, Subversion,и т.д.Если вы посмотрите на хранилище, то увидите, что файл в хранилище всегда содержит, например, $ Id $.Это никогда не содержит расширения этого.Только при оформлении заказа текст расширяется.

10 голосов
/ 28 декабря 2010

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

Однако есть три варианта:

  1. Используйте скрипт, чтобы увеличить 'commit id' и включить его куда-нибудь. Гадкий
  2. .gitignore файл, в котором вы собираетесь хранить хэш. Не очень удобно
  3. В pre-commit сохраните хэш предыдущего коммита :) Вы не модифицируете / вставляете коммиты в 99,99% случаев, поэтому это БУДЕТ работать. В худшем случае вы все еще можете идентифицировать исходную ревизию.

Я работаю над сценарием ловушки, выложу его здесь «когда это будет сделано», но все же - раньше, чем выйдет Duke Nukem Forever:))

UPD : код для .git/hooks/pre-commit:

#!/usr/bin/env bash
set -e

#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300

branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation

# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py

Теперь единственное, что нам нужно, - это инструмент, который преобразует пару prev_commit,branch в реальный хеш коммитов:)

Я не знаю, может ли этот подход отличить слияние коммитов. Скоро проверим

9 голосов
/ 09 августа 2010

Этого можно достичь, используя атрибут filter в gitattributes . Вам нужно будет предоставить команду smudge, которая вставляет идентификатор фиксации, и команду clean, которая удаляет ее, чтобы файл, в который он вставлен, не изменялся только из-за идентификатора фиксации.

Таким образом, идентификатор фиксации никогда не сохраняется в большом двоичном файле; это просто раскрыто в вашей рабочей копии. (Фактически вставка идентификатора коммита в BLOB станет бесконечно рекурсивной задачей. ☺) Любой, кто клонирует это дерево, должен будет настроить атрибуты для себя.

3 голосов
/ 18 января 2018

Думайте за пределами поля фиксации!

вставьте это в файл hooks / post-checkout

#!/bin/sh
git describe --all --long > config/git-commit-version.txt

Версия будет доступна везде, где вы ее используете.

3 голосов
/ 09 августа 2010

Я не думаю, что вы действительно хотите это сделать, потому что, когда файл в коммите изменяется, хеш коммита также изменяется.

0 голосов
/ 29 сентября 2017

Позвольте мне исследовать, почему это сложная проблема с использованием внутренностей git.Вы можете получить sha1 текущего коммита с помощью

#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}

По сути, вы запускаете контрольную сумму sha1 для сообщения, возвращаемого git cat-file commit HEAD.При рассмотрении этого сообщения сразу же возникают две проблемы.Одним из них является дерево sha1, а вторым - время фиксации.

Теперь о времени фиксации легко можно позаботиться, изменив сообщение и угадав, сколько времени потребуется, чтобы выполнить фиксацию или планирование для фиксации в определенное время.,Истинная проблема - это дерево sha1, которое вы можете получить из git ls-tree $(git write-tree) | git mktree.По сути, вы выполняете контрольную сумму sha1 для сообщения из ls-tree, которое представляет собой список всех файлов и их контрольную сумму sha1.

Поэтому ваша контрольная сумма commit sha1 зависит от контрольной суммы sha1 дерева, которая напрямую зависит отконтрольная сумма файлов sha1, которая завершает круг и зависит от коммита sha1.Таким образом, у вас есть круговая проблема с методами, доступными мне.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...