Зміна дати тегу git (або випуску GitHub на основі цього)


95

Я додаю релізи до своїх проектів на GitHub, додаючи теги до різних комітів у головній гілці.

В одному зі своїх проектів я не додавав теги до комітів у хронологічному порядку. (Я знайшов очевидні коміти та позначив їх, а потім знайшов менш очевидні, старі коміти та позначив їх.)

Тепер GitHub показує v1.0.1 як поточний, перед ним v0.7.0, а перед цим v1.1.2 .

Здається, дата створення тегу використовується як дата випуску замість коміту, який тегується. Як я можу редагувати свої теги, щоб дати їх збігалися з комітом, який вони позначають?

відображення випусків та дат між gitk та GitHub

Відповіді:


118

ПОПЕРЕДЖЕННЯ: Це не збереже повідомлення тегів для анотованих тегів.

Підсумок

Для кожного тегу, який потрібно змінити:

  1. Поверніться в часі до коміту, що представляє тег
  2. Видалити тег (локально та віддалено)
    • Це перетворить ваш "Випуск" на GitHub у чернетку, яку ви зможете пізніше видалити.
  3. Повторно додайте однойменний тег за допомогою магічного виклику, який встановлює його дату на дату коміту.
  4. Відправте нові теги з фіксованими датами на GitHub.
  5. Перейдіть на GitHub, видаліть усі випуски, які зараз є чернетками, і заново створіть нові випуски з нових тегів

У коді:

# Fixing tag named '1.0.1'
git checkout 1.0.1               # Go to the associated commit
git tag -d 1.0.1                 # Locally delete the tag
git push origin :refs/tags/1.0.1 # Push this deletion up to GitHub

# Create the tag, with a date derived from the current head
GIT_COMMITTER_DATE="$(git show --format=%aD | head -1)" git tag -a 1.0.1 -m"v1.0.1"

git push --tags                  # Send the fixed tags to GitHub

Деталі

Відповідно до тегу в Git :

Якщо ви забули позначити тег випуску чи версії, ви завжди можете позначити його назад таким чином:

git checkout SHA1_OF_PAST_COMMIT
git tag -m"Retroactively tagging version 1.5" v1.5

І хоча це цілком придатне для використання, воно приводить до того, що ваші теги виводяться з хронологічного порядку, що може зіпсувати системи побудови, які шукають найновіший тег. Але не треба боятися. Лінус про все думав:

# This moves you to the point in history where the commit exists
git checkout SHA1_OF_PAST_COMMIT

# This command gives you the datetime of the commit you're standing on
git show --format=%aD  | head -1

# And this temporarily sets git tag's clock back to the date you copy/pasted in from above
GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800" git tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"

# Combining the two...
GIT_COMMITTER_DATE="$(git show --format=%aD  | head -1)" git tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"

Однак, якщо ви вже додали тег, ви не можете використовувати вищезазначене, git tag -f existingtagінакше git скаржиться при спробі об'єднати:

Rammy:docubot phrogz$ git push --tags
To git@github.com:Phrogz/docubot.git
 ! [rejected]        1.0.1 -> 1.0.1 (already exists)
error: failed to push some refs to 'git@github.com:Phrogz/docubot.git'
hint: Updates were rejected because the tag already exists in the remote.

Натомість ви повинні видалити тег локально:

git tag -d 1.0.1

Натисніть це видалення віддалено:

git push origin :refs/tags/1.0.1

На GitHub перезавантажте версії - випуск тепер позначено як "Чернетка" і видаліть чернетку.

Тепер додайте тег із датою з урахуванням наведених вище інструкцій і, нарешті, натисніть отриманий тег на GitHub:

git push --tags

а потім перейдіть і повторно додайте інформацію про випуск GitHub ще раз.


2
Ось скрипт bash, який видаляє та повторно додає кожен тег у git tag -l | while read -r tag; do `git checkout $tag && git tag -d $tag && git push origin :refs/tags/$tag && GIT_COMMITTER_DATE="$(git show --format=%aD | head -1)" git tag -a $tag -m"$tag"`; done; git push --tags
репозиторії

11
Ви повинні мати можливість робити всі ці речі, не перевіряючи тег. Ось модифікація вашого git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && git tag -d $tag && git push origin :refs/tags/$tag && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a $tag -m"$tag" $COMMIT_HASH ; done && git push --tags
однокласника,

2
використання git tag -afробить -dнепотрібним, і ви залишаєтесь місцевим, щоб перевірити, чи все в порядку - тоді можнаgit push --tags -f
Mr_and_Mrs_D 02

3
@Mr_and_Mrs_D Гарна порада та хороший спосіб обмежити цю операцію одним натисканням. Маючи це на увазі, я думаю, що отриманим (неперевіреним) git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH ; done && git push --tags --force
одноклассником

2
Це працює в оболонці git для PowerShell, але вам потрібно встановити змінну середовища по-різному, і робити це у два рядки: $env:GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800"аgit tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"
roncli

18

Ось односторонній підклад, заснований на деяких коментарях в іншій відповіді:

git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH ; done && git push --tags --force

ПОПЕРЕДЖЕННЯ: це призведе до нуклеотизації тегів вищого рівня та не збереже повідомлення для анотованих тегів! Будьте впевнені, що ви знаєте, що робите, і ЗОВСІН не робіть цього для загальнодоступного сховища !!!

Щоб розбити його ...

# Loop over tags
git tag -l | while read -r tag
do

    # get the commit hash of the current tag
    COMMIT_HASH=$(git rev-list -1 $tag)

    # get the commit date of the tag and create a new tag using
    # the tag's name and message. By specifying the environment
    # environment variable GIT_COMMITTER_DATE before this is
    # run, we override the default tag date. Note that if you
    # specify the variable on a different line, it will apply to
    # the current environment. This isn't desired as probably
    # don't want your future tags to also have that past date.
    # Of course, when you close your shell, the variable will no
    # longer persist.
    GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH


done

# Force push tags and overwrite ones on the server with the same name
git push --tags --force

Дякуємо @Mr_and_Mrs_D за пропозицію використовувати один натиск.


3

Спираючись на інші відповіді, ось спосіб , який буде зберегти початку повідомлення тега

git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$COMMIT_MSG" $COMMIT_HASH ; done
git tag -l -n1           #check by listing all tags with first line of message
git push --tags --force  #push edited tags up to remote

Біт, відповідальний за збереження повідомлень:

COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1)

head -n1займе перший рядок старого повідомлення коміту. Ви можете змінити його на -n2або -n3і т.д., щоб замість цього отримати два-три рядки.

Якщо ви хочете змінити дату / час лише для одного тегу, ось як ви можете розбити однорядковий рядок, щоб зробити це у вашій оболонці bash:

tag=v0.1.0
COMMIT_HASH=$(git rev-list -1 $tag)
COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1)
COMMIT_DATE=$(git show $COMMIT_HASH --format=%aD | head -1)
GIT_COMMITTER_DATE=$COMMIT_DATE git tag -s -a -f $tag -m"$COMMIT_MSG" $COMMIT_HASH

Список літератури:


Це чудово, дякую. Однак у командах для зміни окремого тегу є -sпрапор, якого немає в однорядковому вкладиші, тому я отримував, error: gpg failed to sign the dataоскільки у мене немає підписки, налаштованої на git. Ця помилка мене трохи відкинула.
wch
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.