Что такое эквивалент Git для номера ревизии?


244

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

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



Есть статья для одного из возможных решений. Он может выглядеть немного тяжелым, но интегрирован в вывод «git log» и не требует никаких дополнительных команд, кроме «git push / pull / fetch».
Дмитрий Павленко

К сожалению, связанная статья от @DmitryPavlenko находится на мертвом домене: gitsvn.x10.mx. Без указания предмета кому-либо будет трудно найти его в другом месте.
Майкл Донохью

Примечание: больше не нужно аббревиатура для git description: см. Stackoverflow.com/a/41308073/6309
VonC

1
Нет, Лоуренс Гонсалвес, это не дубликат "как подсчитать коммит мерзавцев?" - это касается номера версии, и хотя счет коммитов можно изменить, чтобы он выглядел немного похожим, - версия хеша сильно отличается от счетчика коммитов :-)
David Svarrer

Ответы:


149

Хорошая или плохая новость для вас, этот хэш - номер редакции. У меня также были проблемы с этим, когда я переключился с SVN на git.

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

Главное, что нужно понять, это то, что git не может иметь номера ревизий - подумайте о децентрализованной природе. Если пользователи A и B фиксируют свои локальные репозитории, как git может разумно назначить последовательный номер редакции? A не знает о B, прежде чем они будут толкать / вытягивать изменения друг друга.

Еще одна вещь, на которую стоит обратить внимание, это упрощенное ветвление для веток с исправлениями ошибок:

Начните с релиза: 3.0.8. Затем, после этого выпуска, сделайте это:

git branch bugfixes308

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

git checkout bugfixes308

Теперь внесите любые исправления ошибок, которые вы хотите.

git commit -a

Зафиксируйте их и переключитесь обратно в главную ветку:

git checkout master

Затем извлеките эти изменения из другой ветки:

git merge bugfixes308

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


11
Я понял, что хэш - это номер редакции, но я надеялся, что это не так :-))) спасибо за очень хорошее объяснение и за предложение сейчас разобраться с ним.
Радек

3
Пожалуйста. Я был очень разочарован мерзавцем, когда я впервые взял его из SVN, но теперь я
качаюсь

4
ТАКЖЕ, прошло некоторое время с тех пор, как я это опубликовал, но помните, что вы также можете сделать "git checkout -b new_branch_name", чтобы сделать "git branch foo" и "git checkout foo" в качестве одной строки.
Макдад

1
Правильно ли я понимаю, что хеши - это «настоящие» хэши, и даже не последовательные? Итак, что важно, если в базе данных об ошибках написано fixed in 547cc3e..c4b2eba, и у вас есть какая-то другая ревизия, вы не представляете, должен ли ваш код содержать исправление ?! Конечно, у мерзавцев в git-central есть решение для этого?!?!
Оли

3
В SVN тот факт, что ошибка исправлена ​​в r42, не говорит о том, исправлена ​​ли она и в r43, как только вы фактически используете ветки.
Матье Мой

186

С современным Git (1.8.3.4 в моем случае) и без использования веток вы можете сделать:

$ git rev-list --count HEAD
68

22
Подумайте об использованииgit rev-list --count --first-parent HEAD
Flimm

8
Учитывая эту информацию (номер 68), есть ли способ определить ревизию для повторного получения кода? Предположим, что «редакция 68» выпущена для среды тестирования, разработка продолжается, и позже разработчику необходимо повторно получить «редакцию 68» из системы контроля версий. Как он нацелится на конкретную версию, чтобы клонировать? Или я что-то упускаю в Git, что делает это ненужным?
Дэвид

9
Имейте в виду, что это решение даст разные результаты для разных разработчиков. Кроме того, вычисление в обратном направлении от "count" до коммита даст разные коммиты для разных разработчиков !! Это происходит из-за распределенной природы Git и того, что коммиты происходят в разных репозиториях в течение одного и того же отрезка времени, но могут не учитываться в git rev-list --count HEADзависимости от того, когда были сделаны последние изменения.
Джейсон

2
@ Джейсон, комментарий Дэвида о добавлении --first-parentадресует вашу проблему? Я не хотел бы избегать, казалось бы, самого простого решения из-за редкого крайнего случая, если есть столь же простой обходной путь или способ сделать его более надежным.
MarkHu

4
@MarkHu, --first-parentпомогает. Пока перебазирование не выполняется и одна и та же ветка всегда используется для создания релизов (и, конечно, для вычисления этого номера релиза), я думаю, что это можно использовать. Хотя я все еще сомневаюсь, что это всегда однозначно идентифицирует коммит, с которого вышел релиз. Есть так много вещей, которые могут пойти не так, как надо ... но в настоящий момент я не могу придумать что-то, что определенно сломало бы это (учитывая мои вышеприведенные высказывания «до тех пор»). git describeУпоминалось в другом ответе метод является путь. Создайте тег, если вы хотите что-то удобочитаемое человеком.
Джейсон

104

Команда git describeсоздает немного более удобочитаемое имя, которое относится к конкретному коммиту. Например, из документации:

С чем-то вроде текущего дерева git.git я получаю:

[torvalds@g5 git]$ git describe parent
v1.0.4-14-g2414721

то есть текущий заголовок моей "родительской" ветви основан на v1.0.4, но так как он имеет несколько коммитов, к ним добавлено число дополнительных коммитов ("14") и сокращенное имя объекта для фиксации. сам ("2414721") в конце.

Пока вы используете разумно названные теги для маркировки определенных выпусков, это можно считать примерно эквивалентным SVN-номеру «номер редакции».


7
Я просто хотел бы отметить, что это работает, только если ваш gitрепозиторий уже имеет теги; если это не так, вы можете получить git description терпит неудачу с «роковым: имена не найдены, ничего не может описать». - переполнение стека ; Это означает, что вы должны установить теги самостоятельно.
sdaau

14
@sdaau: Если вы используете это в сценарии или что-то и хотите git describeникогда не потерпеть неудачу, используйте git describe --alwaysопцию.
Грег Хьюгилл

Можно ли как-то использовать выходные данные git describeдля поиска исходного коммита? Если не считать ручного подсчета коммитов в журнале, я имею в виду.
Лии

@Lii: Что вы подразумеваете под «исходным коммитом»? И самый близкий tag ( v1.0.4) и самый последний идентификатор фиксации ( 2414721) уже являются частью вывода git description.
Грег Хьюгилл,

@GregHewgill: Да, спасибо, когда я задал вопрос, я не понял, что «сокращенное имя объекта» - это значение, которое можно использовать для идентификации фиксации. Это блестяще!
Лий

67

Другие постеры правы, «номер ревизии» отсутствует.

Я думаю, что лучший способ - использовать теги для «релизов»!

Но я использовал следующее, чтобы подделать номера ревизий (просто для того, чтобы клиенты могли видеть ревизии и ход выполнения, так как они хотели получить такие же увеличивающиеся ревизии от git, какие они использовали для subversion).

Показать "текущую версию" "HEAD" моделируется с помощью этого:

git rev-list HEAD | wc -l

Но что, если клиент скажет мне, что в «ревизии» 1302 есть ошибка?

Для этого я добавил следующее в раздел [alias] моего ~ / .gitconfig:

show-rev-number = !sh -c 'git rev-list --reverse HEAD | nl | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'

использование git show-rev-number 1302затем напечатает хеш для "ревизии" :)

Я сделал блог (на немецком языке) об этой "технике" некоторое время назад.


@Radek - «иногда нужно знать, что« изменение кода = фиксация »что-то исправило» - тогда git bisect(ссылка) является подходящим инструментом для определения того, что и когда изменилось.
Майкл

@Radek Да, это число постоянно растет. Он просто считает ревизии, которые вы зарегистрировали на ГОЛОВЕ. Так что каждый коммит - это новая ревизия. Это не будет работать для разных веток.
OderWat

1
Мне нравится ваше решение. Обратите внимание, что вы можете упростить это: show-rev-number =! Sh -c 'git rev-list --reverse HEAD | awk NR == $ 0 '
Авнер

@avner Спасибо! Я не использовал много awk в своей жизни, очевидно :)
OderWat

3
Я должен был использоватьgit rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
Джерри

27

Git не имеет той же концепции номеров ревизий, что и subversion. Вместо этого каждый данный снимок, сделанный с фиксацией, помечается контрольной суммой SHA1. Зачем? Есть несколько проблем с запуском revno в распределенной системе контроля версий:

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

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

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

Теперь, поскольку у нас есть DAG (направленный ациклический граф) ревизий, и они составляют текущее дерево, нам нужны некоторые инструменты для решения вашей проблемы: Как мы различаем разные версии. Во-первых, вы можете опустить часть хэша, если данный префикс, скажем, 1516bd , однозначно идентифицирует ваш коммит. Но это тоже довольно надумано. Вместо этого, хитрость заключается в использовании тегов и / или ветвей. Тег или ветвь похожи на «желтую заметку», которую вы прикрепляете к данному SHA1-идентификатору коммита. По сути, теги должны быть неподвижными, в то время как ветвь будет двигаться, когда в ее HEAD будут сделаны новые коммиты. Существуют способы ссылки на коммит вокруг тега или ветви, см. Справочную страницу git-rev-parse.

Обычно, если вам нужно поработать над определенным фрагментом кода, этот фрагмент претерпевает изменения и в качестве такового должен представлять собой ветвь с говорящим названием темы. Создание большого количества веток (20-30 на каждого программиста не является неслыханным, с некоторыми 4-5, опубликованными для других, чтобы работать над ними) - хитрость для эффективного git. Каждая часть работы должна начинаться как отдельная ветвь, а затем объединяться при проверке. Неопубликованные ветви могут быть полностью переписаны, и эта часть разрушающей истории - сила мерзости.

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


18

Если вам интересно, я управлял номерами версий автоматически из информации git здесь в формате

<major>.<minor>.<patch>-b<build>

где build - общее количество коммитов. Вы увидите интересный код в Makefile. Вот соответствующая часть для доступа к другой части номера версии:

LAST_TAG_COMMIT = $(shell git rev-list --tags --max-count=1)
LAST_TAG = $(shell git describe --tags $(LAST_TAG_COMMIT) )
TAG_PREFIX = "latex-tutorial-v"

VERSION  = $(shell head VERSION)
# OR try to guess directly from the last git tag
#VERSION    = $(shell  git describe --tags $(LAST_TAG_COMMIT) | sed "s/^$(TAG_PREFIX)//")
MAJOR      = $(shell echo $(VERSION) | sed "s/^\([0-9]*\).*/\1/")
MINOR      = $(shell echo $(VERSION) | sed "s/[0-9]*\.\([0-9]*\).*/\1/")
PATCH      = $(shell echo $(VERSION) | sed "s/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/")
# total number of commits       
BUILD      = $(shell git log --oneline | wc -l | sed -e "s/[ \t]*//g")

#REVISION   = $(shell git rev-list $(LAST_TAG).. --count)
#ROOTDIR    = $(shell git rev-parse --show-toplevel)
NEXT_MAJOR_VERSION = $(shell expr $(MAJOR) + 1).0.0-b$(BUILD)
NEXT_MINOR_VERSION = $(MAJOR).$(shell expr $(MINOR) + 1).0-b$(BUILD)
NEXT_PATCH_VERSION = $(MAJOR).$(MINOR).$(shell expr $(PATCH) + 1)-b$(BUILD)

9

Функция Bash:

git_rev ()
{
    d=`date +%Y%m%d`
    c=`git rev-list --full-history --all --abbrev-commit | wc -l | sed -e 's/^ *//'`
    h=`git rev-list --full-history --all --abbrev-commit | head -1`
    echo ${c}:${h}:${d}
}

выводит что-то вроде

$ git_rev
2:0f8e14e:20130220

То есть

commit_count:last_abbrev_commit:date_YYmmdd

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

8

SHA1 хэш фиксации является эквивалентом номер ревизии Subversion.


7
К сожалению, он имеет свойства, отличные от номера ревизии. Это довольно долго, и это не увеличивается монотонно. Думаю, это цена, которую нужно заплатить за распространение ...
CodesInChaos

1
@CodeInChaos: я знаю, к чему вы клоните, но обычно можно ссылаться на коммиты git только с первыми 6 или 8 символами хеш-кода.
Крис Питман

5
@Radek: Они не гарантированно уникальны (хотя, если вы обнаружите столкновение, вы можете выиграть небольшое количество знаменитостей).
Slartibartfast

8
@Radek Согласно en.wikipedia.org/wiki/Collision_attack , с 4 символами хэша у вас есть 16-битный идентификатор, что означает, что в репо с 256 (= 2 ^ (16/2)) коммитами будет 50 % вероятность того, что два коммита имеют одинаковый префикс с четырьмя символами (и с 65536 коммитами это точно, так как диапазон 4-символьных идентификаторов исчерпан). Когда вы добавляете один символ, у вас есть 20-битный идентификатор, что означает, что порог 50% составляет 1024 коммитов. Но поскольку это статистический параметр, ничто не гарантирует, что таких столкновений не было раньше.
Руди

2
Поскольку хэш основан на содержимом, все еще остается вероятность того, что два коммита имеют одинаковый префикс хеша, а не определенность. При 65536 коммитах очень вероятно, что два будут иметь одинаковый префикс с четырьмя символами, но все еще не уверен. Кроме того, полный хеш еще не имеет коллизии, но git работает над этим :) stackoverflow.com/questions/3475648/…
goodeye

6

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

# Set the source control revision similar to subversion to use in 'c'
# files as a define.
# You must build in the master branch otherwise the build branch will
# be prepended to the revision and/or "dirty" appended. This is to
# clearly ID developer builds.
REPO_REVISION_:=$(shell git rev-list HEAD --count)
BUILD_BRANCH:=$(shell git rev-parse --abbrev-ref HEAD)
BUILD_REV_ID:=$(shell git rev-parse HEAD)
BUILD_REV_ID_SHORT:=$(shell git describe --long --tags --dirty --always)
ifeq ($(BUILD_BRANCH), master)
REPO_REVISION:=$(REPO_REVISION_)_g$(BUILD_REV_ID_SHORT)
else
REPO_REVISION:=$(BUILD_BRANCH)_$(REPO_REVISION_)_r$(BUILD_REV_ID_SHORT)
endif
export REPO_REVISION
export BUILD_BRANCH
export BUILD_REV_ID

3
Кажется, самый безопасный способ git-describeизбежать ошибок - это то, git describe --always --dirty --long --tagsчто работает во всех случаях, о которых я могу подумать.
MarkHu

5

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


5

Я написал несколько утилит PowerShell для получения информации о версии из Git и упрощения тегов

функции: Get-LastVersion, Get-Revision, Get-NextMajorVersion, Get-NextMinorVersion, TagNextMajorVersion, TagNextMinorVersion:

# Returns the last version by analysing existing tags,
# assumes an initial tag is present, and
# assumes tags are named v{major}.{minor}.[{revision}]
#
function Get-LastVersion(){
  $lastTagCommit = git rev-list --tags --max-count=1
  $lastTag = git describe --tags $lastTagCommit
  $tagPrefix = "v"
  $versionString = $lastTag -replace "$tagPrefix", ""
  Write-Host -NoNewline "last tagged commit "
  Write-Host -NoNewline -ForegroundColor "yellow" $lastTag
  Write-Host -NoNewline " revision "
  Write-Host -ForegroundColor "yellow" "$lastTagCommit"
  [reflection.assembly]::LoadWithPartialName("System.Version")

  $version = New-Object System.Version($versionString)
  return $version;
}

# Returns current revision by counting the number of commits to HEAD
function Get-Revision(){
   $lastTagCommit = git rev-list HEAD
   $revs  = git rev-list $lastTagCommit |  Measure-Object -Line
   return $revs.Lines
}

# Returns the next major version {major}.{minor}.{revision}
function Get-NextMajorVersion(){
    $version = Get-LastVersion;
    [reflection.assembly]::LoadWithPartialName("System.Version")
    [int] $major = $version.Major+1;
    $rev = Get-Revision
    $nextMajor = New-Object System.Version($major, 0, $rev);
    return $nextMajor;
}

# Returns the next minor version {major}.{minor}.{revision}
function Get-NextMinorVersion(){
    $version = Get-LastVersion;
    [reflection.assembly]::LoadWithPartialName("System.Version")
    [int] $minor = $version.Minor+1;
    $rev = Get-Revision
    $next = New-Object System.Version($version.Major, $minor, $rev);
    return $next;
}

# Creates a tag with the next minor version
function TagNextMinorVersion($tagMessage){
    $version = Get-NextMinorVersion;
    $tagName = "v{0}" -f "$version".Trim();
    Write-Host -NoNewline "Tagging next minor version to ";
    Write-Host -ForegroundColor DarkYellow "$tagName";
    git tag -a $tagName -m $tagMessage
}

# Creates a tag with the next major version (minor version starts again at 0)
function TagNextMajorVersion($tagMessage){
    $version = Get-NextMajorVersion;
    $tagName = "v{0}" -f "$version".Trim();
    Write-Host -NoNewline "Tagging next majo version to ";
    Write-Host -ForegroundColor DarkYellow "$tagName";
    git tag -a $tagName -m $tagMessage
}

4

Каждый коммит имеет уникальный хеш. Кроме этого в git нет номеров ревизий. Вам нужно пометить коммиты самостоятельно, если вы хотите большего удобства для пользователя.


3

Я просто хотел бы отметить другой возможный подход - это использование git git-notes (1) , существующее начиная с версии 1.6.6 ( Примечание к Self-Git ) (я используюgit версию 1.7.9.5).

Обычно я git svnклонировал SVN-репозиторий с линейной историей (без стандартного макета, без ветвей, без тегов) и хотел сравнить номера ревизий в клонированном gitрепозитории. Этот git-клон не имеет тегов по умолчанию, поэтому я не могу его использовать git describe. Стратегия здесь, вероятно, будет работать только для линейной истории - не уверен, как это получится с объединениями и т. Д .; но вот основная стратегия:

  • Спросите git rev-listсписок всей истории коммитов
    • Так rev-listкак по умолчанию в «обратном хронологическом порядке», мы использовали бы его --reverseпереключатель, чтобы получить список коммитов, отсортированных по самым старым первым
  • Используйте bashоболочку для
    • увеличить переменную счетчика для каждого коммита как счетчик ревизий,
    • генерировать и добавлять «временные» git note для каждого коммита
  • Затем просмотрите журнал, используя git logс --notes, который также выведет заметку коммита, которая в этом случае будет "номером ревизии"
  • Когда закончите, удалите временные заметки ( примечание: я не уверен, зафиксированы ли эти заметки или нет; на самом деле они не отображаютсяgit status )

Во-первых, давайте отметим, что у gitнего есть расположение заметок по умолчанию - но вы также можете указать ref(erence) для заметок - которые будут хранить их в другом каталоге .git; например, находясь в gitпапке репо, вы можете позвонить, git notes get-refчтобы узнать, какой каталог это будет:

$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever

Следует отметить, что если вы используете notes adda --ref, вы должны впоследствии снова использовать эту ссылку - в противном случае вы можете получить ошибки типа « Нет заметки для объекта XXX ...» ».

В этом примере я решил назвать refзаметки «linrev» (для линейного пересмотра) - это также означает, что маловероятно, что процедура будет мешать уже существующим заметкам. Я также использую --git-dirпереключатель, так как, будучи gitновичком, у меня были некоторые проблемы с пониманием этого - поэтому я хотел бы «запомнить на потом» :); и я также использую, --no-pagerчтобы подавить нерест lessпри использовании git log.

Итак, если вы находитесь в каталоге с подпапкой, myrepo_gitкоторая является gitрепозиторием; можно сделать:

### check for already existing notes:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done

# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"

### check status - adding notes seem to not affect it:

$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)

### note is saved - now let's issue a `git log` command, using a format string and notes:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000:  >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000:  >>initial test message 1<< (r1)

### test git log with range:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)

### erase notes - again must iterate through rev-list

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD remove $ih"; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

Таким образом, по крайней мере, в моем конкретном случае полностью линейной истории без ветвей номера ревизий, кажется, совпадают с этим подходом - и, кроме того, кажется, что этот подход позволит использовать git log с диапазонами ревизий, в то же время получая правильные номера ревизий - YMMV хотя с другим контекстом ...

Надеюсь, это поможет кому-то,
ура!


РЕДАКТИРОВАТЬ: Хорошо, здесь это немного проще, с gitпсевдонимами для вышеуказанных циклов, вызванных setlinrevи unsetlinrev; в папке git-репозитория выполните командуbash ( обратите внимание на неприятное побег, см. также # 16136745 - Добавьте псевдоним Git, содержащий точку с запятой ):

cat >> .git/config <<"EOF"
[alias]
  setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD\"; \n\
    done; \n\
    echo \"Linear revision notes are set.\" '"

  unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD remove $ih\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD 2>/dev/null\"; \n\
    done; \n\
    echo \"Linear revision notes are unset.\" '"
EOF

... так что вы можете просто вызвать ее git setlinrevперед тем, как попытаться сделать запись, включающую линейные ревизии; и git unsetlinrevудалить эти заметки, когда вы закончите; пример из каталога git repo:

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

Время, которое потребуется оболочке для завершения этих псевдонимов, будет зависеть от размера истории хранилища.


2

Для людей, у которых есть процесс сборки Ant , вы можете сгенерировать номер версии для проекта на git с этой целью:

<target name="generate-version">

    <exec executable="git" outputproperty="version.revisions">
        <arg value="log"/>
        <arg value="--oneline"/>
    </exec>

    <resourcecount property="version.revision" count="0" when="eq">
        <tokens>
            <concat>
                <filterchain>
                    <tokenfilter>
                        <stringtokenizer delims="\r" />
                    </tokenfilter>
                </filterchain>
            <propertyresource name="version.revisions" />
            </concat>
        </tokens>
    </resourcecount>
    <echo>Revision : ${version.revision}</echo>

    <exec executable="git" outputproperty="version.hash">
        <arg value="rev-parse"/>
        <arg value="--short"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Hash : ${version.hash}</echo>


    <exec executable="git" outputproperty="version.branch">
        <arg value="rev-parse"/>
        <arg value="--abbrev-ref"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Branch : ${version.branch}</echo>

    <exec executable="git" outputproperty="version.diff">
        <arg value="diff"/>
    </exec>

    <condition property="version.dirty" value="" else="-dirty">
        <equals arg1="${version.diff}" arg2=""/>
    </condition>

    <tstamp>
        <format property="version.date" pattern="yyyy-mm-dd.HH:mm:ss" locale="en,US"/>
    </tstamp>
    <echo>Date : ${version.date}</echo>

    <property name="version" value="${version.revision}.${version.hash}.${version.branch}${version.dirty}.${version.date}" />

    <echo>Version : ${version}</echo>

    <echo file="version.properties" append="false">version = ${version}</echo>

</target>

Результат выглядит так:

generate-version:
    [echo] Generate version
    [echo] Revision : 47
    [echo] Hash : 2af0b99
    [echo] Branch : master
    [echo] Date : 2015-04-20.15:04:03
    [echo] Version : 47.2af0b99.master-dirty.2015-04-20.15:04:03

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


1

Наряду с идентификатором SHA-1 фиксации, дата и время серверного времени помогли бы?

Что-то вроде этого:

Фиксация произошла в 11:30:25 19 августа 2013 г. и будет отображаться как 6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025


1

Из руководства по Git теги - блестящий ответ на этот вопрос:

Создать аннотированный тег в Git очень просто. Самый простой способ - указать -a при запуске команды tag:

$ git tag -a v1.4 -m 'my version 1.4'

$ git tag
v0.1
v1.3
v1.4

Ознакомьтесь с 2.6 Git Basics - Tagging


Жаль, что вы должны прыгать через обручи, чтобы изменить значения по умолчанию:By default, the git push command doesn’t transfer tags to remote servers.
MarkHu

1

Мы используем эту команду для получения версии и ревизии из git:

git describe --always --tags --dirty

Возвращается

  • зафиксировать хэш как ревизию, когда теги не используются (например gcc7b71f)
  • имя тега как версия в теге (например v2.1.0, используется для выпусков)
  • имя тега, номер ревизии с момента последнего тега и фиксация хеша после тега (например v5.3.0-88-gcc7b71f)
  • То же, что и выше, плюс «грязный» тег, если рабочее дерево имеет локальные модификации (например v5.3.0-88-gcc7b71f-dirty)

Смотрите также: https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt


0

Событие после сборки для Visual Studio

echo  >RevisionNumber.cs static class Git { public static int RevisionNumber =
git  >>RevisionNumber.cs rev-list --count HEAD
echo >>RevisionNumber.cs ; }

-1

Подумайте об использовании

git-rev-label

Предоставляет информацию о ревизии Git-репозитория в формате вроде master-c73-gabc6bec. Может заполнить строку шаблона или файл переменными окружения и информацией из Git. Полезно для предоставления информации о версии программы: ветка, тег, хеш коммита, количество коммитов, грязный статус, дата и время. Одна из самых полезных вещей - это количество коммитов, без учета объединенных ветвей - только первый родитель.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.