Thay đổi ngày của thẻ git (hoặc Bản phát hành GitHub dựa trên nó)


95

Tôi đang thêm Bản phát hành vào các dự án của mình trên GitHub bằng cách thêm thẻ vào các cam kết khác nhau trong chi nhánh Chính.

Trong một trong những dự án của mình, tôi đã không thêm thẻ vào các cam kết theo thứ tự thời gian. (Tôi tìm thấy các cam kết rõ ràng và gắn thẻ chúng, sau đó tôi thấy các cam kết cũ hơn và ít rõ ràng hơn và đã gắn thẻ chúng.)

Bây giờ GitHub đang hiển thị v1.0.1 dưới dạng hiện tại, với v0.7.0 trước nó và v1.1.2 trước đó .

Dường như sử dụng ngày tạo thẻ làm Ngày phát hành thay vì cam kết đang được gắn thẻ. Làm cách nào tôi có thể chỉnh sửa các thẻ của mình để ngày tháng của chúng giống với cam kết mà chúng đang gắn thẻ?

ánh xạ các bản phát hành và ngày tháng giữa gitk và GitHub

Câu trả lời:


118

CẢNH BÁO: Điều này sẽ không lưu giữ các thông báo thẻ cho các thẻ được chú thích.

Tóm lược

Đối với mỗi thẻ cần được thay đổi:

  1. Quay ngược thời gian để cam kết đại diện cho thẻ
  2. Xóa thẻ (cục bộ và từ xa)
    • Điều này sẽ biến "Bản phát hành" của bạn trên GitHub thành Bản nháp mà bạn có thể xóa sau đó.
  3. Thêm lại thẻ cùng tên bằng cách sử dụng một lệnh gọi ma thuật đặt ngày của nó thành ngày của cam kết.
  4. Đẩy các thẻ mới có ngày tháng cố định lên GitHub.
  5. Truy cập GitHub, xóa mọi bản phát hành hiện là bản nháp và tạo lại các bản phát hành mới từ các thẻ mới

Trong mã:

# 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

Chi tiết

Theo Cách gắn thẻ trong Git :

Nếu bạn quên gắn thẻ bản phát hành hoặc phiên bản quảng cáo, bạn luôn có thể gắn thẻ trở về trước như sau:

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

Và trong khi điều đó hoàn toàn có thể sử dụng được, nó có tác dụng đưa các thẻ của bạn ra khỏi thứ tự thời gian, điều này có thể làm hỏng các hệ thống xây dựng tìm kiếm thẻ "mới nhất". Nhưng đừng sợ. Linus nghĩ về mọi thứ:

# 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"

Tuy nhiên, nếu bạn đã thêm thẻ, bạn không thể sử dụng ở trên với git tag -f existingtaghoặc nếu không, git sẽ phàn nàn khi bạn cố gắng hợp nhất:

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.

Thay vào đó, bạn phải xóa cục bộ thẻ:

git tag -d 1.0.1

Đẩy xóa từ xa:

git push origin :refs/tags/1.0.1

Trên GitHub, tải lại Bản phát hành — bản phát hành hiện đã được đánh dấu là "Bản nháp" —và xóa bản nháp.

Bây giờ, hãy thêm thẻ đã cập nhật dựa trên các hướng dẫn ở trên và cuối cùng đẩy thẻ kết quả vào GitHub:

git push --tags

và sau đó đi và thêm lại thông tin Bản phát hành GitHub một lần nữa.


2
Dưới đây là một kịch bản bash mà loại bỏ và tái bổ sung mỗi thẻ trong một repo git: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

11
Bạn sẽ có thể làm tất cả những điều đó mà không cần kiểm tra thẻ. Dưới đây là một sửa đổi của một lớp lót của bạn mà là nhanh hơn nhiều đối với tôi: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
vmrob

2
sử dụng git tag -aflàm cho -dkhông cần thiết và bạn ở lại địa phương, do đó bạn có thể kiểm tra tất cả là tốt - sau đó bạn có thểgit push --tags -f
Mr_and_Mrs_D

3
@Mr_and_Mrs_D Đề xuất hay và là cách tốt để giới hạn thao tác này trong một lần nhấn. Với ý nghĩ đó, tôi nghĩ rằng kết quả (chưa được kiểm tra) one-liner sẽ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
Công trình này trong vỏ git cho PowerShell, nhưng bạn phải thiết lập các biến môi trường khác nhau, và làm điều đó trên hai dòng: $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

Đây là một lớp lót dựa trên một số nhận xét trong câu trả lời khác:

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

CẢNH BÁO: điều này sẽ vô hiệu hóa các thẻ ngược dòng của bạn và sẽ không lưu giữ các thông báo cho các thẻ được chú thích! Hãy chắc chắn rằng bạn biết những gì bạn đang làm và KHÔNG LÀM điều này cho một kho lưu trữ công cộng !!!

Để phá vỡ nó ...

# 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

Cảm ơn @Mr_and_Mrs_D về đề xuất sử dụng một lần nhấn.


3

Dựa trên các câu trả lời khác, đây là một cách sẽ giữ lại dòng đầu tiên của thông báo thẻ

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

Bit chịu trách nhiệm bảo quản các tin nhắn là:

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

head -n1sẽ lấy dòng đầu tiên của thông báo cam kết cũ. Bạn có thể sửa đổi nó thành -n2hoặc -n3vv để có hai hoặc ba dòng thay thế.

Nếu bạn muốn thay đổi ngày / giờ chỉ cho một thẻ, đây là cách bạn có thể chia nhỏ một lớp lót để thực hiện điều đó trong bash shell của bạn:

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

Người giới thiệu:


Điều này là tuyệt vời, cảm ơn. Tuy nhiên, trong các lệnh để thay đổi một thẻ, có một -scờ không xuất hiện trong một lớp lót, vì vậy tôi đã nhận được error: gpg failed to sign the datavì tôi chưa thiết lập ký git. Lỗi đó đã khiến tôi mất hứng một chút.
wch
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.