Як я можу перемістити тег на гілці git до іншого комітету?


858

Я створив тег на головній гілці, який називається v0.1так:

git tag -a v0.1

Але потім я зрозумів, що все-таки є деякі зміни, які мені потрібні, щоб об'єднатися в master для випуску 0.1, і я це зробив. Але тепер мій v0.1тег застряг на (щоб викликати аналогію пост-примітки) неправильне виконання. Я хочу, щоб він був затриманий на останньому фіксації на master, але замість цього він застряг на другому останньому комітеті master.

Як я можу перемістити його до останнього комітету про майстра?

Відповіді:


1199

Скористайтеся -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 видаляє тег у місцевому оточенні.
  • Рядок 2 видаляє тег у віддаленому оточенні.
  • Рядок 3 додає тег до різних комірок
  • Рядок 4 штовхає зміни в пульт дистанційного керування

Ви також можете обміняти лінію 4, щоб git push origin --tagsвідтіснити всі зміни тегами з локальних змін.

На основі @ stuart-golodetz, @ greg-hewgill, @eedeep, @ ben-hocking відповідей, коментарі під їхніми відповідями та коментарі NateS нижче моєї відповіді.


87

Видаліть його, git tag -d <tagname>а потім відтворіть його на правильному фіксації.


3
@eedeep: Я думаю, що відповідь Грега насправді краще, щоб бути справедливим.
Стюарт Голодець

Не ускладнювати. Видалити це, робити те , що ви зробили , перш ніж знову.
ooolala

1
Це повинно бути прийнято відповідати, за його простоту. Також не використовує -f силу надмірно.
chinnychinchin

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).
Matthijs Kooijman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.