Как я могу переместить тег в ветке git на другой коммит?


858

Я создал тег в основной ветке, который называется v0.1так:

git tag -a v0.1

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

Как я могу переместить его в самый последний коммит на master?

Ответы:


1200

Используйте -fопцию для git tag:

-f
--force

    Replace an existing tag with the given name (instead of failing)

Возможно, вы захотите использовать -fсовместно с -aпринудительным созданием аннотированного тега вместо неаннотированного.

пример

  1. Удалить тег на любом пульте, прежде чем нажать

    git push origin :refs/tags/<tagname>
    
  2. Замените тег для ссылки на самый последний коммит

    git tag -fa <tagname>
    
  3. Нажмите метку для удаленного источника

    git push origin master --tags
    

90
Это может быть хорошей идеей, чтобы удалить тег на любом пульте, прежде чем вы тоже нажмете, выполнив это: git push origin :refs/tag/<tagname>и затем сделайте git tag -fa <tagname>и затем git push origin master --tags. В противном случае вы можете получить странные вещи в списке ссылок на пульте с добавлением символов ^ и {}. Спасибо Дэну на codebasehq.com за указание на это.
eedeep

47
@eedeep: Незначительная коррекция - вместо :refs/tag/<tagname>нее должно быть :refs/tags/<tagname>.
Бен Хокинг

8
Это работает, только если вы не вытолкнули код с вашего компьютера. Если да, лучший ответ - «в мире много цифр», так как это, вероятно, не стоит хлопот.
Крис Хуан-Ливер,

33
Если вы уже нажали свой тег, вы все равно можете обновить удаленный тег принудительным нажатиемgit push -f origin <tagname>
rc_luke

11
То, что не упомянуто здесь и в документации, это то, что это действительно перемещает сообщение тега, если новое сообщение не дано.
Twonky

259

Точнее, вы должны принудительно добавить тег, а затем нажать с опциями --tags и -f:

git tag -f -a <tagname>
git push -f --tags

171

Подводя итог, если ваш пульт вызывается originи вы работаете в masterфилиале:

git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag <tagname> <commitId>
git push origin <tagname>
  • Строка 1 удаляет тег в локальном env.
  • Строка 2 удаляет тег в удаленном env.
  • Строка 3 добавляет тег в другой коммит
  • Строка 4 выдвигает изменения к удаленному

Вы также можете заменить строку 4 на, git push origin --tagsчтобы отправить все изменения с тегами из ваших локальных изменений.

На основе @ stuart-golodetz, @ greg-hewgill, @eedeep, @ ben-hocking ответов, комментариев под своими ответами и комментариев NateS под моим ответом.


87

Удалите его, git tag -d <tagname>а затем воссоздайте на правильном коммите.


3
@eedeep: Я думаю, что ответ Грега на самом деле лучше, если быть честным.
Стюарт Голодец

Будь проще. Удали его, сделай то, что сделал раньше.
ооолала

1
Это должен быть принятый ответ, для его простоты. Также не использует силу -f чрезмерно.
Чиннычинчин

48

Я стараюсь избегать нескольких вещей при использовании Git.

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

  2. Применение силы, когда не требуется.

  3. Переусердствовать (Нажмите на ветку и / или множество тегов, чтобы получить один тег, где я хочу.)

Итак, вот мое ненасильственное решение для изменения тега как локально, так и удаленно, без знания внутренних функций Git.

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

git tag -d fix123                # delete the old local tag
git push github :fix123          # delete the old remote tag (use for each affected remote)
git tag fix123 790a621265        # create a new local tag
git push github fix123           # push new tag to remote    (use for each affected remote)

githubобразец удаленного имени, fix123образец имени тега и 790a621265пример фиксации.


26

Я оставлю здесь еще одну форму этой команды, которая соответствует моим потребностям.
Был тег, v0.0.1.2который я хотел переместить.

$ git tag -f v0.0.1.2 63eff6a

Updated tag 'v0.0.1.2' (was 8078562)

А потом:

$ git push --tags --force

хорошо, спасибо, 2 простые и простые команды
Сержио

10

Еще один способ:

Переместить тег в удаленном репо. (Замените HEAD на любой другой, если это необходимо.)

$ git push --force origin HEAD:refs/tags/v0.0.1.2

Выборка меняется обратно.

$ git fetch --tags

Это более «транзакционный», чем другие ответы.
Джастин М. Кейс

9

Псевдоним для перемещения одного тега в другой коммит.

В вашем образце, чтобы двигаться совершить с хэш - e2ea1639 сделать: git tagm v0.1 e2ea1639.

Для помеченных тегов используйте git tagmp v0.1 e2ea1639.

Оба псевдонима сохраняют исходную дату и сообщение. Если вы используете, git tag -dвы потеряли свое оригинальное сообщение.

Сохраните их в своем .gitconfigфайле

# Return date of tag. (To use in another alias)
tag-date = "!git show $1 | awk '{ if ($1 == \"Date:\") { print substr($0, index($0,$3)) }}' | tail -2 | head -1 #"

# Show tag message
tag-message = "!git show $1 | awk -v capture=0 '{ if(capture) message=message\"\\n\"$0}; BEGIN {message=\"\"}; { if ($1 == \"Date:\" && length(message)==0 ) {capture=1}; if ($1 == \"commit\" ) {capture=0}  }; END { print message }' | sed '$ d' | cat -s #"

### Move tag. Use: git tagm <tagname> <newcommit> 
tagm = "!GIT_TAG_MESSAGE=$(git tag-message $1) && GIT_COMMITTER_DATE=$(git tag-date $1) && git tag-message $1 && git tag -d $1 && git tag -a $1 $2 -m \"$GIT_TAG_MESSAGE\" #"

### Move pushed tag. Use: git tagmp <tagname> <newcommit> 
tagmp = "!git tagm $1 $2 && git push --delete origin $1 && git push origin $1 #"

1

Если вы хотите переместить аннотированный тег, изменив только целевой коммит, но сохранив аннотированное сообщение и другие метаданные, используйте:

moveTag() {
  local tagName=$1
  # Support passing branch/tag names (not just full commit hashes)
  local newTarget=$(git rev-parse $2^{commit})

  git cat-file -p refs/tags/$tagName | 
    sed "1 s/^object .*$/object $newTarget/g" | 
    git hash-object -w --stdin -t tag | 
    xargs -I {} git update-ref refs/tags/$tagName {}
}

использование: moveTag <tag-to-move> <target>

Вышеуказанная функция была разработана с помощью ссылки teerapap / git-move-annotated-tag.sh .


1
Кажется, это больше не нужно: git tag -f -a my_tagуже сохраняется сообщение предыдущего сообщения (с git версии 2.11.0).
Маттис Коойман
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.