Bagaimana Anda mengganti nama tag Git?

1219

Hari ini saya sedang melihat-lihat log untuk sebuah proyek dan menyadari bahwa saya gemuk memainkan nama tag beberapa waktu yang lalu. Apakah ada cara untuk mengganti nama tag? Google belum menemukan sesuatu yang berguna.

Saya menyadari bahwa saya dapat memeriksa versi yang ditandai dan membuat tag baru, saya bahkan mencobanya. Tapi itu sepertinya membuat objek tag yang kurang tepat. Untuk satu,

git tag -l

mencantumkannya dalam urutan relatif terhadap semua tag lainnya. Saya tidak tahu apakah itu signifikan, tetapi itu membuat saya percaya bahwa objek tag baru tidak cukup seperti yang saya inginkan. Saya dapat hidup dengan itu, karena saya benar-benar hanya peduli bahwa nama tag cocok dengan dokumentasi, tetapi saya lebih suka melakukannya "benar", dengan asumsi ada cara yang tepat untuk melakukan ini.

Brandon Fosdick
sumber
Apakah Anda menggunakan doa yang sama, yaitu jika tag lama itu anotasi / tag yang ditandatangani, apakah tag baru juga dari jenis ini, atau apakah itu tag ringan?
Jakub Narębski
1
Tag lama yang salah, dan tag baru yang diinginkan, harus dianotasi dan tidak ditandatangani. Tag lama dibuat dengan 'git tag -a bad_tag_name', jadi saya ingin melakukan sesuatu di sepanjang baris 'git tag -a good_tag_name'.
Brandon Fosdick
Saya harus menunjukkan bahwa saya juga ingin proses penggantian nama tag ajaib ini untuk menjaga anotasi dari tag yang diganti namanya. Sebenarnya, saya benar-benar ingin mengganti nama dan tidak ada yang lain.
Brandon Fosdick
7
git log --oneline --decorate --graphsangat membantu saat membersihkan tag.
Joel Purra
Anda dapat mengganti nama tag dalam satu baris: lihat jawaban saya di bawah ini
VonC

Jawaban:

2039

Inilah cara saya mengganti nama tag oldmenjadi new:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

Tanda titik dua dalam perintah push menghilangkan tag dari repositori jarak jauh. Jika Anda tidak melakukan ini, Git akan membuat tag lama pada mesin Anda saat Anda menarik.

Akhirnya, pastikan bahwa pengguna lain menghapus tag yang dihapus. Harap beri tahu mereka (rekan kerja) untuk menjalankan perintah berikut:

git pull --prune --tags

Perhatikan bahwa jika Anda mengubah tag beranotasi , Anda perlu memastikan bahwa nama tag baru merujuk komit yang mendasarinya dan bukan objek tag beranotasi lama yang akan Anda hapus. Oleh karena itu, gunakan git tag -a new old^{}alih-alih git tag new old(ini karena tag beranotasi adalah objek sementara tag ringan tidak, info lebih lanjut dalam jawaban ini ).

Casey Watson
sumber
19
jika tag dianotasi, tag baru tidak akan memiliki pesan yang lama, tetapi ini adalah info yang
berguna
25
@NickSoft, saya baru saja melakukan hal di atas dengan tag beranotasi. Pesan-pesan itu disalin dari yang lama ke yang baru saja. Mungkin saya punya versi git yang lebih baru?
katyhuff
25
git push origin :refs/tags/olddapat disederhanakan git push origin :oldmenurut saya.
Jesse Glick
25
Saya menyarankan untuk mengubah "git push --tags" agar lebih eksplisit untuk tag ini "git push origin / tag / baru". Anda tidak ingin mendorong tag lain secara tidak sengaja.
chrish
11
Peringatan : Menggunakan git tag new oldakan membuat tag yang menunjuk ke tag lama, bukan komit tag lama. (Lihat Mengapa saya tidak bisa checkout tag saya dari Git GUI? )
Stevoisiak
297

Pertanyaan awal adalah bagaimana mengubah nama tag, yang mudah: pertama kali membuat BARU sebagai alias OLD: git tag NEW OLDkemudian menghapus OLD: git tag -d OLD.

Kutipan mengenai "cara Git" dan kewarasan tidak masuk akal, karena berbicara tentang mempertahankan nama tag, tetapi membuatnya merujuk ke status repositori yang berbeda.

Greg McGary
sumber
3
Jawaban di atas sedikit lebih disukai karena termasuk git push originbisnis.
Roly
cara termudah, bekerja hebat untuk mengganti nama tag rilis sebelumnya yang dibuat dengan Gitflow
RousseauAlexandre
5
Peringatan : Menggunakan git tag new oldakan membuat tag yang menunjuk ke tag lama, bukan komit tag lama. (Lihat Mengapa saya tidak bisa checkout tag saya dari Git GUI? )
Stevoisiak
118

Selain jawaban lain:

Pertama, Anda perlu membuat alias dari nama tag lama , menunjuk ke komit asli:

git tag new old^{}

Maka Anda perlu menghapus yang lama secara lokal :

git tag -d old

Kemudian hapus tag pada Anda lokasi yang jauh:

# Check your remote sources:
git remote -v
# The argument (3rd) is your remote location,
# the one you can see with `git remote`. In this example: `origin`
git push origin :refs/tags/old

Akhirnya Anda perlu menambahkan tag baru Anda ke lokasi yang jauh. Sampai Anda melakukan ini, tag baru tidak akan ditambahkan:

git push origin --tags

Iterasi ini untuk setiap lokasi terpencil.

Sadarilah, implikasi yang dimiliki perubahan Git Tag kepada konsumen suatu paket!

kaisar
sumber
Peringatan : Menggunakan git tag new oldakan membuat tag yang menunjuk ke tag lama, bukan komit tag lama. (Lihat Mengapa saya tidak bisa checkout tag saya dari Git GUI? )
Stevoisiak
1
@StevenVascellaro Terima kasih atas tautannya. Untuk waktu berikutnya, silakan ajukan suntingan - menjawab juga merupakan upaya komunitas. Terima kasih.
kaiser
Saya belum melakukan pengeditan karena saya belum menguji kode untuk saya sendiri. (Catat tanggal
pengiriman
Setelah kita melakukannya git tag new old^{}, maka kita tidak perlu git tag new_tag_name old_tag_name(langkah pertama).
Number945
28

Jika dipublikasikan, Anda tidak dapat menghapusnya (tanpa risiko menjadi tar dan berbulu, artinya). 'Cara Git' adalah melakukan:

Yang waras. Akui saja Anda mengacau, dan gunakan nama yang berbeda. Yang lain telah melihat satu nama tag, dan jika Anda menggunakan nama yang sama, Anda mungkin berada dalam situasi di mana dua orang sama-sama memiliki "versi X", tetapi mereka sebenarnya memiliki "X" yang berbeda. Jadi sebut saja "X.1" dan selesai dengan itu.

Kalau tidak,

Hal yang gila. Anda benar-benar ingin memanggil versi baru "X" juga, meskipun yang lain sudah melihat yang lama. Jadi gunakan saja git-tag -f lagi, seolah-olah Anda belum menerbitkan yang lama.

Ini sangat gila karena:

Git tidak (dan seharusnya tidak) mengubah tag di belakang pengguna. Jadi, jika seseorang sudah mendapatkan tag lama, melakukan git-pull pada pohon Anda tidak hanya membuat mereka menimpa yang lama.

Jika seseorang mendapatkan tag rilis dari Anda, Anda tidak bisa hanya mengubah tag untuk mereka dengan memperbarui tag Anda sendiri. Ini adalah masalah keamanan besar, di mana orang HARUS dapat mempercayai nama tag mereka. Jika Anda benar-benar ingin melakukan hal yang gila, Anda hanya perlu mengakuinya, dan memberi tahu orang-orang bahwa Anda kacau.

Semua milik halaman manual .

Robert Munteanu
sumber
6
Atau Anda dapat memberi tag (dengan nama yang benar) dengan tag yang salah nama ini.
Jakub Narębski
6
Terima kasih, saya sudah membaca halaman manual itu jutaan kali. Untungnya tag yang buruk belum dipublikasikan di mana pun. Bahkan jika itu, ini adalah proyek internal dan saya satu-satunya pengembang (untuk saat ini). Saya pikir saya cukup aman dari tarring dan bulu-bulu, tetapi hanya jika saya bisa mendapatkan repo yang cocok dengan dokumen.
Brandon Fosdick
Terkadang saya menggunakan tag untuk referensi pribadi saya sendiri. Misalnya. itu bisa berupa tag 'ok_jb'. Saya menggunakan ini, karena beberapa orang yang bekerja dengan saya tidak dapat membangun untuk platform saya, jadi kadang-kadang akan ada kesalahan build. Saya kemudian dapat dengan cepat mendapatkan versi yang dibuat, dengan memeriksa tag itu. Saat sumber baru dibuat, saya hanya memindahkan tag, atau saya mengganti namanya menjadi build ##, di mana ## adalah angka (tergantung pada proyek). Saya juga dapat menekankan ketika fitur khusus diperkenalkan, dengan menambahkan tag.
7
Jawaban yang buruk "Jangan lakukan itu" tidak pernah jawaban yang benar untuk "Bagaimana saya bisa melakukannya?". Pengguna tidak bertanya apakah menurut Anda itu ide yang baik atau apakah orang akan menyukainya. Jika seseorang bertanya "Bagaimana saya bisa memotong tangan saya", katakan padanya bagaimana hal itu dilakukan atau tinggalkan dia sendiri tetapi dia tidak akan membutuhkan seseorang mengatakan kepadanya bahwa memotong tangan mungkin bukan ide yang bagus. Dan kamu bisa melakukannya. Anda dapat menambahkan tag baru dan menghapus yang lama, secara teknis memungkinkan, bahkan di repositori jarak jauh.
Mecki
5
Ini sepertinya menjawab pertanyaan "Bagaimana cara saya membuat titik tag yang ada ke revisi yang berbeda?" alih-alih pertanyaan OP, "Bagaimana cara saya mengganti nama tag?" Juga tidak jelas bagaimana memberi tahu orang-orang bahwa Anda mengacau akan menyelesaikan masalah (meskipun itu ide yang bagus secara umum).
LarsH
25

Halaman wiki ini memiliki one-liner yang menarik ini, yang mengingatkan kita bahwa kita dapat mendorong beberapa referensi :

git push origin <refs/tags/old-tag>:<refs/tags/new-tag> :<refs/tags/old-tag> && git tag -d <old-tag>

dan meminta klon lain untuk melakukannya git pull --prune --tags

Jadi idenya adalah untuk mendorong:

  • <new-tag>untuk setiap komit direferensikan oleh <old-tag>: <refs/tags/old-tag>:<refs/tags/new-tag>,
  • penghapusan<old-tag> ::<refs/tags/old-tag>

Lihat sebagai contoh " Mengubah konvensi penamaan tag di dalam repositori git? ".

VONC
sumber
Apakah ini mempertahankan anotasi?
Brandon Fosdick
1
Hati-hati karena ini meninggalkan nama tag asli dalam anotasi untuk tag beranotasi !! Saya tidak yakin apakah itu benar-benar menyiratkan apa pun, setidaknya dalam versi saat ini.
gbr
@ gbr Bisakah Anda mengedit jawaban dengan contoh yang menunjukkan bahwa "nama tag asli" tertinggal di anotasi?
VonC
1
@VonC Saya tidak yakin saya mengerti apa yang Anda minta; mungkin saya tidak jelas: objek penjelasan berisi bidang tag yang disetel ke nama tag, Anda dapat melihatnya dengan git cat-file -p <tag>; dengan metode Anda di sistem saya, saya mendapatkan tag 'diubah namanya' ( <new-tag>), tetapi bidang tagnya masih <old-tag>.
gbr
3
@ gbr Bukankah yang diinginkan OP? Dia menyebutkan "Saya harus menunjukkan bahwa saya juga ingin proses penggantian nama tag ajaib ini untuk menjaga anotasi dari tag yang diganti namanya. Sebenarnya, saya benar-benar ingin mengubah hanya nama dan tidak ada yang lain" ( stackoverflow.com/questions/1028649/ how-do-you-rename-a-git-tag / ... )
VonC
25

Sebagai tambahan pada jawaban lain, saya menambahkan alias untuk melakukan semuanya dalam satu langkah, dengan nuansa perintah * nix move yang lebih akrab. Argumen 1 adalah nama tag lama, argumen 2 adalah nama tag baru.

[alias]
    renameTag = "!sh -c 'set -e;git tag $2 $1; git tag -d $1;git push origin :refs/tags/$1;git push --tags' -"

Pemakaian:

git renametag old new
Jared Knipp
sumber
Ini tidak bekerja untuk saya, karena gagal !sh(pertanyaan adalah mengenai Windows Git), namun, setelah memperbarui format dengan berikut ini, itu bekerja: renametag = "!f() { git tag $2 $1; git tag -d $1; git push origin :refs/tags/$1; git push --tags; }; f".
Sunny Patel
10

Ikuti pendekatan 3 langkah untuk satu atau beberapa tag.

Langkah 1: Identifikasi komit / objek ID dari komit tag saat ini menunjuk ke

     command: git rev-parse <tag name>
     example: git rev-parse v0.1.0-Demo
     example output: db57b63b77a6bae3e725cbb9025d65fa1eabcde

Langkah 2: Hapus tag dari repositori

     command: git tag -d <tag name>
     example: git tag -d v0.1.0-Demo
     example output: Deleted tag 'v0.1.0-Demo' (was abcde)

Langkah 3: Buat tag baru yang menunjuk ke id komit yang sama seperti yang ditunjukkan oleh tag lama

     command: git tag -a <tag name>  -m "appropriate message" <commit id>
     example: git tag -a v0.1.0-full  -m "renamed from v0.1.0-Demo" db57b63b77a6bae3e725cbb9025d65fa1eabcde
     example output: Nothing or basically <No error>

Setelah git lokal siap dengan perubahan nama tag, perubahan ini dapat didorong kembali ke asal untuk diambil orang lain.

vikas pachisia
sumber
Tidak ada langkah untuk mendorong kembali tag yang dihapus: git push origin :refs/tags/v0.1.0-Demodan untuk mendorong tag kembali (dengan hal-hal lain yang tertunda)git push --tags
Star Wolf
6

Untuk para petualang itu dapat dilakukan dalam satu perintah:

mv .git/refs/tags/OLD .git/refs/tags/NEW
serigala
sumber
7
Ini tidak akan berhasil jika referensi Anda penuh, yaitu jika Anda git gcbaru saja menjalankan
forivall
2
Ini juga hanya akan mempengaruhi repo lokal. Jika Anda memiliki remote yang dikonfigurasi, saya tidak yakin apa efek negatif ini bisa menyebabkan. Saya tidak merekomendasikan pendekatan ini.
therealklanni
1
Perhatikan juga bahwa untuk tag beranotasi, ini mungkin akan lebih merepotkan, karena gumpalan 'anotasi' di antara hal-hal lain berisi nama asli tag. Sebenarnya saya tidak yakin apakah itu digunakan oleh apa saja (semoga setidaknya dengan memverifikasi-tag), tapi saya tidak akan mengambil risiko.
gbr
1
@gbr Ini berfungsi dengan baik. (Tentu saja, catatan oleh @ forivall harus diperhitungkan.) Trik ini telah digunakan secara besar-besaran selama berabad-abad dalam sistem pembangunan ALT Sisyphus. Lihatlah bagaimana sumber-sumber untuk suatu paket disimpan, mis .: git.altlinux.org/gears/g/gear.git . Tag yang dapat dibaca seperti 2.0.7-alt1 adalah tag bertanda tangan yang dikirimkan oleh pengelola ke sistem build. Tag cryptic gb-sisyphus-task164472.200 diletakkan di sana oleh sistem build untuk melacak ID tugas yang telah dibuat & menerbitkan pkg dari sumber ini. Itu adalah salinan bodoh ( cp), dengan pesan pengelola tidak disentuh.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Baik untuk mengetahui, saya tidak akan menaruh terlalu banyak kepercayaan meskipun itu tidak akan menimbulkan masalah di masa depan, dengan beberapa produk; tidak ada spesifikasi nyata dari format repositori git dan interaksi yang diharapkan, jadi ketika itu layak saya akan berusaha untuk melakukan hal-hal secara bersih dengan cara yang paling mengejutkan
gbr
3

Terlepas dari masalah yang terkait dengan mendorong tag dan mengganti nama tag yang telah didorong, jika tag untuk mengganti nama adalah yang beranotasi , Anda dapat menyalinnya terlebih dahulu berkat baris perintah baris tunggal berikut:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}

Kemudian, Anda hanya perlu menghapus tag lama:

git tag -d old_tag

Saya menemukan baris perintah ini berkat dua jawaban berikut:

Edit:
Setelah mengalami masalah menggunakan sinkronisasi otomatis tag pengaturan fetch.pruneTags=true(seperti yang dijelaskan dalam https://stackoverflow.com/a/49215190/7009806 ), saya pribadi menyarankan untuk pertama menyalin tag baru pada server dan kemudian menghapus yang lama. Dengan begitu, tag baru tidak dihapus secara acak ketika menghapus tag lama dan sinkronisasi tag ingin menghapus tag baru yang belum ada di server . Jadi, misalnya, secara bersama-sama kita dapatkan:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}
git push --tags
git tag -d old_tag
git push origin :refs/tags/old_tag
Olivier
sumber
3

Anda juga dapat mengganti nama tag jarak jauh tanpa memeriksanya, dengan menduplikasi tag / cabang lama ke nama baru dan menghapus yang lama, dalam satu git pushperintah.

Terpencil tag rename / Remote cabang → konversi tag: (Notice: :refs/tags/)

git push <remote_name> <old_branch_or_tag>:refs/tags/<new_tag> :<old_branch_or_tag>

Terpencil cabang rename / Remote tag → konversi cabang: (Notice: :refs/heads/)

git push <remote_name> <old_branch_or_tag>:refs/heads/<new_branch> :<old_branch_or_tag>

Output mengganti nama tag jarak jauh:

D:\git.repo>git push gitlab App%2012.1%20v12.1.0.23:refs/tags/App_12.1_v12.1.0.23 :App%2012.1%20v12.1.0.23

Total 0 (delta 0), reused 0 (delta 0)
To https://gitlab.server/project/repository.git
 - [deleted]               App%2012.1%20v12.1.0.23
 * [new tag]               App%2012.1%20v12.1.0.23 -> App_12.1_v12.1.0.23
zionyx
sumber