(คำตอบนี้ใช้เวลาสักครู่ในการเขียนและคำตอบของ codeWizardนั้นถูกต้องในจุดมุ่งหมายและสาระสำคัญ แต่ไม่สมบูรณ์ทั้งหมดดังนั้นฉันจะโพสต์สิ่งนี้ต่อไป)
ไม่มีสิ่งเช่น "แท็ก Git ระยะไกล" มี "แท็ก" เท่านั้น ผมชี้ออกทั้งหมดนี้ไม่ได้ที่จะอวดความรู้1แต่เนื่องจากมีการจัดการที่ดีของความสับสนเกี่ยวกับเรื่องนี้กับผู้ใช้ Git สบายและเอกสารที่ Git ไม่เป็นประโยชน์มาก2ที่จะเริ่มต้น (ไม่ชัดเจนว่าเกิดความสับสนเนื่องจากเอกสารที่ไม่ดีหรือเอกสารที่ไม่ดีมาเพราะสิ่งนี้ค่อนข้างสับสนหรืออะไร)
มีเป็น "สาขาระยะไกล" เรียกว่ามากขึ้นอย่างถูกต้อง "ระยะไกลติดตามสาขา" แต่มันเป็นที่น่าสังเกตว่าเหล่านี้เป็นหน่วยงานท้องถิ่นจริง ไม่มีแท็กระยะไกลแม้ว่า (เว้นแต่คุณจะเป็นผู้ประดิษฐ์แท็กเหล่านั้น) มีแท็กท้องถิ่นเท่านั้นดังนั้นคุณต้องได้รับแท็กในเครื่องเพื่อใช้งาน
รูปแบบทั่วไปสำหรับชื่อที่เฉพาะเจาะจงกระทำซึ่งเรียก Git อ้างอิง -is สตริงใด ๆ refs/ที่เริ่มต้นด้วย สตริงที่เริ่มต้นด้วยrefs/heads/ชื่อสาขา สตริงเริ่มต้นด้วยrefs/remotes/ชื่อสาขาติดตามระยะไกล; และสตริงที่ขึ้นต้นด้วยrefs/tags/ชื่อแท็ก ชื่อrefs/stashคือการอ้างอิงที่เก็บ (ตามที่ใช้โดยgit stash: หมายเหตุการขาดเครื่องหมายสแลช)
มีบางชื่อกรณีพิเศษที่ผิดปกติที่ไม่ได้เริ่มต้นด้วยการเป็นrefs/: HEAD, ORIG_HEAD, MERGE_HEADและCHERRY_PICK_HEADโดยเฉพาะอย่างยิ่งทุกคนนอกจากนี้ยังมีชื่อที่อาจหมายถึงการกระทำที่เฉพาะเจาะจง (แม้ว่าHEADตามปกติมีชื่อของสาขาคือมี) แต่โดยทั่วไปเริ่มต้นด้วยการอ้างอิงref: refs/heads/branchrefs/
สิ่งหนึ่งที่ Git ทำเพื่อทำให้เกิดความสับสนนี้ก็คือมันช่วยให้คุณสามารถละเว้นrefs/และมักจะเป็นคำพูดหลังจากrefs/นั้น ตัวอย่างเช่นคุณสามารถละเว้นrefs/heads/หรือrefs/tags/เมื่ออ้างถึงสาขาหรือแท็กท้องถิ่นและในความเป็นจริงคุณต้องละเว้นrefs/heads/เมื่อทำการตรวจสอบสาขาท้องถิ่น! คุณสามารถทำได้เมื่อใดก็ตามที่ผลลัพธ์ไม่ชัดเจนหรือ - ตามที่เราเพิ่งสังเกต - เมื่อคุณต้องทำ (สำหรับ)git checkout branch
เป็นความจริงที่การอ้างอิงนั้นไม่เพียง แต่ในที่เก็บข้อมูลของคุณเท่านั้น แต่ยังอยู่ในที่เก็บข้อมูลระยะไกลด้วย อย่างไรก็ตาม Git ช่วยให้คุณสามารถเข้าถึงการอ้างอิงของที่เก็บระยะไกลในเวลาที่ระบุเท่านั้น: ระหว่างfetchและpushการดำเนินการ นอกจากนี้คุณยังสามารถใช้git ls-remoteหรือgit remote showดูพวกเขา แต่fetchและpushเป็นจุดที่น่าสนใจของการติดต่อ
Refspecs
ในระหว่างfetchและpushGit ใช้สตริงที่เรียกrefspecsเพื่อถ่ายโอนการอ้างอิงระหว่างที่เก็บในท้องถิ่นและระยะไกล ดังนั้นจึงเป็นช่วงเวลาเหล่านี้และผ่าน refspecs ที่เก็บ Git สองแห่งสามารถซิงค์กันได้ เมื่อชื่อของคุณซิงค์กันแล้วคุณสามารถใช้ชื่อเดียวกับที่มีคนใช้รีโมต แม้ว่าจะมีเวทมนตร์พิเศษบางอย่างที่นี่fetchและมันส่งผลกระทบต่อทั้งชื่อสาขาและชื่อแท็ก
คุณควรคิดว่าgit fetchเป็นผู้กำกับ Git ของคุณให้เรียก (หรืออาจเป็นข้อความตัวอักษร) Git อีกตัว - "ระยะไกล" - และสนทนากับมัน ในช่วงต้นของการสนทนารีโมตจะแสดงรายการข้อมูลอ้างอิงทั้งหมด: ทุกอย่างในrefs/heads/และทุกสิ่งในrefs/tags/รวมถึงข้อมูลอ้างอิงอื่น ๆ ที่มี Git ของคุณสแกนผ่านสิ่งเหล่านี้และ (ขึ้นอยู่กับ refspec ดึงข้อมูลปกติ) เปลี่ยนชื่อสาขาของพวกเขา
ลองดู refspec ปกติสำหรับชื่อระยะไกลorigin:
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$
Refspec นี้สั่งให้ Git ของคุณทำการจับคู่ชื่อทุกชื่อrefs/heads/*- ทุกสาขาในรีโมต - และเปลี่ยนชื่อเป็นrefs/remotes/origin/*เช่นให้ส่วนที่ตรงกันตรงกันเปลี่ยนชื่อสาขา ( refs/heads/) เป็นชื่อสาขาติดตามระยะไกล ( refs/remotes/โดยเฉพาะ , refs/remotes/origin/)
มันเป็นผ่าน refspec นี้ว่าorigin's originสาขากลายเป็นสาขาที่ห่างไกลการติดตามของคุณสำหรับระยะไกล ชื่อสาขาจะกลายเป็นชื่อสาขาของการติดตามระยะไกลโดยมีชื่อของรีโมตในกรณีนี้originรวมอยู่ด้วย เครื่องหมายบวก+ที่ด้านหน้าของ refspec ตั้งค่าสถานะ "บังคับ" เช่นสาขาการติดตามระยะไกลของคุณจะได้รับการอัปเดตให้ตรงกับชื่อสาขาของรีโมตโดยไม่คำนึงถึงสิ่งที่ต้องใช้ในการจับคู่ (หากไม่มีการ+อัปเดตสาขาจะ จำกัด เฉพาะการเปลี่ยนแปลง "กรอไปข้างหน้า" และการอัปเดตแท็กจะถูกละเว้นเพียงตั้งแต่ Git เวอร์ชัน 1.8.2 หรือก่อนหน้านั้นจะมีการใช้กฎการกรอไปข้างหน้าแบบเดียวกัน)
แท็ก
แต่แท็กล่ะ อย่างน้อยก็ไม่มีค่าอ้างอิงสำหรับพวกเขา คุณสามารถตั้งค่าหนึ่งในกรณีที่รูปแบบของการอ้างอิงขึ้นอยู่กับคุณ; git fetch --tagsหรือคุณสามารถเรียก ใช้--tagsมีผลกระทบของการเพิ่มrefs/tags/*:refs/tags/*การ refspec คือมันนำกว่าแท็กทั้งหมด ( แต่ไม่ได้อัปเดตของคุณแท็กหากคุณมีแท็กที่มีชื่อนั้นคำนึงถึงสิ่งที่แท็กระยะไกลกล่าวว่าการแก้ไขมกราคม 2017: ณ Git 2.10 การทดสอบแสดงให้เห็นว่าการ--tagsบังคับใช้อัปเดตแท็กของคุณจากแท็กของรีโมตราวกับว่า refspec อ่าน+refs/tags/*:refs/tags/*นี่อาจเป็นพฤติกรรมที่แตกต่างจาก Git รุ่นก่อนหน้า)
โปรดทราบว่าไม่มีการเปลี่ยนชื่อที่นี่: หากรีโมตoriginมีแท็กxyzzyและคุณไม่และgit fetch origin "refs/tags/*:refs/tags/*"คุณจะrefs/tags/xyzzyถูกเพิ่มในที่เก็บข้อมูลของคุณ (ชี้ไปที่การคอมมิชชันเดียวกันกับรีโมต) ถ้าคุณใช้+refs/tags/*:refs/tags/*แล้วแท็กของคุณxyzzyถ้าคุณมีหนึ่งจะถูกแทนที่originโดยหนึ่งจาก นั่นคือการ+ตั้งค่าสถานะกองทัพใน refspec หมายถึง "แทนที่ค่าอ้างอิงของฉันด้วยหนึ่ง Git ของฉันได้รับจาก Git ของพวกเขา"
แท็ก Automagic ระหว่างการดึงข้อมูล
ด้วยเหตุผลทางประวัติศาสตร์3หากคุณไม่ใช้--tagsตัวเลือกหรือ--no-tagsตัวเลือกให้git fetchดำเนินการพิเศษ โปรดจำไว้ว่าเราได้กล่าวไว้ข้างต้นว่ารีโมทเริ่มต้นด้วยการแสดงการอ้างอิงทั้งหมดของ Git ในท้องถิ่นของคุณไม่ว่า Git ในท้องถิ่นของคุณต้องการเห็นพวกเขาหรือไม่ 4 Git ของคุณจดบันทึกแท็กทั้งหมดที่เห็นในตอนนี้ จากนั้นเมื่อเริ่มต้นการดาวน์โหลดออบเจ็กต์การส่งมอบใด ๆ มันจะต้องจัดการกับสิ่งที่กำลังดึงหากหนึ่งในการกระทำเหล่านั้นมี ID เหมือนกับแท็กเหล่านั้น git จะเพิ่มแท็กนั้นหรือแท็กเหล่านั้นหากมีหลายแท็กนั้น พื้นที่เก็บข้อมูลของคุณ
แก้ไขมกราคม 2017: การทดสอบแสดงให้เห็นว่าพฤติกรรมใน Git 2.10 อยู่ในขณะนี้: ถ้า Git ของพวกเขาให้แท็กชื่อT , และคุณไม่ต้องแท็กชื่อT , และกระทำ ID ที่เกี่ยวข้องกับTเป็นบรรพบุรุษของหนึ่งในสาขาของพวกเขา เมื่อคุณgit fetchตรวจสอบ Git ของคุณจะเพิ่มTในแท็กของคุณไม่--tagsว่าจะมีหรือไม่มี การเพิ่ม--tagsทำให้ Git ของคุณได้รับแท็กทั้งหมดและบังคับให้อัปเดต
บรรทัดล่าง
คุณอาจต้องใช้git fetch --tagsเพื่อรับแท็กของพวกเขา หากชื่อแท็กของพวกเขาขัดแย้งกับชื่อแท็กที่มีอยู่คุณอาจ (ขึ้นอยู่กับเวอร์ชัน Git) แม้จะต้องลบ (หรือเปลี่ยนชื่อ) แท็กบางส่วนของคุณแล้วเรียกใช้git fetch --tagsเพื่อรับแท็ก เนื่องจากแท็กซึ่งแตกต่างจากสาขาระยะไกลจึงไม่มีการเปลี่ยนชื่อโดยอัตโนมัติชื่อแท็กของคุณจะต้องตรงกับชื่อแท็กซึ่งเป็นสาเหตุที่คุณมีปัญหากับข้อขัดแย้ง
ในกรณีปกติส่วนใหญ่จะมีการดำเนินการอย่างง่ายgit fetchการนำการคอมมิชชันและแท็กที่จับคู่มาและเมื่อพวกเขา - ไม่ว่าพวกเขาจะเป็นแท็กจะทำในเวลาที่พวกเขาเผยแพร่คอมมิชชันคุณจะต้องติดตามแท็กของพวกเขา หากคุณไม่สร้างแท็กของคุณเองหรือผสมที่เก็บและที่เก็บอื่น ๆ (ผ่านรีโมตหลายตัว) คุณจะไม่มีชื่อแท็กชนกันดังนั้นคุณจะไม่ต้องยุ่งยากกับการลบหรือเปลี่ยนชื่อแท็กเพื่อ รับแท็กของพวกเขา
เมื่อคุณต้องการชื่อที่ผ่านการรับรอง
ผมกล่าวข้างต้นที่คุณสามารถละเว้นrefs/เกือบตลอดเวลาและrefs/heads/และrefs/tags/และอื่น ๆ ส่วนใหญ่ของเวลา แต่เมื่อไม่สามารถคุณ?
ฉบับสมบูรณ์ (หรือใกล้เสร็จสมบูรณ์แล้ว) คำตอบคือในเอกสาร Git จะแก้ไขชื่อให้เป็นรหัสยืนยันโดยใช้ลำดับหกขั้นตอนที่ระบุในลิงก์ อยากรู้อยากเห็นแท็กแทนที่สาขา: หากมีแท็กและสาขาและพวกเขาชี้ไปที่ความมุ่งมั่นที่แตกต่างกันแล้ว:gitrevisionsxyzzyxyzzy
git rev-parse xyzzy
จะให้ ID ที่จุดแท็ก อย่างไรก็ตาม - และนี่คือสิ่งที่ขาดหายไปgitrevisions- git checkoutชอบชื่อสาขาดังนั้นgit checkout xyzzyจะนำคุณไปที่สาขาโดยไม่คำนึงถึงแท็ก
ในกรณีที่มีความคลุมเครือคุณมักจะสามารถสะกดออกชื่อเตะใช้ชื่อเต็มของมันหรือrefs/heads/xyzzy refs/tags/xyzzy(โปรดทราบว่าวิธีนี้ใช้งานได้git checkoutแต่อาจเป็นไปในลักษณะที่ไม่คาดคิด: git checkout refs/heads/xyzzyเป็นสาเหตุของการชำระเงินแบบถอดหัวแทนที่จะชำระเงินสาขานี่คือสาเหตุที่คุณต้องทราบว่าgit checkoutจะใช้ชื่อย่อเป็นชื่อสาขาก่อนนั่นคือวิธีที่คุณ ตรวจสอบสาขาxyzzyแม้ว่ามีแท็กxyzzyอยู่หากคุณต้องการตรวจสอบแท็กคุณสามารถใช้refs/tags/xyzzy)
เนื่องจาก (เป็นgitrevisionsบันทึกย่อ) Git จะพยายามคุณสามารถเขียนเพื่อระบุการกระทำที่ติดแท็กได้ (ถ้ามีคนที่มีการจัดการที่จะเขียนอ้างอิงที่ถูกต้องชื่อเข้าแต่นี้จะแก้ไขเป็น. แต่ปกติต่าง ๆชื่อควรจะอยู่ใน.)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR
1โอเคโอเค "ไม่ใช่แค่อวดความสามารถ" :-)
2บางคนก็พูดว่า "ไม่ค่อยเป็นประโยชน์" และฉันก็มักจะเห็นด้วย
3โดยทั่วไปgit fetchและแนวคิดทั้งหมดของรีโมตและผู้อ้างอิงเป็นเรื่องที่ค่อนข้างช้านอกเหนือจาก Git ซึ่งเกิดขึ้นในช่วงเวลาของ Git 1.5 ก่อนหน้านี้มีเพียงกรณีพิเศษแบบเฉพาะกิจและการดึงแท็กเป็นหนึ่งในนั้นจึงได้รับรหัสผ่านด้วยรหัสพิเศษ
4ถ้ามันช่วยได้ให้คิดว่า Git จากระยะไกลเป็นตัวกะพริบในความหมายของคำสแลง
git checkout A. คือAอะไร คุณสร้างAอย่างไร