Apa itu tag git, Cara membuat tag & Cara checkout tag remote git

524

ketika saya checkout perintah git tag remote gunakan seperti ini:

git checkout -b local_branch_name origin/remote_tag_name

Saya mendapat kesalahan seperti ini:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Saya dapat menemukan remote_tag_name ketika saya menggunakan perintah git tag.

Ryanqy
sumber

Jawaban:

1154

Mari kita mulai dengan menjelaskan apa itu tag di git

masukkan deskripsi gambar di sini

Tag digunakan untuk memberi label dan menandai komit tertentu dalam riwayat.
Biasanya digunakan untuk menandai titik rilis (mis. V1.0, dll.).

Meskipun tag mungkin tampak mirip dengan cabang, tag, bagaimanapun, tidak berubah . Ini menunjuk langsung ke komit tertentu dalam sejarah.

masukkan deskripsi gambar di sini


Anda tidak akan dapat checkout tag jika tidak secara lokal di repositori Anda, jadi pertama-tama, Anda harus fetchtag ke repositori lokal Anda.

Pertama, pastikan bahwa tag ada secara lokal dengan melakukan

# --all will fetch all the remotes.
# --tags will fetch all tags as well
$ git fetch --all --tags --prune

Kemudian periksa tag dengan menjalankan

$ git checkout tags/<tag_name> -b <branch_name>

Alih-alih originmenggunakan tags/awalan.


Dalam sampel ini Anda memiliki 2 tag versi 1.0 & versi 1.1 Anda dapat memeriksanya dengan salah satu dari yang berikut:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

Semua hal di atas akan melakukan hal yang sama karena tag hanya sebuah pointer ke komit yang diberikan.

masukkan deskripsi gambar di sini
asal: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Bagaimana cara melihat daftar semua tag?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

Bagaimana cara membuat tag?

Ada 2 cara untuk membuat tag:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

Perbedaan antara 2 adalah bahwa ketika membuat tag beranotasi Anda dapat menambahkan metadata seperti yang Anda miliki dalam komit git:
nama, email, tanggal, komentar & tanda tangan

masukkan deskripsi gambar di sini

Bagaimana cara menghapus tag?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Bagaimana cara mengkloning tag tertentu?

Untuk mengambil konten dari tag yang diberikan, Anda dapat menggunakan checkoutperintah. Seperti yang dijelaskan di atas, tag sama seperti commit lainnya sehingga kita dapat menggunakan checkoutdan alih-alih menggunakan SHA-1, cukup menggantinya dengan tag_name

Pilihan 1:

# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>

Pilihan 2:

Menggunakan perintah klon

Karena git mendukung clone dangkal dengan menambahkan --branchperintah clone, kita dapat menggunakan nama tag daripada nama cabang. Git tahu bagaimana "menerjemahkan" SHA-1 yang diberikan ke komit yang relevan

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch =

--branch juga dapat mengambil tag dan melepaskan HEAD pada komit di repositori yang dihasilkan.


Bagaimana cara mendorong tag?

git push --tags

Untuk mendorong semua tag:

# Push all tags
$ git push --tags 

Menggunakan refs/tagsbukan hanya menentukan <tagname>.

Mengapa? - Disarankan untuk menggunakan refs/tagskarena kadang-kadang tag dapat memiliki nama yang sama dengan cabang Anda dan dorongan git sederhana akan mendorong cabang bukan tag

Untuk mendorong tag beranotasi dan tag rantai riwayat saat ini gunakan:

git push --follow-tags

Bendera ini --follow-tagsmendorong kedua komit dan hanya tag yang sama-sama:

  • Tag beranotasi (sehingga Anda dapat melewati tag build lokal / temporer)
  • Tag yang dapat dijangkau (leluhur) dari cabang saat ini (terletak pada sejarah)

masukkan deskripsi gambar di sini

Dari Git 2.4 Anda dapat mengaturnya menggunakan konfigurasi

$ git config --global push.followTags true

Contekan: masukkan deskripsi gambar di sini


Panduan Kode
sumber
3
bagus. git checkout A. apa A? Bagaimana cara Anda membuat A?
Sayang
3
@CodeWizard Bagan alur yang bagus! Perangkat lunak apa yang Anda gunakan untuk memproduksinya?
Giovanni Lovato
4
@Honey Aadalah hash komit
Alex Baklanov
2
@GiovanniLovato Diagram alir adalah yang pihak ketiga. Tautan ke gambar adalah backlog.com/git-tutorial/img/post/stepup/… yang berasal dari halaman ini backlog.com/git-tutorial/stepup/stepup4_1.html situs web yang disebut Panduan Pemula Git untuk Dummies (backlog) .com).
George
2
Perlu dicatat bahwa git checkout tags/<tag_name> -b <branch_name>memang membutuhkan -b <branch_name>. git checkout tags/<tag_name>memberiku kepala yang terpisah. Seperti artikel ini tentang kepala terpisah , Anda menghindari kepala terpisah dengan membuat sementara dan menghapus cabang. Ini adalah aliran kerja yang sangat asing. Jelas saya sebagai pengguna git harus terbiasa membuat dan menghapus cabang untuk kesenangan dan keuntungan.
icc97
194

(Jawaban ini perlu waktu untuk ditulis, dan jawaban codeWizard benar dalam tujuan dan esensi, tetapi tidak sepenuhnya lengkap, jadi saya akan tetap memposting ini.)


Tidak ada yang namanya "tag Git jarak jauh". Hanya ada "tag". Aku menunjukkan semua keluar ini tidak menjadi bertele-tele, 1 tetapi karena ada banyak kebingungan tentang ini dengan pengguna Git santai, dan dokumentasi Git tidak sangat membantu 2 untuk pemula. (Tidak jelas apakah kebingungan muncul karena dokumentasi yang buruk, atau dokumentasi yang buruk muncul karena ini pada dasarnya agak membingungkan, atau apa.)

Ada yang "cabang terpencil", lebih tepat disebut "remote-pelacakan cabang", tapi itu perlu dicatat bahwa ini sebenarnya entitas lokal. Tidak ada tag jarak jauh, kecuali (kecuali jika Anda membuatnya). Hanya ada tag lokal, jadi Anda perlu mendapatkan tag secara lokal untuk menggunakannya.

Bentuk umum untuk nama untuk komit tertentu — yang Git sebut referensi — adalah string apa pun yang dimulai dengan refs/. String yang dimulai dengan refs/heads/nama cabang; string yang dimulai dengan refs/remotes/nama cabang pelacakan jarak jauh; dan string yang dimulai dengan memberi refs/tags/nama sebuah tag. Nama refs/stashadalah referensi simpanan (seperti yang digunakan oleh git stash; perhatikan kurangnya garis miring).

Ada beberapa nama-kasus khusus yang tidak biasa yang tidak dimulai dengan refs/: HEAD, ORIG_HEAD, MERGE_HEAD, dan CHERRY_PICK_HEADkhususnya semua juga nama-nama yang mungkin merujuk kepada komit tertentu (meskipun HEADbiasanya berisi nama cabang, yaitu, mengandung ). Tetapi secara umum, referensi dimulai dengan .ref: refs/heads/branchrefs/

Satu hal yang dilakukan Git untuk membuat ini membingungkan adalah bahwa hal itu memungkinkan Anda untuk menghilangkan refs/, dan seringkali kata setelahnya refs/. Misalnya, Anda dapat menghilangkan refs/heads/atau refs/tags/ketika merujuk ke cabang atau tag lokal — dan sebenarnya Anda harus menghilangkannya refs/heads/saat memeriksa cabang lokal! Anda dapat melakukan ini kapan pun hasilnya tidak ambigu, atau — seperti yang baru saja kita catat — ketika Anda harus melakukannya (untuk ).git checkout branch

Memang benar bahwa referensi ada tidak hanya di repositori Anda sendiri, tetapi juga di repositori jarak jauh. Namun, Git memberi Anda akses ke referensi repositori jarak jauh hanya pada waktu yang sangat spesifik: yaitu, selama fetchdan pushoperasi. Anda juga dapat menggunakan git ls-remoteatau git remote showmelihat mereka, tetapi fetchdan pushadalah poin lebih menarik kontak.

Refspec

Selama fetchdan push, Git menggunakan string yang dipanggil refspec untuk mentransfer referensi antara repositori lokal dan jarak jauh. Dengan demikian, pada saat-saat ini, dan melalui refspecs, dua repositori Git dapat disinkronkan satu sama lain. Setelah nama Anda disinkronkan, Anda dapat menggunakan nama yang sama dengan yang digunakan seseorang dengan remote. Ada beberapa keajaiban khusus di sini fetch, dan itu memengaruhi nama cabang dan nama tag.

Anda harus menganggap git fetchmengarahkan Git Anda untuk memanggil (atau mungkin mengirim pesan teks) Git lain — yang "jauh" - dan bercakap-cakap dengannya. Di awal percakapan ini, kendali jarak jauh mencantumkan semua rujukannya: semua yang ada di dalamnya refs/heads/dan semua yang ada di refs/tags/dalamnya, bersama dengan referensi lain yang dimilikinya. Git Anda memindai ini dan (berdasarkan pada mengambil refspec biasa) mengubah nama cabang mereka.

Mari kita lihat refspec normal untuk remote bernama origin:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

Refspec ini menginstruksikan Git Anda untuk mengambil setiap pencocokan nama refs/heads/*—yaitu, setiap cabang pada remote — dan mengubah namanya menjadi refs/remotes/origin/*, yaitu, menjaga agar bagian yang cocok tetap sama, mengubah nama cabang ( refs/heads/) menjadi nama cabang pelacakan jarak jauh ( refs/remotes/, khususnya , refs/remotes/origin/).

Ini adalah melalui refspec ini bahwa origincabang 's menjadi cabang remote-pelacakan untuk remote origin. Nama cabang menjadi nama cabang pelacakan jarak jauh, dengan nama kendali jarak jauh, dalam hal ini origin, disertakan. Tanda plus +di bagian depan refspec menetapkan bendera "force", yaitu, cabang pelacak jarak jauh Anda akan diperbarui agar sesuai dengan nama cabang jarak jauh, terlepas dari apa yang diperlukan untuk membuatnya cocok. (Tanpa itu +, pembaruan cabang dibatasi hanya untuk perubahan "maju cepat", dan pembaruan tag diabaikan begitu saja sejak Git versi 1.8.2 atau lebih — sebelum itu diterapkan aturan maju cepat yang sama.)

Tag

Tapi bagaimana dengan tag? Tidak ada refspec untuk mereka — setidaknya, tidak secara default. Anda dapat mengatur satu, dalam hal ini bentuk refspec terserah Anda; atau kamu bisa lari git fetch --tags. Menggunakan --tagsmemiliki pengaruh penambahan refs/tags/*:refs/tags/*ke refspec, yaitu, itu membawa lebih dari semua tag ( tapi tidak memperbarui Anda tag jika Anda sudah memiliki tag dengan nama itu, terlepas dari apa tag remote mengatakan Edit, 2017 Jan: sebagai Git 2.10 , pengujian menunjukkan bahwa --tagssecara paksa memperbarui tag Anda dari tag jarak jauh, seolah-olah refspec membaca +refs/tags/*:refs/tags/*; ini mungkin perbedaan perilaku dari versi Git yang lebih lama).

Perhatikan bahwa tidak ada penggantian nama di sini: jika remote originmemiliki tag xyzzy, dan Anda tidak, dan Anda git fetch origin "refs/tags/*:refs/tags/*", Anda refs/tags/xyzzyditambahkan ke repositori Anda (menunjuk ke komit yang sama seperti pada remote). Jika Anda menggunakan +refs/tags/*:refs/tags/*maka tag Anda xyzzy, jika ada, diganti dengan yang dari origin. Yaitu, +flag gaya pada refspec berarti "ganti nilai referensi saya dengan yang didapat Git dari Git mereka".

Tag otomatis saat mengambil

Untuk alasan historis, 3 jika Anda tidak menggunakan --tagsopsi atau --no-tagsopsi, git fetchmengambil tindakan khusus. Ingat bahwa kami mengatakan di atas bahwa remote dimulai dengan menampilkan semua referensi Git lokal Anda, apakah Git lokal Anda ingin melihatnya atau tidak. 4 Git Anda mencatat semua tag yang dilihatnya saat ini. Kemudian, ketika ia mulai mengunduh objek komit yang diperlukan untuk menangani apa pun yang diambilnya, jika salah satu dari komitmen tersebut memiliki ID yang sama dengan salah satu dari tag tersebut, git akan menambahkan tag itu — atau tag itu, jika beberapa tag memiliki ID itu — untuk repositori Anda.

Edit, Jan 2017: pengujian menunjukkan bahwa perilaku di Git 2.10 sekarang: Jika Git mereka memberikan tag bernama T , dan Anda tidak memiliki tag bernama T , dan ID komit yang terkait dengan T adalah leluhur dari salah satu cabang mereka bahwa Anda git fetchsedang memeriksa, Git Anda menambahkan T ke tag Anda dengan atau tanpa --tags. Menambahkan --tagsmenyebabkan Git Anda mendapatkan semua tag mereka, dan juga memaksa pembaruan.

Intinya

Anda mungkin harus menggunakan git fetch --tagsuntuk mendapatkan tag mereka. Jika nama tag mereka bertentangan dengan nama tag yang ada, Anda dapat (tergantung pada versi Git) bahkan harus menghapus (atau mengganti nama) beberapa tag Anda, dan kemudian menjalankan git fetch --tags, untuk mendapatkan tag mereka. Karena tag — tidak seperti cabang jarak jauh — tidak memiliki penamaan ulang otomatis, nama tag Anda harus cocok dengan nama tag mereka, itulah sebabnya Anda dapat memiliki masalah dengan konflik.

Namun, dalam kebanyakan kasus normal, orang yang sederhana git fetchakan melakukan pekerjaannya, membawa komitmen mereka dan tag yang cocok, dan karena mereka — siapa pun mereka — akan menandai komitmen pada saat mereka menerbitkan komitmen tersebut, Anda akan tetap mengikuti tag mereka. Jika Anda tidak membuat tag sendiri, atau mencampur repositori dan repositori lainnya (melalui beberapa remote), Anda tidak akan memiliki tabrakan nama tag, jadi Anda tidak perlu repot menghapus atau mengganti nama tag untuk dapatkan tag mereka.

Ketika Anda membutuhkan nama yang memenuhi syarat

Saya sebutkan di atas bahwa Anda dapat menghilangkan refs/hampir selalu, dan refs/heads/dan refs/tags/dan seterusnya sebagian besar waktu. Tetapi kapan Anda tidak bisa ?

Lengkap (atau dekat-lengkap pula) jawabannya adalah di dalam gitrevisionsdokumentasi . Git akan menyelesaikan nama ke ID komit menggunakan urutan enam langkah yang diberikan dalam tautan. Anehnya, tag menimpa cabang: jika ada tag xyzzydan cabang xyzzy, dan mereka menunjukkan komitmen yang berbeda, maka:

git rev-parse xyzzy

akan memberi Anda ID yang ditunjuk oleh tag. Namun — dan inilah yang tidak ada gitrevisions- git checkoutlebih suka nama cabang, jadi Anda git checkout xyzzyakan ditempatkan di cabang, mengabaikan tag.

Dalam hal ambiguitas, Anda hampir selalu bisa mengeja nama ref menggunakan nama lengkapnya, refs/heads/xyzzyatau refs/tags/xyzzy. (Catatan bahwa ini tidak bekerja dengan git checkout, tetapi dalam cara yang mungkin tak terduga: git checkout refs/heads/xyzzymenyebabkan checkout terpisah-KEPALA daripada checkout cabang Inilah sebabnya mengapa Anda hanya perlu catatan itu. git checkoutAkan menggunakan nama pendek sebagai nama cabang pertama: itulah bagaimana Anda periksa cabang xyzzybahkan jika tag xyzzyada. Jika Anda ingin memeriksa tag, Anda dapat menggunakan refs/tags/xyzzy.)

Karena (sebagai gitrevisionscatatan) Git akan mencoba , Anda juga dapat menulis untuk mengidentifikasi komit yang ditandai . (Jika seseorang telah berhasil menulis referensi yang valid bernama ke , bagaimanapun, ini akan menyelesaikan sebagai . Tapi biasanya hanya berbagai nama harus dalam .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Oke, oke, "bukan hanya untuk menjadi sombong". :-)

2 Beberapa orang akan mengatakan "sangat tidak membantu", dan saya cenderung setuju, sebenarnya.

3 Pada dasarnya,, git fetchdan seluruh konsep remote dan refspec, sedikit tambahan terlambat untuk Git, terjadi sekitar waktu Git 1.5. Sebelum itu hanya ada beberapa kasus khusus ad-hoc, dan pengambilan tag adalah salah satunya, jadi itu dibuat kakek melalui kode khusus.

4 Jika itu membantu, pikirkan remote Git sebagai flasher , dalam arti slang.

torek
sumber
Langgan yang bagus. Satu nit kecil: git fetchhanya akan mengambil tag jarak jauh yang diberikan --tagsarg.
minggu
@cweekly: perilaku --tags, --no-tagsdan standar sebenarnya cukup rumit. Defaultnya adalah untuk membawa tag yang tidak Anda miliki yang ada di dalam komit yang Anda bawa. (Lihat hasil edit Januari 2017). Tetapi ada juga gangguan di sini, dan Git modern memiliki --tags / --no-tag menangani kode direvisi lagi, yang mungkin akan mengarah ke kasus sudut yang lebih istimewa.
torek
1

Untuk checkout git tag, Anda akan menjalankan perintah berikut

git checkout tags/tag-name -b branch-name

misal seperti yang disebutkan di bawah ini.

 git checkout tags/v1.0 -b v1.0-branch

Untuk mengambil semua tag gunakan perintah

git fetch --all --tags
mani
sumber
0

Untuk mendapatkan kode tag khusus, coba buat cabang baru, tambah dapatkan kode tag di dalamnya. Saya telah melakukannya dengan perintah:$git checkout -b newBranchName tagName

Rahul Khatri
sumber