Как изменить имя Tagger и адрес электронной почты Git Tag

Короче говоря, я пишу сценарий для переноса очень большого проекта с (задыхающегося) Microsoft SourceSafe на Git, и я пытаюсь сохранить авторов меток проекта SourceSafe (которые по сути являются тегами в Git). Я знаю, что вы можете изменить автора и имя / дату коммиттера для Git Commit, но можете ли вы сделать то же самое для Git Tag?

3 ответа

Решение

TL;DR

Повторно создайте теги с новыми желаемыми данными. Но если кто-то еще имел их раньше, они могут не принять ваши новые. Или они могут! Это до них, все же.

Описание

Я знаю, что вы можете изменить автора и имя коммиттера / дату Git Commit

На самом деле, вы не можете, и тот факт, что вы не можете (и что вы можете сделать вместо этого) играет важную роль в остальной части ответа.

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

Это то, что git commit --amend (и какие варианты интерактивной перебазировки, такие как edit а также reword можно сделать так же). Сначала мы извлекаем исходный объект Git в обычные данные, где мы можем манипулировать им; затем мы делаем манипуляции и просим Git создать новый объект; и, наконец, мы прекращаем использовать старый объект и начинаем использовать новый.

Для коммита, который является коммитом-подсказкой (см. Определение head в gitglossary), все это идет довольно легко и гладко, пока мы еще не выдвинули этот коммит. Не существует никаких дополнительных коммитов, ссылающихся на этот коммит-наконечник, поэтому мы делаем новый "такой же хороший" коммит, перенаправляем имя ветки (заголовок) на новый коммит и забываем об оригинале, который мы только что заменили. Похоже, мы изменили коммит, но вместо этого мы получили новый хэш-идентификатор.

Как это относится к тегам

Git имеет два вида тегов: легкий тег и аннотированный тег. Разница между ними заключается в том, что аннотированный тег состоит из облегченного тега, указывающего на объект тега. Это объект тега, который имеет информацию тегера. (У легковесного тега такой информации нет, он просто указывает непосредственно на объект фиксации.)

Следовательно, чтобы "изменить" объект тега, мы должны сделать то же самое, что и "изменить" объект фиксации: скопировать его в новый объект тега.

Для этого нет встроенной команды, но ее легко создать из git cat-file -pЭто позволяет вам извлечь исходный тег в обычные данные и git mktag, что позволяет превратить обычные данные в новый объект тега. Например, v2.2.1 Тег в Git-репозитории для Git начинается с:

$ git cat-file -p v2.2.1
object 9b7cbb315923e61bb0c4297c701089f30e116750
type commit
tag v2.2.1
tagger Junio C Hamano <...

object Строка - это коммит, на который указывает тег:

$ git cat-file -t 9b7cbb315923e61bb0c4297c701089f30e116750
commit

так что мы можем скопировать этот тег на новый с другим tagger:

$ new_hash_id=$(git cat-file -p v2.2.1 | sed -e .... | git mktag)
$ git update-ref refs/tags/$name $new_hash_id

где sed делает все необходимое (см. ниже) и $name это имя тега. Тогда мы бы сделали легкий тег v2.2.1 указать на этот новый объект тега в $new_hash_id, Но есть две проблемы (только одна из которых может быть применима к вашему делу).

Теги могут быть подписаны PGP

Приведенный выше тег говорит:

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

и затем имеет подпись PGP в нем. Эта подпись охватывает все данные, кроме самой подписи. Если вы копируете и модифицируете этот тег, вам следует полностью отказаться от оригинальной подписи (она будет недействительной и провалит любое примененное тестирование); можете ли вы и должны ли заменить его новой подписью, и если да, то кому это решать.

Теги не должны изменять свои целевые объекты

Существующий легкий тег v2.2.1 в данный момент указывает на существующий объект тега:

$ git rev-parse v2.2.1
7c56b20857837de401f79db236651a1bd886fbbb

Это данные, которые мы просматривали до этого момента.

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

Тэги, однако, довольно часто "хорошо известны". Фактически, цель тегов - в частности, аннотированных тегов, подписанных PGP, где подпись PGP позволяет вам убедиться, что никто не связывался с данными тега, - это гарантия того, что вы можете быть уверены, что этот тег является правильным тегом, и что объект коммита, на который он указывает, является оригинальным коммитом, а не каким-то троянским конем. Если вы измените существующий тег, вы подрываете это намерение. Более того, некоторые люди, которые знают значение предыдущего тега, просто откажутся принимать новое значение: вы не сможете заставить их обновить существующий тег. Пока вы делаете это, прежде чем кто-либо еще имеет тег, они никогда не узнают, и вы будете в порядке.


1 Вернее, вы не можете изменить содержимое объекта Git, если не можете разорвать хеш. Смотрите также Как новое обнаруженное столкновение sha1 влияет на git?

В отличие от коммитов, вы можете легко удалить теги с удаленного компьютера, воссоздать их с нужным вам именем автора

git tag -d <tag-name> 
git push origin :refs/tags/<tag-name>
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git tag <tag-name> [commit]
git push origin <tag-name>

Еще одна деталь: при создании аннотированных/подписанных тегов git tagбуду использовать GIT_COMMITTER_NAMEа также GIT_COMMITTER_EMAIL( не GIT_AUTHOR_NAME/ GIT_AUTHOR_EMAIL) для " Tagger" поле.

Чтобы создать тег с другим именем/адресом электронной почты без изменения глобальной конфигурации Git :

      GIT_COMMITTER_NAME="name" GIT_COMMITTER_EMAIL="email" git tag -am"1.0.0" v1.0.0 <commit>

Обратите внимание, что для создания подписанного тега ( -s), требуется закрытый ключ для указанного удостоверения (это точка подписания).

Другие вопросы по тегам