การจัดระเบียบที่เก็บ Git ด้วยโมดูลย่อยที่ซ้อนกันทั่วไป


50

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

ฉันกำลังตั้งค่าเวิร์กโฟลว์สำหรับหลายโครงการในที่ทำงานและฉันสงสัยว่ามันจะเป็นอย่างไรถ้าเราใช้วิธีนี้แบบสุดขั้วแทนที่จะมีโครงการเสาหินเดียว ฉันรู้อย่างรวดเร็วมีความสามารถที่มีศักยภาพของเวิร์มในจริงๆโดยใช้โมดูลย่อย

เผื่อว่าคู่ของการใช้งาน: studioและplayerและขึ้นอยู่กับห้องสมุดcore, graphและnetworkที่อ้างอิงมีดังนี้

  • core เป็นแบบสแตนด์อโลน
  • graphขึ้นอยู่กับcore(โมดูลย่อยที่./libs/core)
  • networkdepdends on core(โมดูลย่อยที่./libs/core)
  • studioขึ้นอยู่กับgraphและnetwork(โมดูลย่อยที่./libs/graphและ./libs/network)
  • playerขึ้นอยู่กับgraphและnetwork(โมดูลย่อยที่./libs/graphและ./libs/network)

สมมติว่าเรากำลังใช้CMakeและแต่ละโครงการเหล่านี้มีการทดสอบหน่วยและงานทั้งหมด แต่ละโครงการ (รวมถึงstudioและplayer) จะต้องสามารถรวบรวมได้แบบสแตนด์อโลนเพื่อดำเนินการวัดรหัสการทดสอบหน่วย ฯลฯ

สิ่งที่เป็นแบบเรียกซ้ำgit submodule fetchแล้วคุณจะได้รับโครงสร้างไดเรกทอรีต่อไปนี้:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/         (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/       (sub-module depth: 2)
studio/libs/network/libs/core/

ขอให้สังเกตว่าcoreถูกโคลนสองครั้งในstudioโครงการ นอกเหนือจากพื้นที่ดิสก์นี้เสียผมมีปัญหาการสร้างระบบเพราะผมกำลังสร้างcoreสองครั้งและผมอาจจะได้รับสองรุ่นต่าง ๆ coreของ

คำถาม

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

ทางออกที่เป็นไปได้

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

  • มีระบบการสร้างgraphและnetworkบอกพวกเขาว่าจะหาได้ที่ไหนcore(เช่นผ่านทางคอมไพเลอร์รวมถึงเส้นทาง) กำหนดสองเป้าหมายการสร้าง "สแตนด์อโลน" และ "การพึ่งพา" โดยที่ "สแตนด์อโลน" ขึ้นอยู่กับ "การพึ่งพา" และเพิ่มพา ธ รวมเพื่อชี้ไปยังcoreโมดูลย่อยท้องถิ่น
  • แนะนำการพึ่งพาเสริมบนstudio coreจากนั้นstudioสร้างcoreตั้งค่าเส้นทางรวมให้เป็นสำเนาของcoreโมดูลย่อยจากนั้นสร้างgraphและnetworkในโหมด "การพึ่งพา"

โครงสร้างโฟลเดอร์ที่ได้จะเป็นดังนี้:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/         (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/       (empty folder, sub-modules not fetched)

แต่นี้ต้องบางมายากลสร้างระบบ (ฉันสวยมั่นใจนี้สามารถทำได้ด้วย CMake) และบิตของการทำงานด้วยตนเองในส่วนของการปรับปรุงรุ่น (ปรับปรุงgraphนอกจากนี้ยังอาจจำเป็นต้องมีการปรับปรุงcoreและnetworkจะได้รับรุ่นที่รองรับการcoreในทุกโครงการ) .

ความคิดใด ๆ เกี่ยวกับเรื่องนี้?


โปรดทราบว่าปัญหานี้ไม่ได้เฉพาะกับ cmake: มันมีอยู่สำหรับระบบการสร้างใด ๆ รวมถึงไม่มีระบบ! (เช่นเมื่อมีวัตถุประสงค์เพื่อให้ซุปเปอร์โปรเจ็กต์เพิ่งเพิ่มแหล่งไลบรารีซึ่งรวมถึงไลบรารีเฉพาะส่วนหัว)
MM

คำตอบ:


5

ฉันไปงานเลี้ยงสายนี้มาก แต่คำถามของคุณยังดูเหมือนจะไม่ได้รับคำตอบที่สมบูรณ์และเป็นที่นิยมอย่างมากจาก google

ฉันมีปัญหาเดียวกันกับ C ++ / CMake / Git / Submodules และฉันมีปัญหาที่คล้ายกันกับ MATLAB / Git / Submodules ซึ่งได้รับความแปลกพิเศษเนื่องจาก MATLAB ไม่ได้รวบรวม ฉันเพิ่งเจอวิดีโอนี้เมื่อเร็ว ๆ นี้ซึ่งดูเหมือนจะเสนอ "วิธีแก้ปัญหา" ฉันไม่ชอบวิธีแก้ปัญหาเพราะโดยพื้นฐานแล้วมันหมายถึงการทิ้งซับเซลลูโลส แต่ก็กำจัดปัญหาได้ มันเป็นเช่นเดียวกับ @errordeveloper แนะนำ แต่ละโครงการไม่มี submodules ในการสร้างโครงการให้สร้างโครงการซุปเปอร์เพื่อสร้างและรวมเป็นพี่น้องกับการอ้างอิงของมัน

ดังนั้นโครงการของคุณสำหรับการพัฒนาgraphอาจมีลักษณะดังนี้:

buildgraph/graph
buildgraph/core

แล้วโครงการสตูดิโอของคุณอาจเป็น:

buildstudio/studio
buildstudio/graph
buildstudio/network
buildstudio/core

โครงการสุดยอดเป็นเพียงโครงการหลักCMakeLists.txtและโครงการย่อย แต่ไม่มีโครงการใดที่มี submodules ด้วยตนเอง

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


1

ผมคิดว่าเมื่อคุณรวมทั้งgraphและnetworksubmodules เข้าstudioคุณก็ต้องมีรุ่นเดียวกันของในเวลาที่กำหนดในประวัติศาสตร์ของcore studioฉันจะเชื่อมโยงstudio/libs/coresubmodule เข้าstudio/libs/{graph,network}/libsด้วยกัน

ปรับปรุง:

ฉันได้สร้างที่เก็บหลายแห่งพร้อมการอ้างอิงที่คุณระบุไว้:

./core      <--- (v2)
./graph
./graph/libs
./graph/libs/core  <--- (v2)
./graph/.gitmodules
./network
./network/libs
./network/libs/core  <--- (v1)
./network/.gitmodules
./studio
./studio/libs
./studio/libs/graph
./studio/libs/graph/libs
./studio/libs/graph/libs/core <--- (v1)
./studio/libs/graph/.gitmodules
./studio/libs/network
./studio/libs/network/libs
./studio/libs/network/libs/core  <--- (v1)
./studio/libs/network/.gitmodules
./studio/studio
./studio/.gitmodules

v1และมีสองรุ่นแตกต่างกันของ v2 จัดการเวอร์ชัน 2 ในขณะที่ต้องการงานบางอย่างและติดอยู่ที่เวอร์ชัน 1 ในเวอร์ชันทั้งสองแบบโลคัลของจุดทั้งสองจะมีโปรแกรมทำงาน ตอนนี้นอกเหนือจากมุมมองการสร้างทุกอย่างทำงานได้ดีกับ submodulescoregraphnetworkstudiocorev1

ตอนนี้ฉันสามารถลบไดเรกทอรีต่อไปนี้:

./studio/libs/network/libs/core

และแทนที่ด้วยลิงก์สัญลักษณ์:

./studio/libs/network/libs/core@ -> ../../graph/libs/core/

ฉันกระทำในท้องถิ่นการเปลี่ยนแปลงนี้และสูญเสียความสามารถในการที่จะมีสองรุ่นที่แยกต่างหากจากcoreภายในstudioแต่ฉันเพียง แต่สร้างcoreครั้งเดียว เมื่อฉันพร้อมที่จะอัปเกรดเป็นv2ฉันสามารถทำ:

 git submodule update # (--rebase ?)

... ภายในสตูดิโอ / libs / เครือข่าย


แนวคิดลิงก์สัญลักษณ์ทำให้ใจของฉันหมด แต่มันไม่ใช่วิธีแก้ปัญหา หากคุณเชื่อมโยงจากgraph/libs/coreด้านนอกคุณไม่ได้ใช้ submodule หากคุณเชื่อมโยงจากstudio/libs/coreที่หนึ่งของห้องสมุดเองโมดูลย่อยแล้วที่หนึ่งที่คุณเลือกgraphหรือnetwork? ยิ่งกว่านั้นจะเกิดอะไรขึ้นเมื่อสามชั้นลึกขึ้นไป ในที่สุดถ้าcoreเป็นช่วงของการแก้ไข ไม่ชัดเจนว่าคุณต้องการเชื่อมโยงไปยังเวอร์ชันcoreนั้นgraphและnetworkกำลังใช้งานอยู่
André Caron

"คุณเลือกอันไหน : coreจะเป็นไฟล์ submodule ที่ดึงมาจากไลบรารี่ดั้งเดิมcoreอัพเดทเป็นเวอร์ชั่นที่เข้ากันได้กับทั้งสองgraphและnetwork(คุณต้องตัดสินใจว่าอันไหนดี) ลิงก์สัญลักษณ์จะถูกเพิ่มในโลคอลgraphและnetworkซับโดเลส (ไม่ถูกดึง)
coredump

1
ลิงก์สัญลักษณ์ที่คุณเสนอให้เพิ่มgraphและnetworkจะชี้นอกที่เก็บข้อมูลของตนเอง (เช่นที่อื่นในstudioโครงการ) พวกเขารู้ได้อย่างไรว่าเมื่อใดควรใช้โมดูลย่อยของตนเองเมื่อเทียบกับการใช้ลิงก์สัญลักษณ์? บางทีคุณควรเพิ่มตัวอย่างเพื่อแสดงแนวความคิดของคุณ
André Caron

0

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


1
ฉันไม่แน่ใจว่าสิ่งนี้ชัดเจนในโพสต์ของฉันหรือไม่ แต่ฉันมีหลายแอพพลิเคชั่นที่ขึ้นอยู่กับไลบรารี่เดียวกันและฉันไม่ต้องการสร้างสคริปต์บิลด์สำหรับไลบรารี่ข้ามแอพพลิเคชั่น
André Caron

3
คุณควรอธิบายรายละเอียดเกี่ยวกับวิธีแก้ปัญหาต่าง ๆ มันไม่ชัดเจนสำหรับฉันว่าคุณเชื่อมโยงการพึ่งพาอย่างไรโดยขึ้นอยู่กับบริบทห้องสมุดที่พึ่งพานั้นไม่ได้อยู่ในตำแหน่งเดียวกัน
André Caron

0

ฉันจะไม่ใช้ submodules

มันดึงดูดเช่นเดียวกับที่เคยเป็นกรณีที่มี svn-externals อย่างไรก็ตามคุณแน่ใจได้หรือไม่ว่าโครงการที่ลิงก์เหล่านั้นทั้งหมดยังคงอยู่ในที่เดียวกันในหนึ่งปี? แล้วห้าข้อล่ะ

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

โดยทั่วไปฉันมีโครงสร้างโฟลเดอร์ดังนี้

myproject/... [sources etc]
ext/ [third-party dependencies]


e.g. ext/boost, ext/cppunit

แม้ว่าสิ่งนี้จะไม่ดีมากจากมุมมองของพื้นที่ดิสก์ แต่ฉันให้ความสำคัญกับการรับประกันว่าฉันสามารถตรวจสอบทุกสถานะที่บันทึกไว้ตราบใดที่ repo นั้นมีมากขึ้น

นอกจากนี้ยังมีปัญหามากมายเกี่ยวกับ submodules ดังที่อธิบายไว้ที่นี่


ฉันแน่ใจว่าพวกเขาอยู่ในตำแหน่งที่ถูกต้องเพราะฉันยังคงรักษาไว้ทั้งหมด :-) นอกจากนี้โปรดระมัดระวังเกี่ยวกับการคัดลอกโครงการเนื่องจากเงื่อนไขการแจกจ่ายซ้ำ
André Caron

ตกลงนั่นช่วยลดปัญหา และการออกใบอนุญาต: ใช่คุณต้องระวัง แต่นั่นเป็นปัญหาที่แตกต่างอย่างสิ้นเชิง
Wilbert

0

หันหน้าไปทางปัญหาเดียวกันที่นี่ หนึ่งของการแก้ปัญหาอาจจะมีบางส่วนที่ซื้อคืนlibsที่จะถือcore, network, graphเป็น submodules และเพียงแค่ CMakeLists ที่จะบอกแต่ละ libs ที่จะหาพึ่งพา แต่ละแอปพลิเคชันจะมีlibssubmodule และใช้ libs ที่จำเป็นเท่านั้น

การทดสอบแต่ละ lib สามารถตั้งค่าได้ 2 วิธี:

  • มี core_testing, graph_testing, network_testing เป็นแอปพลิเคชันแยกกัน
  • ปรับใช้ libs ที่ทดสอบแล้วเพื่อทดสอบเซิร์ฟเวอร์และค้นหาพวกเขาขณะทำการทดสอบโดยใช้ cmake

สิ่งนี้ไม่ทำให้ libs ทั้งหมดพร้อมใช้งานสำหรับ libs อื่น ๆ ทั้งหมดหรือไม่
André Caron

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