วิธีการทำ submodules คอมไพล์ตื้น?


139

เป็นไปได้ไหมที่จะมี submodules ตื้น ๆ ? ฉันมี superproject ที่มีหลาย submodules แต่ละอันที่มีประวัติอันยาวนานดังนั้นมันจึงมีความสำคัญมากในการลากประวัติทั้งหมดนั้นโดยไม่จำเป็น

ทั้งหมดที่ฉันได้พบคือนี้ยังไม่มีการตอบกระทู้

ฉันควรแฮ็ค git-submoduleเพื่อใช้งานหรือไม่


1
" git submodule add/update" สามารถโคลนคลังข้อมูล submodule ตอนนี้ได้อย่างง่ายดาย! ดูคำตอบของฉันด้านล่าง
VonC

คำตอบ:


133

ใหม่ในgit1.8.4 ที่จะเกิดขึ้น(กรกฎาคม 2013) :

" git submodule update" อาจเลือกที่จะโคลนคลังเก็บ submodule อย่างตื้นเขิน

(และคอมไพล์ 2.10 ไตรมาสที่ 3 ปี 2016 ช่วยให้การบันทึกว่าด้วยgit config -f .gitmodules submodule.<name>.shallow true.
ดูตอนท้ายของคำตอบนี้)

ดูการยอมรับ 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :

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

การทดสอบจะถูกเพิ่มและมีการปรับปรุงการเยื้องเพื่อให้สอดคล้องกับส่วนที่เหลือของ testfile ใน "การปรับปรุง submodule สามารถจัดการลิงก์สัญลักษณ์ใน pwd"

ลงชื่อออกโดย: Fredrik Gustafsson <iveqy@iveqy.com>
ตอบรับโดย: Jens Lehmann<Jens.Lehmann@web.de>

นั่นหมายความว่างานนี้:

git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]

ด้วย:

--depth::

ตัวเลือกนี้ใช้ได้สำหรับaddและupdateคำสั่ง
สร้างโคลน 'ตื้น' ที่มีประวัติถูกตัดให้เหลือจำนวนการแก้ไขที่ระบุ


atwymanเพิ่มในความคิดเห็น :

เท่าที่ฉันสามารถบอกตัวเลือกนี้ไม่สามารถใช้งานได้สำหรับ submodules ซึ่งไม่ได้ติดตามmasterอย่างใกล้ชิด หากคุณตั้งค่าความลึก 1 จากนั้นsubmodule updateจะประสบความสำเร็จได้ก็ต่อเมื่อ submodule ยอมรับว่าคุณต้องการเป็นมาสเตอร์คนล่าสุด มิฉะนั้นคุณจะได้รับ "fatal: reference is not a tree "

นั่นเป็นความจริง.
นั่นคือจนถึง git 2.8 (มีนาคม 2016) ด้วย 2.8, submodule update --depthโอกาสที่จะประสบความสำเร็จมากกว่าหนึ่งแม้ว่า SHA1 สามารถเข้าถึงได้โดยตรงจากหนึ่งใน repo HEADs ระยะไกล

ดูกระทำ fb43e31 (24 กุมภาพันธ์ 2016) โดยสเตฟานสนั่น (stefanbeller )
ช่วยโดย: Junio C Hamano (gitster )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 9671a76 , 26 กุมภาพันธ์ 2016)

submodule: พยายามดึง sha1 ที่ต้องการได้ยากขึ้นโดยดึง sha1 โดยตรง

เมื่อตรวจสอบการเปลี่ยนแปลงที่อัปเดต submodule ใน Gerrit แนวทางการตรวจสอบทั่วไปคือการดาวน์โหลดและเลือกแพทช์เชอร์รี่ในพื้นที่เพื่อทดสอบ
อย่างไรก็ตามเมื่อทำการทดสอบภายในเครื่อง ' git submodule update' อาจล้มเหลวในการดึงข้อมูล submodule sha1 ที่ถูกต้องเนื่องจากการกระทำที่สอดคล้องกันใน submodule นั้นยังไม่ได้เป็นส่วนหนึ่งของประวัติโครงการ แต่ก็เป็นเพียงการเปลี่ยนแปลงที่เสนอ

ถ้า$sha1ไม่ได้เป็นส่วนหนึ่งของการเริ่มต้นเรียกเราพยายามที่จะดึงข้อมูล$sha1โดยตรง อย่างไรก็ตามเซิร์ฟเวอร์บางตัวไม่รองรับการดึงโดยตรงด้วย sha1 ซึ่งทำให้git-fetchล้มเหลวอย่างรวดเร็ว
เราสามารถทำให้ตัวเองล้มเหลวได้ที่นี่เพราะ sha1 ที่หายไปจะนำไปสู่ความล้มเหลวในขั้นตอนการชำระเงินต่อไปดังนั้นความล้มเหลวที่นี่จึงดีเท่าที่เราจะได้รับ


MVGชี้ให้เห็นในความคิดเห็นที่จะกระทำ fb43e31 (git 2.9, Feb 2016)

ดูเหมือนว่าฉันที่ยอมรับ fb43e31ร้องขอการกระทำที่ขาดหายไปโดยรหัส SHA1 ดังนั้นการตั้งค่าuploadpack.allowReachableSHA1InWantและuploadpack.allowTipSHA1InWantบนเซิร์ฟเวอร์อาจส่งผลกระทบต่อการทำงานนี้
ฉันเขียนโพสต์ไปยังรายการ git วันนี้ชี้ให้เห็นว่าการใช้ submodules ตื้น ๆ สามารถทำงานได้ดีขึ้นในบางสถานการณ์หรือไม่นั่นคือถ้าการกระทำเป็นแท็กด้วย
รอดูกันก่อน

ฉันเดาว่านี่เป็นเหตุผลที่ fb43e31 ทำการดึงข้อมูลสำหรับ SHA1 เฉพาะทางเลือกหลังจากการดึงข้อมูลสำหรับสาขาเริ่มต้น
อย่างไรก็ตามในกรณีของ“ - ส่วนที่ 1” ฉันคิดว่ามันสมเหตุสมผลแล้วที่จะยกเลิกก่อน: ถ้าไม่มีผู้อ้างอิงที่ระบุไว้ตรงกับที่ร้องขอและการร้องขอจาก SHA1 ไม่ได้รับการสนับสนุนจากเซิร์ฟเวอร์ ดึงสิ่งใด ๆ เนื่องจากเราจะไม่สามารถตอบสนองความต้องการ submodule ด้วยวิธีใดวิธีหนึ่ง


อัปเดตสิงหาคม 2559 (3 ปีต่อมา)

ด้วย Git 2.10 (Q3 2559) คุณจะสามารถทำได้

 git config -f .gitmodules submodule.<name>.shallow true

ดูที่ " God submodule โดยไม่มีน้ำหนักเพิ่ม "


Git 2.13 (Q2 2017) จะเพิ่มในกระทำ 8d3047c (19 เมษายน 2017) โดยเซบาสเตียน Schuberth (sschuberth )
(ผสานโดยSebastian Schuberth - sschuberth-ในวันที่8d3047c , 20 เม.ย. 2560)

โคลนของ submodule นี้จะดำเนินการเป็นโคลนตื้น(ที่มีประวัติความลึก 1)

อย่างไรก็ตามCiro Santilliเพิ่มในความคิดเห็น (และรายละเอียดในคำตอบของเขา )

shallow = trueบน.gitmodulesจะมีผลต่อการอ้างอิงการติดตามโดยหัวของระยะไกลเมื่อใช้--recurse-submodulesแม้ว่าเป้าหมายกระทำจะชี้ไปตามสาขาและแม้กระทั่งถ้าคุณใส่branch = mybranchใน.gitmodulesได้เป็นอย่างดี


Git 2.20 (Q4 2018) ปรับปรุงในส่วนสนับสนุน submodule ซึ่งได้รับการอัพเดทให้อ่านจาก blob HEAD:.gitmodulesเมื่อ.gitmodulesไฟล์หายไปจากแผนผังการทำงาน

ดูกระทำ 2b1257e , กระทำ 76e9bdc (25 ตุลาคม 2018) และกระทำ b5c259f , กระทำ 23dd8f5 , กระทำ b2faad4 , กระทำ 2502ffc , กระทำ 996df4d , กระทำ d1b13df , กระทำ 45f5ef3 , กระทำ bcbc780 (5 ตุลาคม 2018) โดยแอนโตนิโอ Ospite (ao2 )
(ผสานโดยJunio ​​C Hamano - gitster- in abb4824 , 13 Nov 2018)

submodule: สนับสนุนการอ่าน.gitmodulesเมื่อมันไม่ได้อยู่ในแผนผังการทำงาน

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

นี้จะทำให้มันเป็นไปได้ที่จะใช้เวลาอย่างน้อย ' git submodule' คำสั่งซึ่งอ่านgitmodulesแฟ้มการกำหนดค่าโดยไม่ต้องเต็มที่ประชากรต้นทำงาน

เขียนไปจะยังคงต้องว่าไฟล์มีการตรวจสอบออกมาเพื่อตรวจสอบว่าก่อนที่จะเรียก.gitmodulesconfig_set_in_gitmodules_file_gently

เพิ่มการตรวจสอบที่คล้ายกันgit-submodule.sh::cmd_add()เพื่อคาดการณ์ความล้มเหลวในที่สุดของgit submodule addคำสั่ง "" เมื่อ.gitmodulesไม่สามารถเขียนได้อย่างปลอดภัย สิ่งนี้ป้องกันไม่ให้คำสั่งออกจากที่เก็บในสถานะปลอม (เช่นที่เก็บ submodule ถูกโคลน แต่.gitmodulesไม่ถูกอัพเดตเนื่องจากconfig_set_in_gitmodules_file_gentlyล้มเหลว)

ยิ่งไปกว่านั้นตั้งแต่config_from_gitmodules()ตอนนี้เข้าถึงที่เก็บอ็อบเจ็กต์โกลบอลจึงจำเป็นต้องปกป้องพา ธ โค้ดทั้งหมดที่เรียกใช้ฟังก์ชันจากการเข้าถึงที่เก็บอ็อบเจ็กต์โกลบอลพร้อมกัน
ปัจจุบันนี้จะเกิดขึ้นในbuiltin/grep.c::grep_submodules()เพื่อเรียกร้อง ก่อนที่จะเรียกใช้รหัสที่เกี่ยวข้องกับgrep_read_lock()config_from_gitmodules()

หมายเหตุ: มีกรณีที่เกิดขึ้นได้ยากน้อยหนึ่งกรณีซึ่งคุณลักษณะใหม่นี้ทำงานไม่ถูกต้อง: submodules ที่ซ้อนกันโดยไม่ต้อง.gitmodulesอยู่ในแผนผังการทำงาน


หมายเหตุ: Git 2.24 (Q4 2019) แก้ไข segfault ที่เป็นไปได้เมื่อทำการโคลน submodule

ดูกระทำ ddb3c85 (30 กันยายน 2019) โดยอาลี Utku Selen (auselen )
(ผสานโดยJunio ​​C Hamano - gitster- in 678a9ca , 09 Oct 2019)


Git 2.25 (Q1 2020) ชี้แจงgit submodule updateเอกสารประกอบ

ดูกระทำ f0e58b3 (24 พฤศจิกายน 2019) โดยฟิลิปป์ Blain (phil-blain )
(ผสานโดยJunio ​​C Hamano - gitster- in ef61045 , 05 Dec 2019)

doc: ระบุว่า 'git submodule update' เรียกคอมมิทที่หายไป

ช่วยเหลือโดย: Junio ​​C Hamano
ช่วยเหลือโดย: Johannes Schindelin
ลงชื่อออกโดย: Philippe Blain

' git submoduleปรับปรุง' จะเรียกใหม่กระทำจากระยะไกล submodule ถ้า SHA-1 ที่บันทึกไว้ใน superproject ไม่พบ สิ่งนี้ไม่ได้กล่าวถึงในเอกสารประกอบ


คำเตือน: ด้วย Git 2.25 (ไตรมาสที่ 1 ปี 2020) การโต้ตอบระหว่าง " git clone --recurse-submodules" และที่เก็บวัตถุทางเลือกได้รับการออกแบบมาไม่ดี

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

ดูกระทำ 4f3e57e , กระทำ 10c64a0 (2 ธันวาคม 2019) โดยโจนาธานตาล (jhowtan )
(ผสานโดยJunio ​​C Hamano - gitster-ในการกระทำ 5dd1d59 , 10 ธันวาคม 2019)

submodule--helper: แนะนำเกี่ยวกับข้อผิดพลาดทางเลือกร้ายแรง

ลงชื่อออกโดย: Jonathan Tan
ตอบรับโดย: Jeff King

เมื่อทำการโคลน.gitmodulesซูเปอร์โปรเจ็กซ้ำด้วยโมดูลตื้นบางอันที่กำหนดไว้ในนั้นจากนั้นทำการรีเคลมด้วย " --reference=<path>" จะเกิดข้อผิดพลาด ตัวอย่างเช่น:

git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

ล้มเหลวด้วย:

fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

เมื่อไม่สามารถเพิ่มทางเลือกอื่นที่คำนวณได้จากทางเลือกของ superproject ไม่ว่าจะในกรณีนี้หรือในกรณีอื่นแนะนำให้ตั้งค่า " submodule.alternateErrorStrategy" ตัวเลือกการกำหนดค่าและใช้ " --reference-if-able" แทนการ--referenceโคลน "

นั่นคือรายละเอียดใน:

ด้วย Git 2.25 (ไตรมาสที่ 1 ปี 2020) การทำงานร่วมกันระหว่าง "git clone --recurse-submodules" และที่เก็บวัตถุสำรองได้รับการออกแบบมาไม่ดี

Doc: อธิบาย submodule.alternateErrorStrategy

ลงชื่อออกโดย: Jonathan Tan
ตอบรับโดย: Jeff King

Commit 31224cbdc7 (" clone: ตัวเลือกการเรียกซ้ำและการอ้างอิงจะเรียกใช้ตัวเลือก submodule", 2016-08-17, Git v2.11.0-rc0 - รวมอยู่ในชุดที่ 1 ) สอน Git เพื่อสนับสนุนตัวเลือกการกำหนดค่า " submodule.alternateLocation" และ " submodule.alternateErrorStrategy" ใน superproject .

หาก " submodule.alternateLocation" ได้รับการกำหนดค่าให้เป็น " superproject" ในซูเปอร์โปรเจ็กต์ทุกครั้งที่โคลนซูเปอร์โปรเจ็กต์นั้นถูกโคลนมันจะคำนวณพา ธ ทางเลือกแบบอะนาล็อกแทนสำหรับซูเปอร์$GIT_DIR/objects/info/alternatesโปรเจ็กต์นั้นและจากการอ้างอิง

"การsubmodule.alternateErrorStrategyเลือก" กำหนดสิ่งที่จะเกิดขึ้นหากอื่นที่ไม่สามารถอ้างอิง
อย่างไรก็ตามมันไม่ชัดเจนว่าโคลนจะดำเนินต่อราวกับว่าไม่มีการระบุตัวเลือกอื่นเมื่อไม่ได้ตั้งค่าตัวเลือก "ตาย" (ดังที่เห็นได้จากการทดสอบใน31224cbdc7 )
ดังนั้นให้จัดทำเอกสารตามนั้น

เอกสารการตั้งค่า submoduleขณะนี้รวมถึง:

submodule.alternateErrorStrategy::

ระบุวิธีการรักษาข้อผิดพลาดกับสลับสำหรับ submodule submodule.alternateLocationเป็นคำนวณผ่าน
ค่าที่เป็นไปได้ignore, ,info เริ่มต้นคือ โปรดทราบว่าหากการตั้งค่าหรือและถ้ามีข้อผิดพลาดกับทางเลือกคำนวณเงินโคลนเช่นถ้าไม่มีสำรองถูกระบุdie
die
ignoreinfo


2
ว้าวนั่นเร็วมาก! ขอบคุณสำหรับคำตอบโดยวิธีการ โอ้และ--depthshoudl ก็ทะเลาะกันเช่นกัน)
Brice

3
ดูเหมือนว่าฉันที่ยอมรับ fb43e31ร้องขอการกระทำที่ขาดหายไปโดยรหัส SHA1 ดังนั้นการตั้งค่าuploadpack.allowReachableSHA1InWantและuploadpack.allowTipSHA1InWantบนเซิร์ฟเวอร์อาจส่งผลกระทบต่อการทำงานนี้ ฉันเขียนโพสต์ไปยังรายการ gitวันนี้ชี้ให้เห็นว่าการใช้ submodules ตื้น ๆ สามารถทำให้ดีขึ้นได้อย่างไรในบางสถานการณ์เช่นถ้า commit ยังเป็นแท็กด้วย รอดูกันก่อน
MvG

2
เมื่อเพิ่มตัวเลือกแบบตื้นล่าสุดตัวเลือก.gitmodulesจะ--depth 1ทำงานกับสาขาที่ไม่ได้ติดตามข้อมูลหลักอย่างใกล้ชิดหรือไม่
CMCDragonkai

2
@CiroSantilli 刘晓波死六四事件法轮功ขอบคุณสำหรับความแม่นยำและการทดสอบ ฉันได้รวมความคิดเห็นของคุณไว้ในคำตอบเพื่อให้มองเห็นได้มากขึ้นและอัปเกรดคำตอบของคุณแล้ว
VonC

2
มันไม่ชัดเจนจากคำตอบว่าอะไรเป็นวิธีปัจจุบัน นอกจากนี้ยังไม่ชัดเจนหากจำเป็นต้องใช้ทุกครั้งที่มีคนโคลนสำเนาใหม่หรือการตั้งค่า submodule sparce เหล่านี้กลายเป็นส่วนหนึ่งของ repo ที่อ้างอิง submodules เหล่านี้ (เช่นแต่ละโคลนใหม่และผลการปรับปรุง submodule ในการตรวจสอบ submodule sparce)
Pavel P

26

Git 2.9.0รองรับ submodules ตื้นตื้นโดยตรงดังนั้นตอนนี้คุณสามารถโทร:

git clone url://to/source/repository --recursive --shallow-submodules

2
ตัวเลือกนี้มีแนวโน้มมากที่สุด แต่ล้มเหลวใน git 2.14.1 การคอมมิทย่อยกระทำไม่ได้ติดตามโดยสาขาหรือแท็ก: stackoverflow.com/a/47374702/895245
Ciro Santilli i 冠状病病六四法轮功

1
@CiroSantilli 刘晓波死六四事件法轮功ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ git ของคุณได้รับการอัปเดตด้วย
KindDragon

ขอบคุณฉันทดสอบในเครื่องโดยไม่มีเซิร์ฟเวอร์และบน GitHub ซึ่งฉันไม่สามารถอัปเดต :-)
Ciro Santilli 郝海东冠状病六四事件法轮功

1
ฉันมีปัญหาเดียวกันโดยใช้ git 2.20 มันไม่ทำงานเมื่อ submodule ไม่ได้อยู่ที่ปลายกิ่ง
Zitrax

16

การทำตามคำตอบของไรอันฉันสามารถสร้างสคริปต์ง่าย ๆ นี้ซึ่งวนซ้ำผ่านซับโดดูเลสและโคลนนิ่งตื้น ๆ ทั้งหมด:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    spath=$(git config -f .gitmodules --get submodule.$i.path)
    surl=$(git config -f .gitmodules --get submodule.$i.url)
    git clone --depth 1 $surl $spath
done
git submodule update

ฉันจะได้รับfatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349dfสำหรับแต่ละ submodule
knocte


1
@ Knocte: ฉันเขียนคำตอบของฉันในปี 2010 สิ่งที่มีการเปลี่ยนแปลง คุณไม่สามารถคาดหวังให้ทุกคนคงคำตอบไว้ได้ ฉันทำเครื่องหมายคำตอบที่ถูกต้องในปัจจุบันว่ายอมรับแล้ว
Mauricio Scheffer

13
@knocte นี่คือหนึ่งในเหตุผลที่ฉันหยุดบริจาคให้กับ Stackoverflow ผู้คนมีความคาดหวังที่ไม่สมจริงเหล่านี้ มันจะเป็นงานเต็มเวลาที่จะรักษาทุกคำตอบของฉัน 1637 แล้วยังมีความคิดเห็นฉันคิดว่าฉันต้องรักษาเหล่านั้นด้วยหรือไม่ ลองดูวันที่นั่นคือสิ่งที่พวกเขากำลังทำ หากคุณอ่านบล็อก. NET บางส่วนจากปี 2002 ด้วยรหัสโดยใช้ ArrayList แทนที่จะเป็นรายการคุณจะใช้มันหรือไม่ คุณต้องการให้ผู้เขียนอัพเดทโพสต์ของเขาหรือไม่? ใช้หลักการเดียวกันนี้
Mauricio Scheffer

1
s / statusquo / คืบหน้า /
knocte

8

การอ่านผ่าน "แหล่งข้อมูล" git-submodule ดูเหมือนว่าgit submodule addสามารถจัดการกับ submodule ที่มีที่เก็บของพวกเขาอยู่แล้ว ในกรณีนั้น...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

คุณจะต้องตรวจสอบให้แน่ใจว่าการกระทำที่ต้องการอยู่ใน submodule repo ดังนั้นให้แน่ใจว่าคุณได้ตั้งค่าที่เหมาะสม - ความลึก

แก้ไข: คุณอาจสามารถหนีไปได้หลายโคลน submodule ด้วยตนเองตามด้วยการปรับปรุงเดียว:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update

5
ตอนนี้สำหรับ git 1.8.0 คุณไม่สามารถโคลนที่เก็บข้อมูลภายในที่เก็บอีกต่อไป ดังนั้นวิธีนี้ไม่ทำงานอีกต่อไป
Bohr

7

สรุปพฤติกรรมรถ / ไม่คาดคิด / น่ารำคาญ ณ Git 2.14.1

  1. shallow = trueใน.gitmodulesผลเฉพาะgit clone --recurse-submodulesถ้าHEADในจุด submodule ระยะไกลไปยังจำเป็นต้องกระทำแม้ว่าเป้าหมายกระทำเป็นชี้ไปตามสาขาและแม้กระทั่งถ้าคุณใส่branch = mybranchใน.gitmodulesได้เป็นอย่างดี

    สคริปต์ทดสอบท้องถิ่น พฤติกรรมเดียวกันใน GitHub 2017-11 ซึ่งHEADควบคุมโดยการตั้งค่า repo สาขาเริ่มต้น:

    git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow
    cd test-shallow-submodule-top-branch-shallow/mod
    git log
    # Multiple commits, not shallow.
    
  2. git clone --recurse-submodules --shallow-submoduleserror: Server does not allow request for unadvertised objectล้มเหลวหากกระทำการอ้างอิงค่าโดยสาขาหรือแท็กที่มีข้อความ:

    สคริปต์ทดสอบท้องถิ่น พฤติกรรมเดียวกันใน GitHub:

    git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha
    # error
    

    ฉันยังถามในรายการส่งเมล: https://marc.info/?l=git&m=151863590026582&w=2และคำตอบคือ:

    ในทางทฤษฎีสิ่งนี้น่าจะง่าย :)

    ในทางปฏิบัติไม่มากโชคไม่ดี เนื่องจากการโคลนจะได้รับเคล็ดลับล่าสุดของสาขา ไม่มีกลไกในการโคลนเพื่อระบุ sha1 ที่ต้องการ

    โปรโตคอล wire รองรับการถาม sha1 ที่แน่นอนดังนั้นจึงควรครอบคลุม (Caveat: ใช้งานได้เฉพาะในกรณีที่ผู้ให้บริการเซิร์ฟเวอร์เปิดใช้งาน

    git-fetch อนุญาตให้ดึง sha1 โดยพลการดังนั้นคุณจึงสามารถเรียกใช้การดึงข้อมูลหลังจากโคลนแบบเรียกซ้ำโดยใช้ "git submodule update" ซึ่งจะใช้การดึงข้อมูลหลังจากการโคลนเริ่มต้น

สิ่งที่ต้องทำแบบทดสอบ: allowReachableSHA1InWant.


ดูเหมือนว่าไม่มีวิธีง่ายๆในการชำระเงิน HEAD เดี่ยวที่ส่งข้อมูลแฮชสำหรับ submodule และมีผู้ใช้ดาวน์สตรีมgit clone --recursiveที่ดึงเฉพาะการคอมมิทเฉพาะนั้น
CMCDragonkai

3

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

หากคุณต้องการโคลนตื้น ๆ เพื่อประหยัดพื้นที่ในท้องถิ่นคำตอบของ Ryan Graham ดูเหมือนจะเป็นวิธีที่ดี โคลนที่เก็บข้อมูลด้วยตนเองเพื่อให้มันตื้น หากคุณคิดว่ามันจะมีประโยชน์ให้ปรับตัวgit submoduleรองรับมัน ส่งอีเมลไปยังรายการที่ถามเกี่ยวกับมัน (คำแนะนำสำหรับการนำไปใช้งานคำแนะนำเกี่ยวกับอินเทอร์เฟซ ฯลฯ ) ในความคิดของฉันผู้คนมีส่วนสนับสนุนผู้มีศักยภาพที่ต้องการพัฒนา Git อย่างสร้างสรรค์

หากคุณตกลงกับการทำโคลนแบบเต็มหนึ่งแบบของแต่ละ submodule (รวมถึงการดึงข้อมูลภายหลังเพื่อให้เป็นปัจจุบัน) คุณอาจลองใช้--referenceตัวเลือกของgit submodule update(อยู่ใน Git 1.6.4 และใหม่กว่า) เพื่ออ้างถึงที่เก็บวัตถุในท้องถิ่น (เช่น สร้าง--mirrorโคลนของคลังเก็บ submodule ที่เป็นที่ยอมรับจากนั้นใช้--referenceใน submodules ของคุณเพื่อชี้ไปที่โคลนเฉพาะที่เหล่านี้) เพียงให้แน่ใจว่าจะอ่านเกี่ยวกับgit clone --reference/ ก่อนที่จะใช้git clone --shared --referenceปัญหาที่น่าเป็นไปได้เพียงอย่างเดียวกับการอ้างอิงมิรเรอร์คือถ้าพวกเขาเคยได้รับการอัปเดตที่ไม่ใช่การส่งต่ออย่างรวดเร็ว (แม้ว่าคุณจะสามารถเปิดใช้งาน reflogs และขยายหน้าต่างการหมดอายุเพื่อช่วยรักษาคอมมิทที่ละทิ้ง คุณไม่ควรมีปัญหาใด ๆ ตราบใดที่

  • คุณไม่ได้ทำ submodule ในท้องถิ่นหรือ
  • ความมุ่งมั่นใด ๆ ที่ถูกทิ้งไว้โดยไม่ส่งต่ออย่างรวดเร็วว่าที่เก็บข้อมูลที่เป็นที่ยอมรับอาจเผยแพร่ไม่ใช่บรรพบุรุษของคอมมิชชันในท้องถิ่นของคุณหรือ
  • คุณขยันเกี่ยวกับการรักษา submodule ในประเทศของคุณกระทำการ rebased ด้านบนของสิ่งที่ไม่ไปข้างหน้าอย่างรวดเร็วอาจมีการเผยแพร่ในคลังข้อมูล submodule ที่เป็นที่ยอมรับ

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

และอย่างที่git clonemanpage บอกไว้อย่าใช้--referenceถ้าคุณไม่เข้าใจความหมายเหล่านี้

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

หรือมิฉะนั้น--referenceคุณสามารถใช้มิเรอร์โคลนนิ่งร่วมกับการใช้งานเริ่มต้น hardlinking git cloneโดยใช้มิเรอร์โลคัลเป็นแหล่งข้อมูลสำหรับ submodules ของคุณ ในโคลนซูเปอร์โปรเจ็กต์ใหม่ ๆ ให้ทำgit submodule initแก้ไข submodule URL .git/configเพื่อชี้ไปที่มิเรอร์โลคัลจากนั้นทำgit submodule update. คุณจะต้องเรียกคืน submodules ที่ถูกเอาออกที่มีอยู่แล้วเพื่อรับ hardlinks คุณจะประหยัดแบนด์วิดท์โดยการดาวน์โหลดเพียงครั้งเดียวเข้าสู่มิเรอร์จากนั้นนำข้อมูลจากเครื่องเหล่านั้นไปไว้ในรายการย่อยของคุณ การเชื่อมโยงที่ยากจะช่วยประหยัดพื้นที่ดิสก์ (แม้ว่าการดึงข้อมูลจะมีแนวโน้มที่จะสะสมและทำซ้ำในหลาย ๆ อินสแตนซ์ของที่เก็บอ็อบเจ็กต์ของ submodules ที่ถูกเช็คเอาท์คุณสามารถ recodone submodules ที่ถูกเอาออกจากมิเรอร์เป็นระยะ ๆ hardlinking)


2

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

#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
    spath=$(git config -f .gitmodules --get submodule.$name.path)
    surl=$(git config -f .gitmodules --get submodule.$name.url)
    sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
    if [ -z $sbr ]; then
        git clone $surl $spath
    else
        git clone -b $sbr --depth 1 --single-branch $surl $spath
    fi
done
git submodule update 

2

อ้างอิงถึงวิธีโคลนที่เก็บ git ด้วยการแก้ไข / เซ็ตการแก้ไขเฉพาะ

ฉันได้เขียนสคริปต์ง่าย ๆ ซึ่งไม่มีปัญหาเมื่อการอ้างอิง submodule ของคุณอยู่ห่างจากต้นแบบ

git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'

คำสั่งนี้จะดึงข้อมูล submodule เวอร์ชันที่อ้างถึง

มันเร็ว แต่คุณไม่สามารถคอมมิทแก้ไขของคุณบน submodule (คุณต้องดึงมันออกก่อนที่จะhttps://stackoverflow.com/a/17937889/3156509 )

เต็ม:

#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive

1

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

#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
  mysha=${value%:*}
  mysub=${value#*:}
  myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
  mydir=$(dirname $mysub)
  wget $myurl/archive/$mysha.zip
  unzip $mysha.zip -d $mydir
  test -d $mysub && rm -rf $mysub
  mv $mydir/*-$mysha $mysub
  rm $mysha.zip
done
git submodule init

git submodule deinit --all -f ล้างแผนผัง submodule ซึ่งทำให้สคริปต์สามารถนำกลับมาใช้ใหม่ได้

git submoduleดึง 40 char sha1 ตามด้วยเส้นทางที่สอดคล้องกับสิ่งต่อไป.gitmodulesนี้ ฉันใช้ Perl เพื่อเชื่อมข้อมูลนี้คั่นด้วยโคลอนจากนั้นใช้การแปลงตัวแปรเพื่อแยกค่าออกเป็นmyshaและmysubและ

นี่คือกุญแจสำคัญเนื่องจากเราต้องการ sha1 เพื่อดาวน์โหลดและเส้นทางที่สัมพันธ์กัน url . gitmodules

รับรายการ submodule ทั่วไป:

[submodule "label"]
    path = localpath
    url = https://github.com/repository.git

myurlปุ่มบนpath =จะมีลักษณะ 2 บรรทัดหลังจากรับค่า วิธีนี้อาจทำงานไม่สม่ำเสมอและต้องมีการปรับแต่ง grep URL แถบใด ๆ ที่เหลือ.gitอ้างอิงประเภทจากการจับคู่สุดท้ายและสิ่งที่ขึ้นไป/.

mydirเป็นmysubลบขั้นสุดท้าย/nameซึ่งทำโดยไดเรกทอรีที่นำไปสู่ชื่อ submodule

ถัดไปคือ wgetรูปแบบของ URL เก็บถาวรสำหรับซิปที่ดาวน์โหลดได้ สิ่งนี้อาจเปลี่ยนแปลงได้ในอนาคต

เปิดเครื่องรูดไฟล์mydirที่จะเป็นไดเรกทอรีย่อยที่ระบุในเส้นทาง submodule โฟลเดอร์ผลลัพธ์จะเป็นองค์ประกอบสุดท้ายของurl-sha1 -

ตรวจสอบเพื่อดูว่ามีไดเรกทอรีย่อยที่ระบุในเส้นทาง submodule หรือไม่และลบออกเพื่อให้สามารถเปลี่ยนชื่อโฟลเดอร์ที่แตกออกมาได้

mv เปลี่ยนชื่อโฟลเดอร์ที่แยกซึ่งมี sha1 ของเราเป็นเส้นทาง submodule ที่ถูกต้อง

ลบไฟล์ zip ที่ดาวน์โหลด

Submodule init

นี่เป็นการพิสูจน์แนวคิดของ WIP มากกว่าโซลูชัน เมื่อใช้งานได้ผลลัพธ์จะเป็นโคลนโคลนของ submodule ที่เซ็ตการแก้ไขที่ระบุ

หากที่เก็บกลับมาใช้ submodule อีกครั้งกับการคอมมิทที่ต่างกันให้เรียกใช้สคริปต์อีกครั้งเพื่ออัพเดต

ครั้งเดียวที่สคริปต์แบบนี้จะมีประโยชน์สำหรับการสร้างที่ไม่ทำงานร่วมกันของโครงการต้นฉบับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.