(คำตอบนี้ใช้เวลาสักครู่ในการเขียนและคำตอบของ 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/branch
refs/
สิ่งหนึ่งที่ 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
และpush
Git ใช้สตริงที่เรียก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 จะแก้ไขชื่อให้เป็นรหัสยืนยันโดยใช้ลำดับหกขั้นตอนที่ระบุในลิงก์ อยากรู้อยากเห็นแท็กแทนที่สาขา: หากมีแท็กและสาขาและพวกเขาชี้ไปที่ความมุ่งมั่นที่แตกต่างกันแล้ว:gitrevisions
xyzzy
xyzzy
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/name
tags/xyzzy
xyzzy
xyzzy
$GIT_DIR
$GIT_DIR/xyzzy
*HEAD
$GIT_DIR
1โอเคโอเค "ไม่ใช่แค่อวดความสามารถ" :-)
2บางคนก็พูดว่า "ไม่ค่อยเป็นประโยชน์" และฉันก็มักจะเห็นด้วย
3โดยทั่วไปgit fetch
และแนวคิดทั้งหมดของรีโมตและผู้อ้างอิงเป็นเรื่องที่ค่อนข้างช้านอกเหนือจาก Git ซึ่งเกิดขึ้นในช่วงเวลาของ Git 1.5 ก่อนหน้านี้มีเพียงกรณีพิเศษแบบเฉพาะกิจและการดึงแท็กเป็นหนึ่งในนั้นจึงได้รับรหัสผ่านด้วยรหัสพิเศษ
4ถ้ามันช่วยได้ให้คิดว่า Git จากระยะไกลเป็นตัวกะพริบในความหมายของคำสแลง
git checkout A
. คือA
อะไร คุณสร้างA
อย่างไร