เปลี่ยนวันที่ของแท็ก git (หรือ GitHub Release ตาม)


99

ฉันกำลังเพิ่มการเผยแพร่ในโปรเจ็กต์ของฉันบน GitHub โดยเพิ่มแท็กให้กับคอมมิตต่างๆในสาขาหลัก

ในโปรเจ็กต์หนึ่งของฉันฉันไม่ได้เพิ่มแท็กในคอมมิตตามลำดับเวลา (ฉันพบการกระทำที่ชัดเจนและแท็กพวกเขาจากนั้นฉันพบว่ามีความชัดเจนน้อยกว่าการกระทำที่เก่ากว่าและติดแท็ก)

ตอนนี้GitHub แสดง v1.0.1 เป็นปัจจุบันกับ v0.7.0 ก่อนหน้านั้นและ v1.1.2 ก่อนหน้านี้ว่า

ดูเหมือนว่าจะใช้วันที่ในการสร้างแท็กเป็นวันที่เผยแพร่แทนการคอมมิตที่ถูกแท็ก ฉันจะแก้ไขแท็กเพื่อให้วันที่ตรงกับการคอมมิตที่แท็กได้อย่างไร

การแมปรุ่นและวันที่ระหว่าง gitk และ GitHub

คำตอบ:


125

คำเตือน: สิ่งนี้จะไม่เก็บรักษาข้อความแท็กสำหรับแท็กที่มีคำอธิบายประกอบ

สรุป

สำหรับแต่ละแท็กที่ต้องเปลี่ยน:

  1. ย้อนเวลากลับไปที่การกระทำที่เป็นตัวแทนของแท็ก
  2. ลบแท็ก (ในเครื่องและจากระยะไกล)
    • การดำเนินการนี้จะเปลี่ยน "Release" ของคุณบน 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

และในขณะที่สามารถใช้งานได้อย่างสมบูรณ์แบบ แต่ก็มีผลในการทำให้แท็กของคุณไม่เรียงตามลำดับเวลาซึ่งอาจทำให้ระบบสร้างที่มองหาแท็ก "ล่าสุด" เสียหายได้ แต่ไม่ต้องกลัว Linus นึกถึงทุกสิ่ง:

# 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 Release อีกครั้ง


2
นี่คือสคริปต์ทุบตีที่ลบและเพิ่มทุกแท็กใน git repo: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
Phrogz

2
ใช้git tag -afทำให้-dไม่จำเป็นและคุณอยู่ในพื้นที่เพื่อตรวจสอบว่าทุกอย่างgit push --tags -f
เรียบร้อย

ขอบคุณ @vmrob ที่ใช้งานได้ (แม้ว่าฉันจะต้องป้อนรหัสผ่าน GitHub หลายครั้ง)
พันเอก Panic

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
vmrob

2
ใช้งานได้ใน git shell สำหรับ 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

19

นี่คือหนึ่งซับอิงจากความคิดเห็นบางส่วนในคำตอบอื่น:

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 สำหรับคำแนะนำในการใช้การกดเพียงครั้งเดียว


ดีขอบคุณ ฉันแก้ไขสิ่งนี้เพื่อแก้ไขบาง repos ที่มีแท็กผสม 0.0.1 และ v0.0.1 รูปแบบที่ทำให้เกิดปัญหากับฉัน ความพยายามเดิมของฉันคือการสร้างแท็กใหม่ที่มาจากวันที่ปัจจุบันทั้งหมดนี้จึงช่วยได้มาก gist.github.com/petertwise/3802f392aa5f2d71143b5da8d02e47e0
squarecandy

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 shell ของคุณ:

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เพราะฉันไม่ได้ลงนามในการตั้งค่าคอมไพล์ ข้อผิดพลาดนั้นทำให้ฉันผิดหวังเล็กน้อย
wch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.