(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/stash
adalah 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_HEAD
khususnya semua juga nama-nama yang mungkin merujuk kepada komit tertentu (meskipun HEAD
biasanya berisi nama cabang, yaitu, mengandung ). Tetapi secara umum, referensi dimulai dengan .ref: refs/heads/branch
refs/
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 fetch
dan push
operasi. Anda juga dapat menggunakan git ls-remote
atau git remote show
melihat mereka, tetapi fetch
dan push
adalah poin lebih menarik kontak.
Refspec
Selama fetch
dan 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 fetch
mengarahkan 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 origin
cabang '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 --tags
memiliki 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 --tags
secara 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 origin
memiliki tag xyzzy
, dan Anda tidak, dan Anda git fetch origin "refs/tags/*:refs/tags/*"
, Anda refs/tags/xyzzy
ditambahkan 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 --tags
opsi atau --no-tags
opsi, git fetch
mengambil 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 fetch
sedang memeriksa, Git Anda menambahkan T ke tag Anda dengan atau tanpa --tags
. Menambahkan --tags
menyebabkan Git Anda mendapatkan semua tag mereka, dan juga memaksa pembaruan.
Intinya
Anda mungkin harus menggunakan git fetch --tags
untuk 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 fetch
akan 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 gitrevisions
dokumentasi . Git akan menyelesaikan nama ke ID komit menggunakan urutan enam langkah yang diberikan dalam tautan. Anehnya, tag menimpa cabang: jika ada tag xyzzy
dan 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 checkout
lebih suka nama cabang, jadi Anda git checkout xyzzy
akan ditempatkan di cabang, mengabaikan tag.
Dalam hal ambiguitas, Anda hampir selalu bisa mengeja nama ref menggunakan nama lengkapnya, refs/heads/xyzzy
atau refs/tags/xyzzy
. (Catatan bahwa ini tidak bekerja dengan git checkout
, tetapi dalam cara yang mungkin tak terduga: git checkout refs/heads/xyzzy
menyebabkan checkout terpisah-KEPALA daripada checkout cabang Inilah sebabnya mengapa Anda hanya perlu catatan itu. git checkout
Akan menggunakan nama pendek sebagai nama cabang pertama: itulah bagaimana Anda periksa cabang xyzzy
bahkan jika tag xyzzy
ada. Jika Anda ingin memeriksa tag, Anda dapat menggunakan refs/tags/xyzzy
.)
Karena (sebagai gitrevisions
catatan) 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/name
tags/xyzzy
xyzzy
xyzzy
$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 fetch
dan 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.
git checkout A
. apaA
? Bagaimana cara Anda membuatA
?