“ git fetch --tags” รวมถึง“ git fetch” หรือไม่


270

คำถามที่ดีและเรียบง่าย - ฟังก์ชั่นของ "git fetch" เป็นชุดย่อยที่เข้มงวดgit fetch --tagsหรือไม่?

คือถ้าฉันวิ่งgit fetch --tagsจะมีเหตุผลgit fetchอะไรไหมที่จะวิ่งตรงต่อไปทันที?

สิ่งที่เกี่ยวกับgit pullและgit pull --tags? สถานการณ์เดียวกัน


11
เริ่มต้น Git 1..9 / 2.0 (ไตรมาสที่ 1 ปี 2014) คำตอบจะใช่ ดูคำตอบของฉันด้านล่าง
VonC

3
ถึงบรรณาธิการที่ "แก้ไขข้อความของฉัน" ด้วยการแก้ไข - ไม่จำเป็นต้องใช้ตัวพิมพ์ใหญ่หลังจากยัติภังค์หรือตัวย่อดังนั้นการแก้ไขของคุณจึงไม่ถูกต้องตามหลักไวยากรณ์ซึ่งเป็นสาเหตุที่ฉันปฏิเสธ
davidA

คำตอบ:


176

หมายเหตุ: การเริ่มต้นด้วยคอมไพล์ 1.9 / 2.0 (ไตรมาสที่ 1 ปี 2014) , git fetch --tagsเรียกแท็กนอกเหนือไปจากสิ่งที่เป็นความจริงโดยบรรทัดคำสั่งเดียวกันโดยไม่เลือกที่

ดูคอมมิชชัน c5a84e9โดยMichael Haggerty (mhagger) :

ก่อนหน้านี้--tagsตัวเลือกของการดึงข้อมูลถือเป็นค่าเทียบเท่ากับการระบุตัวอ้างอิง

refs/tags/*:refs/tags/*

บนบรรทัดคำสั่ง โดยเฉพาะอย่างยิ่งทำให้การremote.<name>.refspecกำหนดค่าจะถูกละเว้น

แต่มันไม่ได้มีประโยชน์มากในการดึงข้อมูลแท็กโดยไม่ได้เรียกอ้างอิงอื่น ๆ ในขณะที่มันเป็นประโยชน์มากที่จะสามารถดึงข้อมูลแท็กที่นอกเหนือไปจากการอ้างอิงอื่น ๆ
ดังนั้นเปลี่ยนซีแมนทิกส์ของตัวเลือกนี้ให้ทำหลัง

หากผู้ใช้ต้องการที่จะดึงแท็กเท่านั้นก็ยังเป็นไปได้ที่จะระบุการอ้างอิงอย่างชัดเจน:

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

โปรดทราบว่าเอกสารก่อน 1.8.0.3 นั้นไม่ชัดเจนเกี่ยวกับfetch --tagsพฤติกรรมของ " "
กระทำ f0cb2f1 (2012-12-14) fetch --tagsทำให้เอกสารตรงกับพฤติกรรมเก่า
การกระทำนี้เปลี่ยนเอกสารเพื่อให้ตรงกับพฤติกรรมใหม่ (ดูDocumentation/fetch-options.txt)

ขอให้ดึงแท็กทั้งหมดจากระยะไกลเพิ่มเติมจากสิ่งอื่นที่ถูกดึงออกมา


ตั้งแต่ Git 2.5 (Q2 2558) git pull --tagsแข็งแกร่งกว่า:

ดูคอมมิชชั่น 19d122bโดยPaul Tan ( pyokagan) , 13 พฤษภาคม 2558
(ผสานโดยJunio ​​C Hamano - gitster-ในคอมมิชชัน cc77b99 , 22 พฤษภาคม 2558)

pull: ลบ--tagsข้อผิดพลาดในกรณีที่ไม่มีผู้สมัครผสาน

ตั้งแต่441ed41 (" git pull --tags": ข้อผิดพลาดออกมาพร้อมกับข้อความที่ดีกว่า, 2007-12-28, Git 1.5.4+) git pull --tagsจะพิมพ์ข้อความแสดงข้อผิดพลาดที่แตกต่างกันหาก git-fetchไม่ได้คืนผู้สมัครผสาน:

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

เนื่องจากในขณะนั้นgit-fetch --tagsจะแทนที่ refspecs ที่กำหนดค่าไว้และดังนั้นจึงไม่มีผู้สมัครผสาน ข้อความแสดงข้อผิดพลาดจึงถูกนำมาใช้เพื่อป้องกันความสับสน

อย่างไรก็ตามตั้งแต่c5a84e9 (fetch --tags : ดึงแท็กนอกเหนือจาก สิ่งอื่น ๆ 2013-10-30, Git 1.9.0+) git fetch --tagsจะดึงแท็กนอกเหนือจากผู้อ้างอิงที่กำหนดค่าไว้
ดังนั้นหากมีสถานการณ์ที่ไม่มีผู้สมัครผสานเกิดขึ้นนั่นไม่ใช่เพราะ--tagsถูกตั้งค่าไว้ ดังนั้นข้อความแสดงข้อผิดพลาดพิเศษนี้จึงไม่เกี่ยวข้อง

เพื่อป้องกันความสับสนให้ลบข้อความแสดงข้อผิดพลาดนี้


ด้วย Git 2.11+ (Q4 2016) git fetchนั้นเร็วกว่า

ดูกระทำ 5827a03 (13 ตุลาคม 2016) โดยเจฟฟ์คิง (peff )
ผสานโดยJunio ​​C Hamano - gitster- in 9fcd144 , 26 Oct 2016)

fetch: ใช้ "ด่วน" has_sha1_fileสำหรับการติดตามแท็ก

เมื่อดึงข้อมูลจากระยะไกลที่มีแท็กจำนวนมากที่ไม่เกี่ยวข้องกับสาขาที่เราติดตามเราเคยเสียวงจรมากเกินไปเมื่อตรวจสอบว่าวัตถุที่ชี้ไปที่แท็ก (ว่าเราจะไม่เรียก!) มีอยู่ในพื้นที่เก็บข้อมูลของเรา อย่างระมัดระวังเกินไป

แพทช์นี้สอนการดึงข้อมูลเพื่อใช้ HAS_SHA1_QUICK เพื่อเสียสละความแม่นยำสำหรับความเร็วในกรณีที่เราอาจมีชีวิตชีวาด้วยการบรรจุใหม่พร้อมกัน

นี่คือผลลัพธ์จากสคริปต์ perf ที่รวมอยู่ซึ่งตั้งค่าสถานการณ์คล้ายกับที่อธิบายข้างต้น:

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

สิ่งนั้นใช้สำหรับสถานการณ์ที่:

  1. คุณมีชุดจำนวนมากที่ฝั่งไคลเอ็นต์เพื่อทำให้reprepare_packed_git()มีราคาแพง (ส่วนที่แพงที่สุดคือการค้นหารายการที่ซ้ำกันในรายการที่ไม่เรียงลำดับซึ่งเป็นกำลังสองกำลังสอง)
  2. คุณต้องมีการอ้างอิงแท็กจำนวนมากในฝั่งเซิร์ฟเวอร์ที่เป็นตัวเลือกสำหรับการติดตามอัตโนมัติ (เช่นที่ลูกค้าไม่มี) แต่ละอันจะทริกเกอร์การอ่านไดเรกทอรีแพ็คอีกครั้ง
  3. ภายใต้สถานการณ์ปกติลูกค้าจะติดตามแท็กเหล่านั้นโดยอัตโนมัติและหลังจากการดึงครั้งใหญ่ครั้งหนึ่ง (2) จะไม่เป็นจริงอีกต่อไป
    แต่ถ้าแท็กเหล่านั้นชี้ไปที่ประวัติซึ่งถูกตัดการเชื่อมต่อจากสิ่งที่ลูกค้าเรียกมาแท็กเหล่านั้นจะไม่ติดตามอัตโนมัติและผู้สมัครเหล่านั้นจะส่งผลกระทบต่อทุกการเรียก

Git 2.21 (กุมภาพันธ์ 2019) ดูเหมือนว่าจะมีการแนะนำให้รู้จักการถดถอยเมื่อตั้งค่าremote.origin.fetchเป็นไม่ได้หนึ่งเริ่มต้น ( '+refs/heads/*:refs/remotes/origin/*')

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

Git 2.24 (Q4 2019) เพิ่มการเพิ่มประสิทธิภาพอื่น

ดูกระทำ b7e2d8b (15 กันยายน 2019) โดยมาซายะซูซูกิ (draftcode )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 1d8b0df , 7 ตุลาคม 2019)

fetch: ใช้oidsetเพื่อรักษา OID ที่ต้องการเพื่อการค้นหาที่รวดเร็วขึ้น

ระหว่างgit fetchนั้นลูกค้าจะตรวจสอบว่า OID ของแท็กที่โฆษณานั้นมีอยู่แล้วในชุดการร้องขอการดึงข้อมูลของคำขอดึงข้อมูล
การตรวจสอบนี้ทำในการสแกนเชิงเส้น
สำหรับพื้นที่เก็บข้อมูลที่มีจำนวนมากอ้างอิงซ้ำการสแกนนี้ใช้เวลา 15+ นาที

เพื่อเร่งความเร็วให้สร้างoid_setสำหรับ OID ผู้อ้างอิงคนอื่น


หัวข้อนี้ใน git-list กล่าวถึงความเป็นไปได้ในการแก้ไขพฤติกรรมของgit fetch <remote> <branch>แท็กที่ติดตามอัตโนมัติ (เนื่องจากมีการอัปเดตการติดตามระยะไกลแล้วจากความตั้งใจดั้งเดิม): public-inbox.org/git/…
ankostis

@ankostis น่าสนใจ: ดังที่ Junio ​​กล่าวถึงในpublic-inbox.org/git/… , "การกลับไปสู่พฤติกรรมเดิมอาจเป็นทางเลือกหนึ่งในการแก้ไขปัญหาที่กล่าวถึงในหัวข้อนี้" (แต่จะไม่: public-inbox.org/git/… )
VonC

เป็นไปได้ไหมที่ Git จะเปิดเผยความซับซ้อนที่ไม่จำเป็นกับผู้ใช้ปลายทางโดยต้องการคำสั่งทางไวยากรณ์ที่หนักหน่วงจนถึงจุดที่คล้ายกับแฮ็กเพื่อดำเนินการทั่วไป ฉันยังคิดว่าภายในไม่เพียงพอที่จะต้องมีความรู้
จอห์น Fantastico

1
@ JohnFantastico ฉันเข้าใจมุมมองนั้นได้ ฉันได้เห็นว่าก่อน: news.ycombinator.com/item?id=16587496 หรือhackernoon.com/… ("คำสั่ง Git เป็นเพียงนามธรรมที่รั่วไหลกว่าที่เก็บข้อมูล")
VonC

1
@Vadorequest ขอบคุณ ฉันได้อัปเดตคำตอบแล้วและจะคอยดูรายชื่อผู้รับจดหมาย: public-inbox.org/git/?q=fetch
VonC

131

หมายเหตุ: คำตอบนี้ใช้ได้สำหรับ git v1.8 และเก่ากว่าเท่านั้น

สิ่งเหล่านี้ส่วนใหญ่ได้รับการกล่าวถึงในคำตอบและความคิดเห็นอื่น ๆ แต่นี่เป็นคำอธิบายสั้น ๆ :

  • git fetchดึงส่วนหัวสาขาทั้งหมด (หรือทั้งหมดที่ระบุโดยตัวเลือกการกำหนดค่า remote.fetch) กระทำทั้งหมดที่จำเป็นสำหรับพวกเขาและแท็กทั้งหมดที่สามารถเข้าถึงได้จากสาขาเหล่านี้ ในกรณีส่วนใหญ่แท็กทั้งหมดสามารถเข้าถึงได้ด้วยวิธีนี้
  • git fetch --tagsดึงแท็กทั้งหมดทั้งหมดที่จำเป็นสำหรับแท็กเหล่านั้น จะไม่อัปเดตหัวสาขาแม้ว่าจะสามารถเข้าถึงได้จากแท็กที่ดึงมาแล้ว

สรุป: หากคุณต้องการอัพเดททั้งหมดโดยใช้การดึงข้อมูลเท่านั้นคุณต้องทำทั้งสองอย่าง

นอกจากนี้ยังไม่ "ช้าเป็นสองเท่า" เว้นแต่คุณจะหมายถึงการพิมพ์บนบรรทัดคำสั่งซึ่งในกรณีนี้นามแฝงจะแก้ปัญหาของคุณ ไม่มีค่าใช้จ่ายในการทำคำขอทั้งสองเนื่องจากพวกเขาจะขอข้อมูลที่แตกต่างกัน


2
ขอบคุณสำหรับความคิดเห็นของคุณ ฉันใช้คอมไพล์ใน Cygwin ผ่านเครือข่ายความหน่วงสูง - มันช้าเป็นสองเท่าเมื่อไม่มีอะไรมาดึง (ประมาณ 5 วินาที)
davidA

โอ้ว้าว. ระบบ git-remote ทำงานได้ดีขึ้นหรือไม่? ดูที่แหล่งข้อมูลสั้น ๆ ฉันคิดว่ามันอาจจะโทรเพียงครั้งเดียว - แต่ฉันไม่แน่ใจว่ามันจะคว้าแท็กที่ไม่ได้อยู่ในสาขา สุจริตฉันไม่รู้ว่าฉันเคยเห็นแท็กใด ๆ ที่ไม่ได้อยู่ในสาขา ด้วยสิ่งที่ฉันดึงมาวิธีเดียวที่จะเกิดขึ้นหากฉันรอมานานจนฉันพลาดการบำรุงรักษารุ่นการเปิดตัวคุณลักษณะและการหยุดการบำรุงรักษารุ่นเก่า
คาสคาเบล

ฉันคิดว่าปัญหาคือ 'เรียก git' ดึงแท็กในสาขาที่ถูกติดตามเท่านั้น เรามีสคริปต์ที่ช่วยให้ผู้ใช้สามารถเลือกสาขาที่ใช้งานได้ดังนั้นโดยค่าเริ่มต้นมีหลายสาขาที่ไม่ได้ถูกติดตามโดยบุคคลในปัจจุบัน
davidA

ฉันยังไม่ได้ลอง git-remote แต่อยู่ในรายการที่ต้องทำของฉัน :)
Davida

7
โปรดทราบว่าgit remote updateไม่จริงทดแทนและ git fetch จะไม่อัปเดตแท็กที่มีอยู่ซึ่งมีการเปลี่ยนแปลงแม้ว่าจะนำแท็กใหม่มาด้วย เพียง แต่จะมีการปรับปรุงแท็กที่มีอยู่แล้ว git fetch --tagsgit remote updategit fetch --tags
larsks

48

ฉันจะตอบคำถามนี้ด้วยตัวเอง

ฉันตัดสินใจแล้วว่ามีความแตกต่าง "git fetch --tags" อาจนำแท็กทั้งหมดมาใช้ แต่จะไม่นำมาใช้ใหม่!

กลายเป็นสิ่งที่เราต้องทำเพื่อให้เป็น "ทันสมัย" โดยสิ้นเชิงคือการทำซ้ำ "git pull" โดยไม่ต้องรวม:

$ git fetch --tags
$ git fetch

นี่เป็นความอัปยศเพราะมันช้าเป็นสองเท่า หากมีเพียง "git fetch" เท่านั้นที่มีตัวเลือกให้ทำสิ่งที่มันทำตามปกติและนำแท็กทั้งหมดมาด้วย


ที่น่าสนใจฉันไม่ได้มีประสบการณ์ที่ (อาจเป็นเพราะ repo ของฉันเป็นปัจจุบันในช่วงเวลาของการทดสอบของฉัน) +1
VonC

1
วิธีการเกี่ยวกับ ' git remote update myRemoteRepo': จะดึงเนื้อหาและแท็กระยะไกลหรือไม่
VonC

1
ฉันทำgit fetchตลอดเวลาและจะดึงข้อผูกพันใหม่และแท็กใหม่ ๆ คุณใช้ Git เวอร์ชันใด
Tim Visher

4
FTR 'การอัปเดต git จากระยะไกล myRemoteRepo' ทำงานได้ไม่ดี - ดูเหมือนจะไม่ทำในสิ่งที่ 'git fetch && git fetch --tags' ทำได้โดยเฉพาะอย่างยิ่งเมื่อการรวมภายหลังไม่มีผล
davidA

1
@TimVisher git fetchจะไม่จับแท็กที่ไม่ได้อยู่ในบันทึกการกระทำของสาขา jQuery UI ทำเช่นนี้บนแท็กเผยแพร่ เราทำgit checkout -b temp-branch, ทำรีลีสของเรา, เพิ่มไฟล์ที่จำเป็นสำหรับรีลีส, อัพเดตเวอร์ชั่น ฯลฯ จากgit commit -m "1.10.x" ; git tag 1.10.x; git push --tagsนั้นเราจะลบสาขาชั่วคราวของเรา ไม่มีสาขาระยะไกลที่มาถึงแท็กนั้นและgit fetchจะไม่ดาวน์โหลดเลย
แคระ

31

ปัญหาทั่วไปที่นี่เป็นที่จะเรียกgit fetch +refs/heads/*:refs/remotes/$remote/*หากการกระทำเหล่านี้มีแท็กแท็กเหล่านั้นจะถูกดึงข้อมูล อย่างไรก็ตามหากมีแท็กที่ไม่สามารถเข้าถึงได้โดยสาขาใด ๆ บนรีโมทพวกเขาจะไม่สามารถดึงข้อมูลได้

--tagsตัวเลือกสวิทช์ refspec +refs/tags/*:refs/tags/*ไป คุณสามารถขอgit fetchให้จับทั้งสอง ฉันค่อนข้างมั่นใจว่าgit fetch && git fetch -tคุณจะใช้คำสั่งต่อไปนี้:

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

และถ้าคุณต้องการให้ค่าเริ่มต้นสำหรับ repo นี้คุณสามารถเพิ่ม refspec ตัวที่สองในการดึงข้อมูลเริ่มต้น:

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

นี่จะเพิ่มfetch =บรรทัดที่สองใน.git/configสำหรับรีโมทนี้


ฉันใช้เวลาซักพักหนึ่งเพื่อหาวิธีจัดการกับโครงการนี้ นี่คือสิ่งที่ฉันมาด้วย

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

ในกรณีของฉันฉันต้องการคุณสมบัติเหล่านี้

  • หยิบหัวและแท็กทั้งหมดจากรีโมทเพื่อใช้ refspec refs/*:refs/*
  • เขียนทับสาขาและแท็กท้องถิ่นด้วยการไม่ส่งต่ออย่างรวดเร็ว +ก่อนที่จะมีการอ้างอิง
  • เขียนทับสาขาที่เช็คเอาท์หากจำเป็น -u
  • ลบสาขาและแท็กที่ไม่ได้อยู่ในระยะไกล -p
  • และบังคับให้ถูกต้องแน่นอน -f

นี่ควรเป็นคำตอบ
redolent

+1 สำหรับ " --tagsตัวเลือกจะเปลี่ยน refspec เป็น+refs/tags/*:refs/tags/*" แม้ว่า, man git-fetchดูเหมือนว่าจะระบุ refspec ที่ไม่มีส่วนนำหน้า+( refs/tags/*:refs/tags/*)
Dmitry Minkovsky

remote.origin.fetchค่าเริ่มต้น +refs/heads/*:refs/remotes/origin/*คือ+เวอร์ชันใช่ไหม (ซึ่งหมายความว่าที่มา / สาขาจะถูกเขียนทับไม่ว่าที่มา / สาขาอยู่ที่ใดในขณะนี้)
Robert Siemer

... และในขณะที่เขียนล่าสุดgit --tagsมีการดึงแท็กนอกเหนือจากทุกอย่างแล้ว ดูคำตอบของ @VonC
Robert Siemer

10

ในสถานการณ์ส่วนใหญ่git fetchควรทำในสิ่งที่คุณต้องการซึ่งเป็น 'รับสิ่งใหม่ ๆ จากที่เก็บระยะไกลและวางไว้ในสำเนาในเครื่องของคุณโดยไม่ต้องรวมกับสาขาท้องถิ่นของคุณ' git fetch --tagsทำเช่นนั้นยกเว้นว่าจะไม่ได้รับอะไรนอกจากแท็กใหม่

ในความรู้สึกที่git fetch --tagsอยู่ในทางที่ superset git fetchของ มันเป็นความจริงตรงกันข้าม

git pullของหลักสูตรคืออะไร git fetch <thisrefspec>; git mergeแต่เสื้อคลุมสำหรับเป็น ขอแนะนำให้คุณทำความคุ้นเคยกับการทำgit fetchไอเอ็นgit mergeจีด้วยตัวเองก่อนที่จะข้ามไปgit pullเพียงเพราะช่วยให้คุณเข้าใจสิ่งที่git pullกำลังทำอยู่ในตอนแรก

git fetchที่ถูกกล่าวว่าความสัมพันธ์เป็นเหมือนกันเช่นเดียวกับ เป็นเซ็ตของgit pullgit pull --tags


1
"git pull คือ superset ของ git pull --tags" - แต่ ... 'git fetch' ไม่ใช่ superset ของ 'git fetch --tags' ดังนั้นความสัมพันธ์จึงไม่เหมือนกัน ... ?
davidA

9
เพิ่งพบคำถามนี้ ... ดีดูเหมือนว่าฉันgit pullจะไม่ได้รับแท็กทั้งหมดแต่เฉพาะที่สามารถเข้าถึงได้จากหัวสาขาปัจจุบัน แต่เรียกแท็กทั้งหมดและเห็นได้ชัดคือเทียบเท่ากับgit pull --tags git fetch --tags
Archimedix

2
git fetch upstream --tags

ทำงานได้ดีมันจะได้รับแท็กใหม่เท่านั้นและจะไม่ได้รับรหัสฐานอื่น ๆ


1
upstreamoriginเรียกว่าตามปกติ ฉันคิดว่าupstreamเป็นชื่อที่ใช้โดย GitHub ในกรณีใด ๆ git remoteชื่อเพื่อใช้เป็นหนึ่งที่แสดงโดย
ฟาบิโอพูดว่า Reinstate Monica เมื่อ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.