จะส่งออกประวัติการแก้ไขจาก mercurial หรือ git ไปยัง cvs ได้อย่างไร?


100

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


เมื่อคุณพูดว่า "CVS แบบกระจาย" ฉันคิดว่าคุณหมายถึง "Distrubted VCS" หรือ "DVCS" ซึ่งย่อมาจาก "ระบบควบคุมเวอร์ชันที่แจกจ่าย"
Patrick McElhaney

ฉันหมายถึงระบบควบคุมเวอร์ชันกระจาย
tatsuhirosatou

คำตอบ:


237

โชคดีสำหรับพวกเราที่ยังคงถูกบังคับให้ใช้ CVS คอมไพล์มีเครื่องมือที่ดีมากในการทำสิ่งที่คุณต้องการทำ ข้อเสนอแนะของฉัน (และสิ่งที่เราทำที่ $ work):

การสร้างโคลนเริ่มต้น

ใช้git cvsimportเพื่อโคลนประวัติการแก้ไข CVS ลงในที่เก็บ git ฉันใช้คำขอร้องต่อไปนี้:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

-Aตัวเลือกที่จะเป็นตัวเลือก แต่มันจะช่วยให้ประวัติการแก้ไขของคุณที่นำเข้าจาก CVS มีลักษณะเหมือนคอมไพล์ (ดูman git-cvsimportข้อมูลเพิ่มเติมเกี่ยวกับวิธีการนี้มีการตั้งค่า)

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

เมื่อกระบวนการนี้เสร็จสิ้นคุณจะมีmasterสาขาที่ควรสะท้อนถึง HEAD ของ CVS ( git cvsimportโดยค่าเริ่มต้นจะละเว้นค่าคอมมิต 10 นาทีสุดท้ายเพื่อหลีกเลี่ยงการจับคอมมิตที่เสร็จไปแล้วครึ่งหนึ่ง) จากนั้นคุณสามารถใช้git logและเพื่อน ๆ เพื่อตรวจสอบประวัติทั้งหมดของที่เก็บได้เหมือนกับว่าเคยใช้คอมไพล์มาตั้งแต่ต้น

การปรับแต่งการกำหนดค่า

มีการปรับแต่งการกำหนดค่าบางอย่างที่จะทำให้การนำเข้าเพิ่มเติมจาก CVS (เช่นเดียวกับการส่งออก) ง่ายขึ้นในอนาคต สิ่งเหล่านี้ไม่ได้บันทึกไว้ในgit cvsimportman page ดังนั้นฉันคิดว่าพวกเขาสามารถเปลี่ยนแปลงได้โดยไม่ต้องแจ้งให้ทราบล่วงหน้า แต่ FWIW:

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

ตัวเลือกทั้งหมดนี้สามารถระบุได้ในบรรทัดคำสั่งเพื่อให้คุณข้ามขั้นตอนนี้ได้อย่างปลอดภัย

การนำเข้าที่เพิ่มขึ้น

ครั้งต่อ ๆ ไปgit cvsimportควรเร็วกว่าการเรียกครั้งแรกมาก อย่างไรก็ตามทำcvs rlogในทุกไดเร็กทอรี (แม้กระทั่งที่มีเฉพาะไฟล์ในAttic) ดังนั้นจึงอาจใช้เวลาสักครู่ หากคุณได้ระบุการกำหนดค่าที่แนะนำไว้ข้างต้นสิ่งที่คุณต้องทำคือดำเนินการ:

% git cvsimport

หากคุณไม่ได้ตั้งค่าคอนฟิกของคุณเพื่อระบุค่าเริ่มต้นคุณจะต้องระบุในบรรทัดคำสั่ง:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

ไม่ว่าจะด้วยวิธีใดสองสิ่งที่ควรคำนึงถึง:

  1. ตรวจสอบให้แน่ใจว่าคุณอยู่ในไดเร็กทอรีรูทของที่เก็บ git ของคุณ หากคุณอยู่ที่อื่นก็จะพยายามทำใหม่cvsimportที่จะใช้เวลาตลอดไป
  2. ตรวจสอบให้แน่ใจว่าคุณอยู่ในmasterสาขาของคุณเพื่อให้สามารถรวมการเปลี่ยนแปลง (หรือเปลี่ยนฐาน) เป็นสาขาในพื้นที่ / หัวข้อของคุณได้

การเปลี่ยนแปลงในท้องถิ่น

ในทางปฏิบัติฉันขอแนะนำให้ทำการเปลี่ยนแปลงในสาขาเสมอและรวมเฉพาะmasterเมื่อคุณพร้อมที่จะส่งออกการเปลี่ยนแปลงเหล่านั้นกลับไปยังที่เก็บ CVS คุณสามารถใช้เวิร์กโฟลว์ใดก็ได้ที่คุณต้องการในสาขาของคุณ (การรวมการทำซ้ำการบีบ ฯลฯ ) แต่แน่นอนว่าจะมีการใช้กฎการปรับซ้ำมาตรฐาน: อย่าตั้งฐานใหม่หากมีคนอื่นมาพิจารณาการเปลี่ยนแปลงในสาขาของคุณ

การส่งออกการเปลี่ยนแปลงเป็น CVS

git cvsexportcommitคำสั่งช่วยให้คุณสามารถส่งออกเพียงครั้งเดียวกระทำออกไปยังเซิร์ฟเวอร์ที่ CVS คุณสามารถระบุรหัสคอมมิตเดียว (หรืออะไรก็ได้ที่อธิบายคอมมิตเฉพาะตามที่กำหนดไว้man git-rev-parse) จากนั้นสร้างความแตกต่างนำไปใช้กับการชำระเงิน CVS จากนั้น (เป็นทางเลือก) ที่มุ่งมั่นกับ CVS โดยใช้cvsไคลเอ็นต์จริง คุณสามารถเอ็กซ์พอร์ตไมโครคอมมิตแต่ละอันในสาขาหัวข้อของคุณได้ แต่โดยทั่วไปฉันต้องการสร้างคอมมิตการผสานให้เป็นปัจจุบันmasterและส่งออกคอมมิตเดียวนั้นไปยัง CVS เมื่อคุณเอ็กซ์พอร์ตคอมมิตการผสานคุณต้องบอกคอมมิตที่คอมมิตพาเรนต์ที่จะใช้สร้างความแตกต่าง นอกจากนี้จะใช้ไม่ได้หากการผสานของคุณเป็นการกรอไปข้างหน้า (ดูส่วน "วิธีผสานการทำงาน" ของman git-mergeคำอธิบายของการผสานกรอไปข้างหน้า) ดังนั้นคุณต้องใช้--no-ffตัวเลือกเมื่อทำการผสาน นี่คือตัวอย่าง:

# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD

คุณสามารถมองเห็นสิ่งที่แต่ละตัวเลือกเหล่านั้นหมายถึงบนหน้าคนสำหรับ Git-cvsexportcommit คุณมีตัวเลือกในการตั้งค่า-wตัวเลือกในการกำหนดค่าคอมไพล์ของคุณ:

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

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

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

% cvs commit -F .msg file1 file2 file3 etc

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

การโคลน CVS ของคุณ

หากคุณมีมากกว่าหนึ่งคนที่ต้องการทำสิ่งcvsimportนี้จะมีประสิทธิภาพมากกว่าที่จะมีที่เก็บ git เดียวที่ดำเนินการ cvsimport และมีที่เก็บอื่น ๆ ทั้งหมดที่สร้างเป็นโคลน สิ่งนี้ใช้งานได้อย่างสมบูรณ์และที่เก็บโคลนสามารถดำเนินการ cvsexportcommits ได้ตามที่อธิบายไว้ข้างต้น อย่างไรก็ตามมีข้อแม้อย่างหนึ่ง เนื่องจากวิธีที่ CVS คอมมิตกลับมาพร้อมกับรหัสการคอมมิตที่แตกต่างกัน (ตามที่อธิบายไว้ข้างต้น) คุณไม่ต้องการให้สาขาที่โคลนของคุณติดตามที่เก็บ git ส่วนกลาง ตามค่าเริ่มต้นนี่คือวิธีgit cloneกำหนดค่าที่เก็บของคุณ แต่สามารถแก้ไขได้ง่าย:

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

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

% git pull origin master

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


3
ขอบคุณ. สิ่งนี้ช่วยฉันได้อย่างมากโดยเฉพาะเคล็ดลับเกี่ยวกับการใช้การผสานที่ไม่ใช่ fastforward เพื่อรวมการเปลี่ยนแปลงสำหรับ CVS ไว้ในคอมมิตเดียว
skiphoppy

8
สำหรับเร็กคอร์ดอ็อพชัน -A ที่คุณแนะนำให้ใช้สำหรับ git-cvsimport ถูกกล่าวถึงใน manpage ว่า "ไม่แนะนำ ... ถ้าคุณตั้งใจจะเอ็กซ์พอร์ตการเปลี่ยนแปลงกลับไปเป็น CVS อีกครั้งในภายหลังด้วย git-cvsexportcommit (1)" ในกรณีของฉันฉันชอบวิธีที่ผู้เขียนออกมาตามที่เป็นจริง
skiphoppy

2
ขอบคุณสำหรับเคล็ดลับ สิ่งที่มีประโยชน์อย่างหนึ่งที่ฉันทำคือเพิ่ม "cvs =! git cvsimport -k -a" ภายใต้ [alias] ใน. gitconfig ของฉัน สิ่งนี้ทำให้ "git cvs" จะ DTRT (จากด้านบนของต้นไม้)
bstpierre

1
หากคุณพลาดgit cvsimportDebian ลองapt-get install git-cvs
Tino

5
Mac OSX mavricks ไม่มี cvs โดยสิ้นเชิงและดูเหมือนว่า git cvsimport นั้นขึ้นอยู่กับ cvs Initialized empty Git repository in /Users/gus/projects/foo/foobar/.git/ Can't exec "cvsps": No such file or directory at /Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git-cvsimport line 777. Could not start cvsps: No such file or directory git cvsimport: fatal: cvsps reported errorดังนั้นสิ่งนี้จึงไม่ได้รับคุณเลยหากไม่มี CVS :(
Gus

22

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

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

ฉันสามารถแก้ปัญหานี้ได้โดยการแก้ไขพารามิเตอร์ 'fuzz' ให้เหลือน้อยกว่าหนึ่งนาที

ตัวอย่าง:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

บรรทัดล่าง: ตรวจสอบต้นไม้ของคุณหลังจากนำเข้า


3

นอกจากคำตอบของ Brian Phillips แล้วยังมีgit-cvsserverซึ่งทำหน้าที่เหมือนเซิร์ฟเวอร์ CVS แต่เข้าถึงที่เก็บ git ได้จริง ... แต่ก็มีข้อ จำกัด บางประการ

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