Apakah "git fetch --tags" termasuk "git fetch"?

270

Pertanyaan yang bagus dan sederhana - apakah fungsi "git fetch" adalah sub-set yang ketat git fetch --tags?

Yaitu kalau saya lari git fetch --tags, adakah alasan untuk segera lari git fetchlurus sesudahnya?

Bagaimana dengan git pulldan git pull --tags? Situasi yang sama?

davidA
sumber
11
Mulai Git 1..9 / 2.0 (Q1 2014), jawabannya adalah ya . Lihat jawaban saya di bawah ini
VonC
3
Kepada editor yang "mengoreksi teks saya" dengan suntingan - orang tidak harus menggunakan huruf kapital setelah tanda hubung atau akronim, jadi pengeditan Anda secara tata bahasa salah, itulah sebabnya saya menolaknya.
davidA

Jawaban:

176

Catatan: dimulai dengan git 1.9 / 2.0 (Q1 2014) , git fetch --tagsmengambil tag di samping apa yang diambil oleh baris perintah yang sama tanpa opsi.

Lihat commit c5a84e9 oleh Michael Haggerty (mhagger) :

Sebelumnya, pilihan fetch --tagsdianggap setara dengan menentukan refspec

refs/tags/*:refs/tags/*

di baris perintah; khususnya, itu menyebabkan remote.<name>.refspeckonfigurasi diabaikan.

Tapi itu tidak sangat berguna untuk mengambil tag tanpa juga mengambil referensi lain, padahal ini sangat berguna untuk dapat mengambil tag di samping referensi lain.
Jadi ubah semantik opsi ini untuk melakukan yang terakhir.

Jika seorang pengguna ingin mengambil hanya tag, maka masih mungkin untuk menentukan sebuah refspec eksplisit:

git fetch <remote> 'refs/tags/*:refs/tags/*'

Harap perhatikan bahwa dokumentasi sebelum 1.8.0.3 tidak jelas tentang aspek fetch --tagsperilaku ini.
Commit f0cb2f1 (2012-12-14) fetch --tagsmenjadikan dokumentasi tersebut cocok dengan perilaku lama.
Komit ini mengubah dokumentasi agar sesuai dengan perilaku baru (lihat Documentation/fetch-options.txt).

Minta agar semua tag diambil dari jarak jauh selain apa pun yang sedang diambil .


Karena Git 2.5 (Q2 2015) git pull --tagslebih kuat:

Lihat komit 19d122b oleh Paul Tan ( pyokagan) , 13 Mei 2015.
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit cc77b99 , 22 Mei 2015)

pull: hapus --tagskesalahan dalam kasus tidak ada kandidat gabungan

Sejak 441ed41 (" git pull --tags": galat dengan pesan yang lebih baik., 2007-12-28, Git 1.5.4+), git pull --tagsakan mencetak pesan galat yang berbeda jika git-fetchtidak mengembalikan kandidat gabungan:

It doesn't make sense to pull all tags; you probably meant:
       git fetch --tags

Ini karena pada saat itu, git-fetch --tagsakan menimpa refspec yang dikonfigurasi, dan dengan demikian tidak akan ada kandidat gabungan. Pesan kesalahan dengan demikian diperkenalkan untuk mencegah kebingungan.

Namun, karena c5a84e9 ( fetch --tags: ambil tag di samping hal-hal lain, 2013-10-30, Git 1.9.0+), git fetch --tagsakan mengambil tag di samping setiap refspec yang dikonfigurasi.
Oleh karena itu, jika ada situasi tidak ada kandidat yang bergabung, itu bukan karena --tagsditetapkan. Dengan demikian, pesan kesalahan khusus ini sekarang tidak relevan.

Untuk mencegah kebingungan, hapus pesan kesalahan ini.


Dengan Git 2.11+ (Q4 2016) git fetchlebih cepat.

Lihat komit 5827a03 (13 Okt 2016) oleh Jeff King ( peff) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 9fcd144 , 26 Okt 2016)

fetch: gunakan "cepat" has_sha1_fileuntuk mengikuti tag

Ketika mengambil dari remote yang memiliki banyak tag yang tidak relevan dengan cabang yang kita ikuti, kita dulu membuang terlalu banyak siklus ketika memeriksa apakah objek diarahkan oleh tag (yang tidak akan kita ambil!) Ada di repositori kami terlalu hati-hati.

Patch ini mengajarkan cara menggunakan HAS_SHA1_QUICK untuk mengorbankan akurasi demi kecepatan, dalam kasus di mana kita mungkin bersemangat dengan pengemasan ulang secara simultan.

Berikut adalah hasil dari skrip perf yang disertakan, yang mengatur situasi yang mirip dengan yang dijelaskan di atas:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

Itu hanya berlaku untuk situasi di mana:

  1. Anda memiliki banyak paket di sisi klien untuk menghasilkan reprepare_packed_git()mahal (bagian paling mahal adalah menemukan duplikat dalam daftar yang tidak disortir, yang saat ini kuadratik).
  2. Anda memerlukan sejumlah besar tag referensi di sisi server yang merupakan kandidat untuk mengikuti otomatis (yaitu, yang tidak dimiliki klien). Masing-masing memicu membaca kembali direktori paket.
  3. Dalam keadaan normal, klien akan mengikuti tag itu secara otomatis dan setelah mengambil satu jumlah besar, (2) tidak lagi benar.
    Tetapi jika tag-tag itu menunjuk pada sejarah yang terputus dari apa yang dijemput oleh klien, maka itu tidak akan pernah secara otomatis mengikuti, dan para kandidat itu akan berdampak pada setiap pengambilan.

Git 2.21 (Februari 2019) tampaknya telah memperkenalkan regresi ketika config remote.origin.fetchadalah tidak satu standar ( '+refs/heads/*:refs/remotes/origin/*')

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed

Git 2.24 (Q4 2019) menambahkan optimasi lain.

Lihat commit b7e2d8b (15 Sep 2019) oleh Masaya Suzuki ( draftcode) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam commit 1d8b0df , 07 Okt 2019)

fetch: gunakan oidsetuntuk menjaga OID yang diinginkan agar pencarian lebih cepat

Selama git fetch, klien memeriksa apakah OID tag yang diiklankan sudah dalam permintaan pengambilan yang ingin OID atur.
Pemeriksaan ini dilakukan dalam pemindaian linier.
Untuk repositori yang memiliki banyak referensi, mengulangi pemindaian ini membutuhkan waktu 15 menit lebih.

Untuk mempercepat ini, buat oid_setOID referensi lain.

VONC
sumber
Utas ini di git-list membahas kemungkinan untuk mengubah perilaku git fetch <remote> <branch>untuk mengikuti tag otomatis (karena sudah memperbarui pelacakan jarak jauh MELAWAN niat asli): public-inbox.org/git/…
ankostis
@ankostis Menarik: seperti yang disebutkan Junio ​​di public-inbox.org/git/… , "kembali ke perilaku lama mungkin menjadi salah satu opsi untuk mengatasi masalah yang sedang dibahas di utas ini." (tetapi mereka tidak akan: public-inbox.org/git/… )
VonC
Apakah mungkin bagi Git untuk mengekspos kompleksitas yang lebih tidak perlu kepada pengguna akhir, membutuhkan perintah sintaksis yang berat hingga menyerupai hack untuk melakukan operasi umum? Saya pikir belum cukup pengetahuan internal yang dibutuhkan.
John Fantastico
1
@ JohnFantastico Saya bisa mengerti sudut pandang itu. Saya telah melihat itu sebelumnya: news.ycombinator.com/item?id=16587496 . Atau hackernoon.com/… ("Perintah Git hanyalah abstraksi yang bocor atas penyimpanan data.")
VonC
1
@Vadorequest Terima kasih. Saya telah memperbarui jawabannya dan akan terus melihat ke milis: public-inbox.org/git/?q=fetch
VonC
131

Catatan: jawaban ini hanya berlaku untuk git v1.8 dan lebih lama.

Sebagian besar ini telah dikatakan dalam jawaban dan komentar lain, tetapi inilah penjelasan singkatnya:

  • git fetchmengambil semua kepala cabang (atau semua yang ditentukan oleh opsi konfigurasi remote.fetch), semua melakukan yang diperlukan untuk mereka, dan semua tag yang dapat dijangkau dari cabang-cabang ini. Dalam kebanyakan kasus, semua tag dapat dijangkau dengan cara ini.
  • git fetch --tagsmengambil semua tag, semua komitmen diperlukan untuk mereka. Itu tidak akan memperbarui kepala cabang, bahkan jika mereka dapat dijangkau dari tag yang diambil.

Ringkasan: Jika Anda benar-benar ingin mendapatkan informasi terkini, hanya menggunakan pengambilan, Anda harus melakukan keduanya.

Ini juga tidak "dua kali lebih lambat" kecuali jika Anda bermaksud mengetikkan perintah-baris, dalam hal ini alias memecahkan masalah Anda. Pada dasarnya tidak ada overhead dalam membuat dua permintaan, karena mereka meminta informasi yang berbeda.

Cascabel
sumber
2
Terima kasih atas komentar Anda. Saya menjalankan git di Cygwin melalui jaringan latensi tinggi - dua kali lebih lambat ketika tidak ada yang perlu diambil (sekitar 5 detik).
davidA
Oh wow. Apakah git-remote berfungsi lebih baik? Melihat sumbernya sebentar, saya pikir itu mungkin hanya membuat satu panggilan - tapi saya tidak sepenuhnya yakin apakah itu akan mengambil tag tidak-cabang. Jujur saya tidak tahu apakah saya pernah melihat tag tidak pada cabang. Dengan hal-hal yang saya tarik dari, satu-satunya cara yang akan terjadi jika saya menunggu begitu lama sehingga saya melewatkan rilis pemeliharaan, rilis fitur, dan penghentian pemeliharaan rilis lama.
Cascabel
Saya pikir masalahnya adalah bahwa 'git fetch' hanya mengambil tag pada cabang yang dilacak . Kami memiliki skrip yang memungkinkan pengguna untuk memilih cabang yang berfungsi, jadi secara default ada banyak cabang yang saat ini tidak dilacak oleh seorang individu.
davidA
Saya belum mencoba git-jauh, tapi itu pada saya terus tumbuh ke-do list :)
Davida
7
Perhatikan bahwa git remote updatesebenarnya bukan pengganti untuk git fetchdan git fetch --tags. git remote updatetidak akan memperbarui tag yang ada yang telah berubah, meskipun akan membawa tag baru. Hanya git fetch --tagsakan memperbarui tag yang sudah ada.
larsks
48

Saya akan menjawab ini sendiri.

Saya telah menentukan bahwa ada perbedaan. "git fetch --tags" mungkin membawa semua tag, tetapi itu tidak menghasilkan komitmen baru!

Ternyata seseorang harus melakukan ini agar benar-benar "terkini", yaitu mereplikasi "git pull" tanpa penggabungan:

$ git fetch --tags
$ git fetch

Ini memalukan, karena ini dua kali lebih lambat. Andai saja "git fetch" memiliki opsi untuk melakukan apa yang biasanya ia lakukan dan membawa semua tag.

davidA
sumber
Menarik, saya tidak mengalami itu (mungkin karena repo saya up to date pada saat ujian saya.) +1
VonC
1
Bagaimana dengan ' git remote update myRemoteRepo': apakah itu akan mengambil konten dan tag jarak jauh ?
VonC
1
Saya melakukan git fetchsemua waktu dan secara konsisten menarik setiap komitmen baru dan tag baru. Git versi apa yang Anda jalankan?
Tim Visher
4
FTR, 'git remote update myRemoteRepo' tidak berfungsi dengan baik - sepertinya tidak melakukan apa yang 'git fetch && git fetch - tag' lakukan, terutama karena penggabungan berikutnya tidak berpengaruh.
davidA
1
@TimVisher git fetchtidak akan mengambil tag yang tidak ada di log komit cabang. Misalnya jQuery UI melakukan ini pada tag rilis. Kami melakukan git checkout -b temp-branch, melakukan rilis kami, menambahkan file yang diperlukan untuk rilis, memperbarui versi, dll, git commit -m "1.10.x" ; git tag 1.10.x; git push --tagslalu kami menghapus cabang temp lokal kami. Tidak ada cabang jarak jauh yang mencapai tag itu, dan git fetchtidak akan pernah mengunduhnya.
gnarf
31

Masalah umum di sini adalah yang git fetchakan diambil +refs/heads/*:refs/remotes/$remote/*. Jika salah satu dari komit ini memiliki tag, tag tersebut juga akan diambil. Namun, jika ada tag yang tidak dapat dijangkau oleh cabang mana pun di remote, mereka tidak akan diambil.

The --tagspilihan switch refspec untuk +refs/tags/*:refs/tags/*. Anda bisa meminta git fetchuntuk mengambil keduanya. Saya cukup yakin hanya melakukan git fetch && git fetch -tAnda akan menggunakan perintah berikut:

git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"

Dan jika Anda ingin menjadikan ini sebagai standar untuk repo ini, Anda dapat menambahkan refspec kedua ke pengambilan default:

git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"

Ini akan menambahkan fetch =baris kedua .git/configuntuk remote ini.


Saya menghabiskan waktu mencari cara untuk menangani proyek ini. Inilah yang saya pikirkan.

git fetch -fup origin "+refs/*:refs/*"

Dalam kasus saya, saya ingin fitur ini

  • Raih semua kepala dan tag dari jarak jauh jadi gunakan refspec refs/*:refs/*
  • Timpa cabang dan tag lokal dengan non-fast-forward +sebelum refspec
  • Timpa cabang yang sekarang dicek jika diperlukan -u
  • Hapus cabang dan tag yang tidak ada di jarak jauh -p
  • Dan paksa untuk memastikan -f
gnarf
sumber
Ini seharusnya jawabannya.
Wangi
+1 untuk " --tagsOpsi mengalihkan refspec ke +refs/tags/*:refs/tags/*". Meskipun,, man git-fetchtampaknya menentukan refspec tanpa yang memimpin +( refs/tags/*:refs/tags/*).
Dmitry Minkovsky
remote.origin.fetchdefault untuk +refs/heads/*:refs/remotes/origin/*, yaitu +versi, bukan? (Itu artinya, asal / cabang akan ditimpa, tidak peduli di mana asal / cabang sekarang secara lokal.)
Robert Siemer
... dan pada saat penulisan, baru git --tags- baru ini sedang mengambil tag di samping yang lainnya. Lihat jawaban @VonC.
Robert Siemer
10

Dalam kebanyakan situasi, git fetchlakukan apa yang Anda inginkan, yaitu 'dapatkan sesuatu yang baru dari repositori jarak jauh dan letakkan di salinan lokal Anda tanpa bergabung ke cabang lokal Anda'. git fetch --tagstidak persis seperti itu, kecuali itu tidak mendapatkan apa-apa kecuali tag baru.

Dalam arti itu, git fetch --tagssama sekali bukan superset git fetch. Sebenarnya justru sebaliknya.

git pull, tentu saja, tidak lain adalah pembungkus untuk git fetch <thisrefspec>; git merge. Dianjurkan agar Anda terbiasa melakukan manual git fetchdan git mergeing sebelum Anda melakukan lompatan git pullhanya karena itu membantu Anda memahami apa git pullyang dilakukan di tempat pertama.

Konon, hubungannya persis sama dengan git fetch. git pulladalah superset dari git pull --tags.

Tim Visher
sumber
1
"git pull adalah superset dari git pull --tags" - tapi ... 'git fetch' bukan superset dari 'git fetch --tags' sehingga hubungannya tidak persis sama ...?
davidA
9
Hanya menemukan pertanyaan ini ... baik, tampaknya bagi saya bahwa git pulltidak tidak mendapatkan semua tag tetapi hanya mereka dicapai dari kepala cabang saat ini. Namun, git pull --tagsmengambil semua tag dan tampaknya setara dengan git fetch --tags.
Archimedix
2
git fetch upstream --tags

berfungsi dengan baik, itu hanya akan mendapatkan tag baru dan tidak akan mendapatkan basis kode lainnya.

Paand
sumber
1
upstreambiasa disebut origin. Saya pikir upstreamadalah nama yang digunakan oleh GitHub. Bagaimanapun, nama yang digunakan adalah yang ditunjukkan oleh git remote.
Fabio mengatakan Reinstate Monica