Git - возможно ли добавить тег и сделать его коммитом? Точно так же, как в Mercurial - PullRequest
0 голосов
/ 10 мая 2018

Когда я использовал Mercurial, я использовал тег как коммит - по крайней мере, в TortoiseHG он создавал коммит при добавлении тега. Когда я пытался использовать Git, я был разочарован - более того, он не создавал фиксацию для тега, более того - когда я фиксирую из Intellij IDEA, мне нужно установить флажок для фиксации тегов в хранилище. Можно ли добавить тег в Git и сделать его коммитом, как в Mercurial? Большое спасибо за каждый ответ.

1 Ответ

0 голосов
/ 10 мая 2018

Как заметил Дон Брэнсон в комментарии , это похоже на XY проблему .Но у тегов в Git и Mercurial есть принципиальное различие, потому что тег Mercurial - это запись в файле , а тег Git - это имя , которое находится вне пространства хранилища (хотяаннотированный тег также включает в себя объект репозитория.)

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

Это имеет один фундаментальный (хотямаленький) недостаток: извлечение тегового коммита приводит к файлу .hgtags, в котором отсутствует тег, поэтому тег исчезает.Чтобы компенсировать это, современный Mercurial найдет несколько версий .hgtags, в том числе одну из коммитов, более поздних, чем текущая, чтобы найти правильный коммит по имени тега.

Git, напротив,хранит тег как облегченное имя формы refs/tags/<em>name</em>, указывающее непосредственно на фиксацию, или как облегченное имя той же формы, указывающее на объект репозитория типа tag, причем объект хранилища содержит хэш-идентификатор тегацель.Это означает, что создание тега не нарушает существующее содержимое репозитория;нет хранилища файла , содержащего теги.

Обычная цель разработки тегов заключается в том, чтобы теги никогда не изменялись и никогда не исчезали: они действуют как дополнениетолько пулпары (возможно, с дополнительными данными).Если теги действительно используются таким образом, методы Git и Mercurial ведут себя одинаково, за исключением той странности, что Mercurial требует дополнительной фиксации, а не Git.

На практике люди делают ошибки: они перемещают теги случайно или дажеумышленно в попытке скрыть более раннюю авариюСледовательно, метод Mercurial обладает одним фундаментальным преимуществом контрольного журнала по сравнению с тегами Git: мы можем при любом коммите видеть, какие теги были на момент этого коммита, даже если кто-то изменил их с тех пор.Преимущество метода Git в том, что мы не можем увидеть это и, следовательно, не можем запутаться этим: у тега v2.1 нет способа назвать оба commit a93fc12... и e07c1c4..., в зависимости от того, какой коммит мы проверили на данный момент.(Обратите внимание, что поскольку коммиты обеспечивают только частичный заказ, а не общий заказ, мы можем не иметь возможности использовать «заказ на принятие» для выбора окончательного победителя в случае неоднозначности в Mercurial.)

Все, что сказано, если вы хотите создать в Git новый коммит, чтобы иметь уникальный хеш коммита для тега, просто создайте новый коммит. 1 Хотя Git по умолчанию отклонит попыткукоммит то же содержимое, что и текущий коммит, git commit имеет флаг для принудительного такого коммита: --allow-empty.(Этот флаг несколько неверно назван: новый коммит не является пустым , это набор изменений , созданный при сравнении нового коммита с его родителем, который пуст.) Создав новый объект фиксации, вы получите новый уникальный идентификатор хеш-функции.

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


1 Обратите внимание, что каждый коммит получает метку времени (или, точнее, две метки времени, но по умолчанию для нового коммита им обоим присваивается одинаковое значение). Пока мы предполагаем, что время монотонно увеличивается, это означает, что даже если новый коммит в ином случае является дубликатом существующего коммита, т. Е. Он имеет одинаковые tree, одинаковые author и committer, одинаковые parent, и такое же сообщение журнала, как у некоторого существующего коммита - у него будет другая отметка времени и, следовательно, будет другой коммит.

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

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

...