การบำรุงรักษาซอฟต์แวร์ที่แยกต่างหากสองรุ่นจาก Codebase เดียวกันในการควบคุมเวอร์ชัน


45

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

ขณะนี้ฉันกำลังพิจารณาใช้masterและdevelopสาขาสำหรับ codebase หลัก (รุ่นฟรี) ด้านข้างmaster-premiumและdevelop-premiumสาขาสำหรับรุ่นที่จำหน่ายได้แล้ว เมื่อมีการเปลี่ยนแปลงในเวอร์ชั่นฟรีและรวมเข้ากับmasterสาขา (หลังจากการทดสอบอย่างละเอียดในdevelopหลักสูตร) ​​มันจะถูกคัดลอกไปยังdevelop-premiumสาขาผ่านcherry-pickคำสั่งสำหรับการทดสอบเพิ่มเติมแล้วรวมเข้าmaster-premiumด้วยกัน

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

ความคิดเห็นของคุณได้รับการชื่นชมอย่างมาก!

PS นี่สำหรับสคริปต์ PHP ที่จัดเก็บใน Git แต่คำตอบควรใช้กับภาษาหรือ VCS ใด ๆ

คำตอบ:


83

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

หากคุณกลัวที่จะจัดส่งคุณสมบัติพิเศษเหล่านั้น (ปิดใช้งานโดยการกำหนดค่า) ด้วยเวอร์ชันพื้นฐานคุณยังสามารถลบรหัสนั้นในขั้นตอนการสร้าง / บรรจุภัณฑ์ขั้นสุดท้ายและมีเพียงสองโปรไฟล์การสร้าง

มีการออกแบบนี้คุณสามารถส่ง 5 รสชาติที่แตกต่างและมีความยืดหยุ่นมากอาจอนุญาตให้บุคคลที่สามมีส่วนร่วม


2
ใช่นี่คือสิ่งที่ฉันเริ่มคิดเมื่อคืนก่อนที่ฉันจะเข้านอน ขอบคุณ!
โจเซฟ Leedy

3
Windows ที่ทันสมัยได้รับการออกแบบด้วยวิธีนี้ทุกรุ่นมีรหัสเดียวกันทั้งหมดและมีคุณสมบัติปลดล็อคขึ้นอยู่กับรหัสสิทธิ์การใช้งาน
Mooing Duck

39

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

ให้รักษาซอร์สโค้ดสามัญหนึ่งเวอร์ชันและใช้การคอมไพล์แบบมีเงื่อนไข (เช่น#ifdefใน C / C ++ ไม่แน่ใจว่าเทียบเท่ากับ PHP) เพื่อรวมหรือแยกส่วนของโค้ดที่แตกต่างระหว่าง "พื้นฐาน" และ "พรีเมียม"

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


สิ่งที่คุณพูดเกี่ยวกับสาขาทำให้รู้สึกทั้งหมด! บางทีฉันอาจจะสร้าง repo แยกต่างหากที่มีเพียงรหัส Premium และใช้สคริปต์ปล่อยหรือโมดูลย่อยเพื่อรวมกับรหัสฐานหรือไม่ นี่อาจทำให้ TDD ยากขึ้นแม้ว่า ...
Joseph Leedy

14
การสร้างที่เก็บข้อมูลอื่นนั้นแย่กว่าการสร้างสาขา! แน่นอนคุณต้องการเลือกโซลูชันที่เกี่ยวข้องกับการทำซ้ำรหัสรุ่นน้อยที่สุด
Greg Hewgill

2
จุดซื้อคืนที่สองคือการบ้านเพียงรหัสพิเศษ - ไม่สำเนาของ app ทั้งหมดอีก
โจเซฟ Leedy

1
ฉันเห็นว่านั่นจะเป็นรูปแบบ "ปลั๊กอิน" มากกว่าซึ่งรหัสพื้นฐานของคุณมีความสามารถในการโหลดและเรียกใช้ปลั๊กอิน (ถ้ามี) รหัสปลั๊กอินแยกต่างหากและให้คุณสมบัติพิเศษ
Greg Hewgill

4
@Joseph: การใช้สอง repos จะเหมาะสมก็ต่อเมื่อการกำหนดเวอร์ชันของโค้ดสองฐานนั้นเกือบจะเป็นอิสระจากกัน หากเป็นกรณีที่ไม่ฉันจะขอแนะนำให้ทำในสิ่งที่เกร็กเขียนและให้ทุกอย่างในหนึ่ง repo สิ่งเดียวที่ฉันจะคิดใหม่คือการใช้ "ตัวประมวลผลล่วงหน้า" ฉันเดาสคริปต์ขนาดเล็กที่เขียนในภาษาที่คุณเลือก (PHP นั้นใช้ได้, Perl หรือ Python ดีกว่า) ซึ่งทำสำเนาของรหัสของคุณโดยไม่ต้องมีคุณสมบัติพิเศษ
Doc Brown

8

เราใช้ 2 โครงการแยกต่างหากโครงการหนึ่งและโครงการพรีเมียมที่ขึ้นอยู่กับโครงการพื้นฐาน อย่าใช้ก้านพวกเขามักจะใช้สำหรับคุณสมบัติ


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

1
ในกรณีทั่วไปคุณต้องมี 3 โครงการ: ส่วนทั่วไปมักจัดเป็นห้องสมุดและชิ้นส่วนที่กำหนดเองสำหรับสองรุ่นที่แตกต่างกัน
Andriy Tylychko

3

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

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

คำตอบของเกร็กแนะนำให้คุณ“ พิจารณาสาขาสำหรับสิ่งที่จะ (หรืออาจจะ) รวมเข้าด้วยกันอีกครั้งในภายหลัง” ด้วยวิธีการที่ฉันเพิ่งอธิบายกรณีนี้ยกเว้นว่าสาขาสุดท้ายสำหรับการกระทำทั้งหมดจะmaster-premiumไม่master(ซึ่งจริงๆแล้วmaster-basic)

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


0

ใน "ฮาร์ดแวร์" นี้มักจะทำพวกเขาเป็นระบบที่ขายเพื่อควบคุมระเบียบขออภัยที่จำไม่ได้ว่าสิ่งที่พวกเขาเรียกว่า

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

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

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

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