การเลือกระหว่างโครงการเดี่ยวหรือหลายโครงการในที่เก็บ git?


223

ในgitสภาพแวดล้อมที่เราได้ทำให้เป็นส่วนใหญ่โครงการเรากำลังเผชิญหนึ่งโครงการต่อพื้นที่เก็บข้อมูลหรือหลายโครงการต่อปัญหาการออกแบบพื้นที่เก็บข้อมูล ลองพิจารณาโครงการที่ทำให้เป็นโมดูล:

myProject/
   +-- gui
   +-- core
   +-- api
   +-- implA
   +-- implB

วันนี้เรากำลังมีโครงการต่อหนึ่งพื้นที่เก็บข้อมูล มันให้อิสระในการ

  • release แต่ละองค์ประกอบ
  • tag แต่ละองค์ประกอบ

แต่มันก็ยังเป็นเรื่องยุ่งยากสำหรับbranchส่วนประกอบที่บ่อยครั้งที่การแตกแขนงนั้นapiต้องการกิ่งไม้ที่เท่ากันcoreและส่วนประกอบอื่น ๆ

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

มีประสบการณ์อะไรบ้างและคุณได้จัดการกับปัญหาเหล่านี้อย่างไร?


1
ฉันมีปัญหาที่คล้ายกันมากในขณะนี้ ฉันจำเป็นต้องเผยแพร่รุ่นต่าง ๆ ของโครงการดังนั้นพวกเขาจะต้องอยู่ในแหล่งเก็บข้อมูลที่แตกต่างกัน นี่เป็นฝันร้ายที่ต้องจัดการ มันจะดีถ้ามีวิธีแยกสาขาย่อยไดเรกทอรี
Andrew T Finnell

1
แต่ละโมดูลจะต้องมีหมายเลขรุ่นแยกต่างหาก git-describeและเราจะใช้
linquize



ฉันประหลาดใจที่เห็นว่า Bit ( bitsrc.io ) และ Lerna ( github.com/lerna/lerna ) ไม่ได้กล่าวถึง! คุณสามารถเรียนรู้เพิ่มเติมได้ที่นี่: hackernoon.com/…
Yoni

คำตอบ:


199

มีสามข้อเสียที่สำคัญone project per repositoryคือวิธีที่คุณได้อธิบายไว้ข้างต้น สิ่งเหล่านี้จริงน้อยกว่าหากพวกเขาเป็นโครงการที่แตกต่างกันอย่างแท้จริง แต่จากเสียงของมันเปลี่ยนไปเป็นหนึ่งมักจะต้องมีการเปลี่ยนแปลงไปอีกคนหนึ่งซึ่งสามารถเกินจริงปัญหาเหล่านี้:

  1. มันยากที่จะค้นพบเมื่อมีการแนะนำบั๊ก เครื่องมือเช่นgit bisectนี้จะยากต่อการใช้งานมากขึ้นเมื่อคุณแตกที่เก็บข้อมูลลงในที่เก็บย่อย เป็นไปได้มันไม่ใช่เรื่องง่ายความหมายการล่าสัตว์บั๊กในยามวิกฤตินั้นยากกว่ามาก
  2. การติดตามประวัติทั้งหมดของสถานที่นั้นยากกว่ามาก คำสั่งการgit logย้อนกลับของประวัติอย่างเช่นไม่ส่งเอาต์พุตประวัติอย่างมีความหมายกับโครงสร้างที่เก็บข้อมูลที่แตก คุณสามารถรับเอาท์พุทที่มีประโยชน์ด้วย submodulesหรือ subtrees หรือผ่านวิธีการอื่น ๆ ที่ใช้สคริปต์ แต่มันก็ไม่เหมือนกับการพิมพ์tig --grep=<caseID>หรือgit log --grep=<caseID>การสแกนทั้งหมดที่คุณให้ความสำคัญ ประวัติของคุณจะยากต่อการเข้าใจซึ่งทำให้มีประโยชน์น้อยลงเมื่อคุณต้องการ
  3. นักพัฒนาใหม่ใช้เวลาเรียนรู้โครงสร้างของการควบคุมเวอร์ชันก่อนที่จะเริ่มการเข้ารหัส งานใหม่ทุกงานจำเป็นต้องมีขั้นตอนการรับสินค้า แต่การแตกที่เก็บโครงการทำให้พวกเขาต้องรับโครงสร้าง VC เพิ่มเติมจากสถาปัตยกรรมของรหัส จากประสบการณ์ของฉันนี่เป็นเรื่องยากโดยเฉพาะอย่างยิ่งสำหรับนักพัฒนาใหม่สำหรับคอมไพล์ที่มาจากร้านค้าส่วนกลางแบบดั้งเดิมที่ใช้พื้นที่เก็บข้อมูลเดียว

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

มันมากเกินไป มากเกินไปสำหรับเราอย่างน้อย ค่าใช้จ่ายในการจัดการทำให้คุณสมบัติของเราว่องไวน้อยลงทำให้การปรับใช้ยากขึ้นมากทำให้การสอนผู้ใช้งานใหม่ใช้เวลามากเกินไปและในตอนท้ายเราแทบจะจำได้ไม่ได้ว่าทำไมเราถึงแตกที่เก็บข้อมูลในตอนแรก วันหนึ่งในฤดูใบไม้ผลิที่สวยงามฉันใช้เวลา $ 10 สำหรับช่วงบ่ายของการคำนวณคลัสเตอร์ใน EC2 ฉันต้องการให้ repos กลับมาพร้อมกับการgit filter-branchเรียกสองสิบ เราไม่เคยมองย้อนกลับไป


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

2
คุณจะปล่อยแต่ละโครงการเป็นรุ่นแยกต่างหากได้อย่างไร หรือคุณไม่จำเป็นต้องทำเช่นนั้น? นั่นคือปัญหาที่ฉันมี ด้วยถ้าคุณต้องการสร้าง V1 ของ Project A และ V2 ของ Project B
Andrew T Finnell

5
สำหรับการย้ายระหว่าง "หนึ่งโครงการต่อ repo" และ "หลาย repos" ให้พิจารณา git-subtree (คำอธิบายที่ดีที่stackoverflow.com/a/17864475/15585 )
ขัดขวาง

1
ฉันเขียนสคริปต์เพื่อทำสิ่งนี้โดยอัตโนมัติสำหรับกรณีการใช้งานทั่วไป: github.com/Oakleon/git-join-repos
chrishiestand

"โครงสร้าง VC คืออะไร"
Robert Harvey

60

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

ในตำแหน่งปัจจุบันของฉันฉันได้ย้ายที่เก็บ CVS behemoth เดียวที่เก็บประวัติ CVS ที่มีประวัติมากกว่าสิบปีไปยังที่เก็บ git จำนวนหนึ่ง ตั้งแต่การตัดสินใจครั้งแรกจำนวนที่เก็บได้เพิ่มขึ้น (ผ่านการกระทำของทีมอื่น ๆ ) จนถึงจุดที่ฉันสงสัยว่าเรามีมากกว่าที่จะดีที่สุด การจ้างงานใหม่บางคนได้แนะนำการรวมที่เก็บ แต่ฉันได้โต้แย้งกับมัน โครงการ Wayland มีประสบการณ์ที่คล้ายคลึงกัน ในการพูดคุยที่ฉันเห็นเมื่อเร็ว ๆ นี้พวกเขามีที่เก็บของคอมไพล์มากกว่า 200 git ซึ่งผู้นำคนนั้นขอโทษ ดูที่เว็บไซต์ของพวกเขาฉันเห็นตอนนี้พวกเขาอยู่ที่ 5 ซึ่งดูเหมือนสมเหตุสมผล สิ่งสำคัญคือต้องสังเกตว่าการเข้าร่วมและการแยกที่เก็บข้อมูลเป็นงานที่จัดการได้และไม่ควรทดลอง (ด้วยเหตุผล)

ดังนั้นเมื่อใดที่คุณอาจต้องการที่เก็บหลายแห่ง

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

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

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

แม้ว่าจะมีข้อเสียของโครงการหลายพื้นที่เก็บข้อมูล แต่ก็มีงานน่านับถือมากมายที่ทำเช่นนั้น - ทางและเพิ่มขึ้นมาในใจ ฉันไม่เชื่อว่าฉันทามติเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดได้มีการพัฒนาและจำเป็นต้องมีการตัดสินบางอย่าง เครื่องมือสำหรับการทำงานกับที่เก็บหลายแห่ง (git-subtree, git-submodule และอื่น ๆ ) ยังคงได้รับการพัฒนาและทดลองใช้ คำแนะนำของฉันคือการทดสอบและปฏิบัติ


7
คำตอบนี้จะเป็นประโยชน์มากยิ่งขึ้นเมื่อมีการอ้างอิงเพื่อสนับสนุนการอ้างสิทธิ์: "การเข้าร่วมและการแยกที่เก็บเป็นงานที่จัดการได้"
Wildcard

3
repos หลายตัวสามารถทำงานกับแบบแยกส่วนได้เพราะมันทำให้เปลี่ยนรหัสที่แชร์ได้ยากขึ้น Cross-repo พึ่งพาการรวมกันได้ยากขึ้นสามารถทำลายรหัสได้ง่ายขึ้น (แม้ว่าคุณจะมีเครื่องมือที่ดีในการตรวจสอบ) และการคุกคามของการทำลายรหัส repo ซ้ำทำให้ไม่ต้องใช้อินเทอร์เฟซ refactoring ซึ่งเป็นหนึ่งในเครื่องมือที่ทรงพลังที่สุด แบบแยกส่วนเพิ่มเติม
Curt J. Sampson

ทุกอย่างเกี่ยวกับ MicroServices และการออกแบบ DDD ถืออยู่ที่นี่ คุณควรลดรหัสที่ใช้ร่วมกันให้น้อยที่สุด
Arwin

49

ในขณะที่เราใช้ GitHub เรามีหลายโครงการใน repo เดียว แต่ให้แน่ใจว่าโครงการ / โมดูลเหล่านั้นถูกทำให้เป็นโมดูลอย่างถูกต้อง (เราใช้การประชุมแบบ -api และ -core + Maven + การตรวจสอบแบบสแตติกและรันไทม์และอาจไป OSGi ในวันบูต) .

มันประหยัดอะไร เราไม่จำเป็นต้องออกคำขอดึงหลายครั้งหากเราเปลี่ยนบางสิ่งเล็กน้อยในหลาย ๆ โครงการ ปัญหาและ Wiki ถูกเก็บไว้ที่ส่วนกลาง ฯลฯ

เรายังถือว่าแต่ละโมดูล / โครงการเป็นโครงการอิสระที่เหมาะสมและสร้างและรวมเข้าด้วยกันในเซิร์ฟเวอร์ CI ของเราเป็นต้น


1
น่าสนใจมาก. ฉันสงสัยว่านี่เป็นรูปแบบทั่วไปของ GitHub หากคุณเผชิญกับการเผยแพร่ส่วนประกอบแต่ละรายการคุณใช้สิ่งที่ชอบsubmodulesหรือปล่อย / แท็กพื้นที่เก็บข้อมูลทั้งหมดหรือไม่
Johan Sjöberg

submodules ถ้าเราต้อง แต่ตอนนี้เรารุ่นจากผู้ปกครองลง
Martijn Verburg

ที่นายจ้างปัจจุบันของฉันเราใช้กลยุทธ์ที่คล้ายกันและแพคเกจเมตาดาต้าเกี่ยวกับการกระทำล่าสุดในโครงการเป็นไฟล์รายการต่าง ๆ ของสิ่งประดิษฐ์ (เช่นผลลัพธ์ของgit log -1 -- <project_dir>) มันค่อนข้างดีจริงๆ คำตอบนี้สมควรได้รับการโหวตมากขึ้น
คริสโตเฟอร์

22

สำหรับฉันความแตกต่างหลักในการใช้หนึ่งหรือมากกว่าหนึ่งที่เก็บเป็นคำตอบสำหรับคำถามต่อไปนี้:

  • มีหลายส่วนที่พัฒนาโดยทีมเดียวกันมีวงจรการเปิดตัวเดียวกันลูกค้ารายเดียวกันหรือไม่ จากนั้นมีเหตุผลน้อยกว่าในการแยกที่เก็บหนึ่งรายการ
  • เป็นส่วนที่หลายอย่างมากขึ้นอยู่กับแต่ละอื่น ๆ ? ดังนั้นรูปแบบการแยกตัวควบคุมและ UI (แม้ว่าจะเป็นส่วนที่แตกต่างกัน) ไม่สมเหตุสมผลมากเนื่องจากการพึ่งพาซึ่งกันและกัน แต่ถ้า 2 ส่วนมีการพึ่งพาเพียงเล็กน้อยซึ่งถูกนำมาใช้โดยอินเตอร์เฟสที่เสถียรที่เปลี่ยนแปลงเพียงไม่กี่ปีดังนั้นจึงควรแบ่ง 2 ส่วนในที่เก็บ 2 ส่วน

ตัวอย่างเช่นฉันมีแอปพลิเคชั่นขนาดเล็ก (ไคลเอ็นต์เท่านั้น) ที่ตรวจสอบ "คุณภาพ" ของที่เก็บข้อมูลการโค่นล้ม มีการใช้งานหลักที่สามารถเริ่มต้นจากบรรทัดคำสั่งและทำงานได้ดีกับ Java 6 แต่ฉันได้เริ่มใช้ UI ที่ใช้ JavaFX เป็นส่วนหนึ่งของ Java 8 ดังนั้นฉันจึงแยก 2 และสร้าง พื้นที่เก็บข้อมูลที่สอง (ด้วยกระบวนการสร้างที่สอง) ที่มีตารางเวลาที่แตกต่างกัน ...

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


4

มันอาจจะเป็นไปได้ว่าGit-ทรีย่อย (ดูAtlassian บล็อก , บล็อกขนาดกลางหรือการเชื่อมโยงเคอร์เนล ) จะเป็นแบบที่ดีที่คุณมี ดังนั้นโปรเจ็กต์ระดับบนสุดของคุณแต่ละโครงการจะใช้ชุดทรีย่อยในเวอร์ชันที่ต่างกัน


0

จากตัวอย่างของคุณที่เก็บควรตั้งค่าในแง่ของการพึ่งพาซึ่งกันและกัน เหตุผลทั้งหมดเกี่ยวกับการออกแบบ MicroServices และ Domain Driven Design นำไปใช้ที่นี่: ในบางกรณีรหัสที่ซ้ำกันนั้นเป็นที่ยอมรับได้ทำงานกับส่วนต่อประสานไม่ทำลายความเข้ากันได้เว้นแต่คุณจะต้องเป็นต้น

ตอนนี้ในมุมมองของฉัน UI ควรเป็นอิสระจากแบ็กเอนด์ ดังนั้นที่เก็บโครงการ UI ควรมีรหัส UI และตัวควบคุมไคลเอ็นต์ Client Controller จะเชื่อมต่อกับ Service Controllers ในลักษณะที่เป็นนามธรรม พวกเขาจะใช้บริการไคลเอนต์ / api นามธรรมที่เป็นรุ่นแยกต่างหากจากบริการเพื่อให้สามารถอัปเดตบริการได้โดยไม่ทำให้ลูกค้าเสียหาย (อาจมีไคลเอ็นต์ที่แตกต่างกันหลายราย)

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

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

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

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