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

Переход от CVS к Git: $ Id: $ эквивалент?

Я прочитал кучу вопросов о простых инструментах контроля исходного кода, и Git показался мне разумным выбором. У меня есть и работает, и это работает хорошо до сих пор. Один аспект, который мне нравится в CVS, - это автоматическое увеличение номера версии.

Я понимаю, что это имеет меньше смысла в распределенном репозитории, но как разработчик мне нужно/нужно что-то вроде этого. Позвольте мне объяснить, почему:

Я использую Emacs. Периодически я просматриваю новые версии исходных файлов Lisp для сторонних пакетов. Скажем, у меня есть файл foo.el, который, согласно заголовку, версии 1.3; если я посмотрю последнюю версию и увижу ее 1.143 или 2.6 или что-то еще, я знаю, что я довольно далеко позади.

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

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

Итак, какие у меня есть альтернативы? Если я не могу получить эквивалент $ Id: $, как еще я могу предоставить то, что я ищу?

Я должен отметить, что я ожидаю, что конечный пользователь НЕ будет иметь установленный Git, и даже если он сделает это, у него не будет локального репозитория (на самом деле, я не собираюсь делать его доступным таким образом).

4b9b3361

Ответ 1

SHA - это только одно представление версии (пусть и канонической). Команда git describe предлагает другим и делает это довольно хорошо.

Например, когда я запускаю git describe в моей основной ветке моего клиента Java memcached, я получаю это:

2.2-16-gc0cd61a

Это говорит о двух важных вещах:

  1. В этом дереве было ровно 16 коммитов с 2.2
  2. Точное исходное дерево может быть отображено на любом другом клоне.

Допустим, например, что вы упаковали файл version с исходным кодом (или даже переписали весь контент для распространения), чтобы показать это число. Допустим, что упакованная версия была 2.2-12-g6c4ae7a (не релиз, а действительная версия).

Теперь вы можете точно увидеть, насколько далеко вы позади (4 коммитов), и вы можете точно увидеть, какие 4 коммитов:

# The RHS of the .. can be origin/master or empty, or whatever you want.
% git log --pretty=format:"%h %an %s" 2.2-12-g6c4ae7a..2.2-16-gc0cd61a
c0cd61a Dustin Sallings More tries to get a timeout.
8c489ff Dustin Sallings Made the timeout test run on every protocol on every bui
fb326d5 Dustin Sallings Added a test for bug 35.
fba04e9 Valeri Felberg Support passing an expiration date into CAS operations.

Ответ 2

В настоящее время существует поддержка $Id: $в Git. Чтобы включить его для файла README, вы должны поставить "README ident" в .gitattributes. Поддерживаются подстановочные знаки в именах файлов. Подробнее см. man gitattributes.

Ответ 3

Это не необоснованный запрос от ОП.

Мой вариант использования:

  1. Я использую Git для своего личного кода, поэтому не сотрудничаю с другими.
  2. Я храню там системные скрипты Bash, которые могут быть помещены в /usr/local/bin когда они будут готовы.

Я использую три отдельные машины с одним и тем же Git-репозиторием. Было бы неплохо узнать, какая "версия" файла у меня в настоящее время находится в /usr/local/bin без необходимости выполнять руководство "diff -u <версия репозитория> <версия в /usr/local/bin>".

Для тех из вас, кто негативен, помните, что есть и другие варианты использования. Не все используют Git для совместной работы с файлами в репозитории Git, являющимися их "окончательным" местоположением.

В любом случае, я сделал так, чтобы создать файл атрибутов в репозитории следующим образом:

cat .git/info/attributes
# see man gitattributes
*.sh ident
*.pl ident
*.cgi ident

Затем поместите $ Id $ где-нибудь в файле (мне нравится помещать его после Шебанга).

Коммит. Обратите внимание, что это не делает расширение автоматически, как я ожидал. Вы должны повторно создать файл, например,

git commit foo.sh
rm foo.sh
git co foo.sh

И тогда вы увидите расширение, например:

$ head foo.sh
#!/bin/sh

# $Id: e184834e6757aac77fd0f71344934b1cd774e6d4 $

Некоторая полезная информация находится в разделе Как включить строку идентификатора для репозитория Git? ,

Ответ 4

Не уверен, что это когда-нибудь будет в Git. К quote Linus:

"Все понятие замены ключевых слов просто полностью идиотски. тривиально делать" вне "фактического отслеживания контента, если вы хотите иметь это, когда делаете деревья релиза как тар-шары и т.д."

Это довольно легко проверить журнал, хотя - если вы отслеживаете стабильную ветку foo.el, вы можете увидеть, какие новые коммиты находятся в журнале стабильной ветки, которые не находятся в вашей локальной копии. Если вы хотите имитировать внутренний номер версии CVS, вы можете сравнить временную метку последнего фиксации.

Изменить: вы должны писать или использовать для этого другие скрипты, конечно, не делать это вручную.

Ответ 5

Как я писал до:

Наличие автоматически генерируемых тегов идентификаторов, которые показывают разумный номер версии, невозможно сделать с инструментами DSCM, такими как Bazaar, потому что каждая линия развития может отличаться от всех остальных. Поэтому кто-то может ссылаться на версию "1.41" файла, но ваша версия "1.41" этого файла отличается.

В принципе, $Id $не имеет никакого смысла с Bazaar, Git и другими инструментами управления распределенными исходными кодами.

Ответ 6

У меня такая же проблема. Мне нужно было иметь версию, которая была бы проще хеш-строки и была бы доступна людям, использующим инструмент, без необходимости подключения к хранилищу.

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

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

Мой в Ruby, но это не очень сложный код. Скрипт Ruby имеет:

MYVERSION = '1.090'
## Call script to do updateVersion from .git/hooks/pre-commit
def updateVersion
  # We add 1 because the next commit is probably one more - though this is a race
  commits = %x[git log #{$0} | grep '^commit ' | wc -l].to_i + 1
  vers = "1.%0.3d" % commits

  t = File.read($0)
  t.gsub!(/^MYVERSION = '(.*)'$/, "MYVERSION = '#{vers}'")
  bak = $0+'.bak'
  File.open(bak,'w') { |f| f.puts t }
  perm = File.stat($0).mode & 0xfff
  File.rename(bak,$0)
  File.chmod(perm,$0)
  exit
end

И тогда у меня есть опция командной строки (-updateVersion), которая вызывает updateVersion для инструмента.

Наконец, я перехожу к главе Git и создаю исполняемый скрипт в .git/hooks/pre-commit.

Скрипт просто переходит в начало каталога Git и вызывает мой скрипт с -updateVersion.

Каждый раз, когда я регистрируюсь, переменная MYVERSION обновляется в зависимости от количества коммитов.

Ответ 7

Что-то, что делается с репозиториями Git, - это использование объекта tag. Это может быть использовано для маркировки коммита любой строкой и может использоваться для маркировки версий. Вы можете увидеть эти теги в репозитории с помощью команды git tag, которая возвращает все теги.

Это легко проверить тег. Например, если есть тег v1.1 вы можете проверить этот тег на ветке следующим образом:

git checkout -b v1.1

Поскольку это объект верхнего уровня, вы увидите всю историю этого коммита, а также сможете запускать сравнения, вносить изменения и слияния.

Не только это, но и тег сохраняется, даже если ветвь, в которой он находился, была удалена без слияния обратно в основную строку.

Ответ 8

Если для вас важны $Ключевые слова $, возможно, вы могли бы вместо этого взглянуть на Mercurial? Он имеет расширение hgkeyword, которое реализует то, что вы хотите. Mercurial интересен как DVCS в любом случае.

Ответ 9

Если вы просто хотите, чтобы люди могли понять, насколько они устарели, Git может проинформировать их об этом несколькими довольно простыми способами. Например, они сравнивают даты последнего коммита на своем сундуке и вашем сундуке. Они могут использовать git cherry чтобы увидеть, сколько коммитов произошло в вашем сундуке, а их нет.

Если это все, чего вы хотите, я бы искал способ предоставить его без номера версии.

Кроме того, я бы не стал распространять любезность на кого-либо, если вы не уверены, что он этого хочет. :)

Ответ 10

Если я правильно понимаю, по сути, вы хотите знать, сколько коммитов произошло в данном файле с момента последнего обновления.

Сначала получите изменения в удаленном источнике, но не объедините их в ветвь master:

% git fetch

Затем получите журнал изменений, которые произошли в данном файле между веткой master и удаленным origin/master.

% git log master..origin/master foo.el

Это дает вам сообщения журнала всех коммитов, которые произошли в удаленном репозитории с момента последнего объединения origin/master в ваш master.

Если вы просто хотите подсчет изменений, проведите его до wc. Скажем так:

% git rev-list master..origin/master foo.el | wc -l

Ответ 11

Идентификаторы RCS хороши для однофайловых проектов, но для любого другого $ Id $ ничего не говорит о проекте (если вы не выполняете принудительную регистрацию в файле фиктивной версии).

Еще может быть интересно, как получить эквиваленты $ Author $, $ Date $, $ Revision $, $ RCSfile $ и т.д. На уровне файла или на уровне фиксации (как разместить их там, где одни ключевые слова - это другое вопрос). У меня нет ответа на эти вопросы, но я вижу необходимость их обновления, особенно когда файлы (теперь в Git) происходят из RCS-совместимых систем (CVS).

Такие ключевые слова могут быть интересны, если исходники распространяются отдельно от любого Git-репозитория (что я и делаю). Мое решение таково:

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

При работе для следующего выпуска скрипт извлекает этот номер .version, некоторый дескриптор версии Git (например, git describe description) и монотонный номер сборки в .build (плюс хост и дату) в автоматически сгенерированный исходный файл, который связан с финальным Программа, так что вы можете узнать, из какого источника и когда он был построен.

Я разрабатываю новые функции в отдельных ветвях, и первое, что я делаю, это добавляю n (для "следующего") в строку .version (несколько ветвей, происходящих из одного корня, будут использовать один и тот же временный номер .version). Перед выпуском я решаю, какие ветки объединить (надеюсь, у всех .version та же .version). Перед совершением слияния я обновляю .version до следующего номера (основное или незначительное обновление, в зависимости от объединенных функций).

Ответ 12

Я согласен с теми, кто считает, что замена токенов принадлежит инструментам сборки, а не инструментам управления версиями.

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

Ответ 13

Чтобы применить расширение ко всем файлам во всех подкаталогах в хранилище, добавьте файл .gitattributes каталог верхнего уровня в хранилище (т. .gitignore куда вы обычно помещаете файл .gitignore), содержащий:

* ident

Чтобы убедиться в этом, вам нужно сначала выполнить эффективную проверку файлов, например, удалить или отредактировать их любым способом. Затем восстановите их с помощью:

git checkout .

И вы должны увидеть, что $Id$ заменяется чем-то вроде:

$Id: ea701b0bb744c90c620f315e2438bc6b764cdb87 $

От man gitattributes:

идент

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

Этот идентификатор будет меняться каждый раз при подтверждении новой версии файла.

Ответ 14

Поскольку вы используете Emacs, вам может повезти :)

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

Ответ 15

Я также пришел из SCCS, RCS и CVS (%W% %G% %U%).

У меня была похожая проблема. Я хотел знать, какая версия кода была в любой системе, в которой он работает. Система может быть или не быть подключена к любой сети. Система может иметь или не иметь установленный Git. В системе может быть установлен или не установлен репозиторий GitHub.

Я хотел одно и то же решение для нескольких типов кода (.sh,.go,.yml,.xml и т.д.). Я хотел, чтобы любой человек, не знакомый с Git или GitHub, мог ответить на вопрос "Какую версию вы используете?"

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

https://github.com/BradleyA/markit

git clone https://github.com/BradleyA/markit
cd markit

Ответ 16

Если вы хотите, чтобы информация о git коммите была доступна в вашем коде, то вам нужно выполнить шаг перед сборкой, чтобы получить ее там. В bash для C/C++ это может выглядеть примерно так:

prebuild.sh

#!/bin/bash
commit=$(git rev-parse HEAD)
tag=$(git describe --tags --always ${commit})
cat <<EOF >version.c
#include "version.h"
const char* git_tag="${tag}";
const char* git_commit="${commit}";
EOF

с version.h выглядит так:

#pragma once
const char* git_tag;
const char* git_commit;

Затем, где вам это нужно, в вашем коде #include "version.h" и, при необходимости, git_tag или git_commit.

И ваш Makefile может иметь что-то вроде этого:

all: package
version:
  ./prebuild.sh
package: version
  # the normal build stuff for your project

Это имеет преимущество:

  • получить правильные на данный момент значения для этой сборки независимо от ветвления, объединения вишни и тому подобного.

Эта реализация prepublish.sh имеет недостатки:

  • принудительная перекомпиляция, даже если git_tag/git_commit не изменился.
  • он не учитывает локальные измененные файлы, которые не были зафиксированы, но влияет на сборку.
    • используйте git describe --tags --always --dirty чтобы поймать этот вариант использования.
  • загрязняет глобальное пространство имен.

Любитель prebuild.sh который мог бы избежать этих проблем, оставлен в качестве упражнения для читателя.