วิธีแก้ปัญหาง่ายๆ: ลบสาขา 'งาน' ออกหลังจากรวมเข้าด้วยกัน
คำตอบสั้น ๆ :คุณสามารถใช้คอมไพล์ได้ตามต้องการ (ดูขั้นตอนการทำงานอย่างง่ายด้านล่าง) รวมถึงการผสาน เพียงตรวจสอบให้แน่ใจว่าทำตาม ' git merge work ' แต่ละรายการด้วย ' git branch -d work ' เพื่อลบสาขางานชั่วคราว
คำอธิบายความเป็นมา:
ปัญหาการผสาน / dcommit คือเมื่อใดก็ตามที่คุณ 'git svn dcommit' สาขาหนึ่งประวัติการผสานของสาขานั้นจะ 'แบน': git ลืมเกี่ยวกับการดำเนินการผสานทั้งหมดที่เข้าสู่สาขานี้: เพียงแค่เก็บรักษาเนื้อหาของไฟล์ไว้ แต่ความจริงที่ว่าเนื้อหานี้ (บางส่วน) มาจากสาขาอื่นที่เฉพาะเจาะจงจะสูญหายไป ดู: เหตุใด git svn dcommit จึงสูญเสียประวัติของการผสานคอมมิตสำหรับสาขาในพื้นที่
(หมายเหตุ: git-svn สามารถทำได้ไม่มากนัก: svn ไม่เข้าใจการผสาน git ที่ทรงพลังกว่ามากดังนั้นภายในที่เก็บ svn ข้อมูลการผสานนี้จึงไม่สามารถแสดงในลักษณะใดก็ได้)
แต่นี่คือทั้งหมดปัญหาหากคุณลบสาขา 'งาน' หลังจากที่รวมเข้ากับ 'สาขาหลัก' แล้วที่เก็บ git ของคุณจะสะอาด 100% และดูเหมือนที่เก็บ svn ของคุณ
ขั้นตอนการทำงานของฉัน:
แน่นอนก่อนอื่นฉันโคลนที่เก็บ svn ระยะไกลลงในที่เก็บ git ในเครื่อง (อาจใช้เวลาสักครู่):
$> git svn clone <svn-repository-url> <local-directory>
จากนั้นงานทั้งหมดจะเกิดขึ้นภายใน "local-directory" เมื่อใดก็ตามที่ฉันต้องการรับการอัปเดตจากเซิร์ฟเวอร์ (เช่น 'svn update') ฉันจะ:
$> git checkout master
$> git svn rebase
ฉันทำงานพัฒนาทั้งหมดใน 'งาน' สาขาแยกต่างหากที่สร้างขึ้นในลักษณะนี้:
$> git checkout -b work
แน่นอนคุณสามารถสร้างสาขาสำหรับงานของคุณได้มากเท่าที่คุณต้องการและรวมและสร้างใหม่ระหว่างสาขาต่างๆได้ตามที่คุณต้องการ (เพียงแค่ลบออกเมื่อคุณทำเสร็จแล้ว --- ตามที่กล่าวไว้ด้านล่าง) ในการทำงานปกติของฉันฉันทำงานบ่อยมาก:
$> git commit -am '-- finished a little piece of work'
ขั้นตอนต่อไป (git rebase -i) เป็นทางเลือก --- เป็นเพียงการล้างประวัติก่อนที่จะเก็บใน svn: เมื่อฉันไปถึงศิลาไมล์ที่มั่นคงที่ฉันต้องการแบ่งปันกับคนอื่นฉันจะเขียนประวัติของ 'งาน' นี้ใหม่ แยกสาขาและล้างข้อความคอมมิต (นักพัฒนาคนอื่น ๆ ไม่จำเป็นต้องเห็นขั้นตอนและข้อผิดพลาดเล็ก ๆ น้อย ๆ ทั้งหมดที่ฉันทำระหว่างทาง --- แค่ผลลัพธ์) สำหรับสิ่งนี้ฉันทำ
$> git log
และคัดลอกแฮช sha-1 ของคอมมิตสุดท้ายที่อยู่ในที่เก็บ svn (ตามที่ระบุโดย git-svn-id) แล้วฉันก็โทร
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
เพียงวางแฮช sha-1 ของการกระทำ svn ล่าสุดของเราแทนของฉัน คุณอาจต้องการอ่านเอกสารเกี่ยวกับ 'git help rebase' สำหรับรายละเอียด กล่าวโดยย่อ: คำสั่งนี้จะเปิดตัวแก้ไขที่นำเสนอคอมมิตของคุณก่อน ---- เพียงแค่เปลี่ยน 'เลือก' เป็น 'สควอช' สำหรับการกระทำทั้งหมดที่คุณต้องการสควอชด้วยการกระทำก่อนหน้านี้ แน่นอนบรรทัดแรกควรอยู่ในฐานะ "เลือก" ด้วยวิธีนี้คุณสามารถรวมความมุ่งมั่นเล็ก ๆ น้อย ๆ ของคุณให้เป็นหน่วยที่มีความหมายอย่างน้อยหนึ่งหน่วย บันทึกและออกจากโปรแกรมแก้ไข คุณจะได้รับตัวแก้ไขอื่นเพื่อขอให้คุณเขียนข้อความบันทึกการคอมมิตใหม่
กล่าวโดยย่อ: หลังจากฉันเสร็จสิ้น 'การแฮ็กรหัส' ฉันจะนวดสาขา 'งาน' ของฉันจนกว่าจะมีลักษณะที่ฉันต้องการนำเสนอให้กับโปรแกรมเมอร์คนอื่น ๆ (หรือฉันต้องการดูงานในเวลาไม่กี่สัปดาห์เมื่อฉันเรียกดูประวัติ) .
ในการพุชการเปลี่ยนแปลงไปยังที่เก็บ svn ฉันทำ:
$> git checkout master
$> git svn rebase
ตอนนี้เรากลับมาที่สาขา 'master' เก่าที่อัปเดตพร้อมกับการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นในเวลาเฉลี่ยในที่เก็บ svn (การเปลี่ยนแปลงใหม่ของคุณจะซ่อนอยู่ในสาขา 'งาน'
หากมีการเปลี่ยนแปลงที่อาจขัดแย้งกับการเปลี่ยนแปลง "งาน" ใหม่ของคุณคุณต้องแก้ไขปัญหาเหล่านี้ในพื้นที่ก่อนที่จะส่งงานใหม่ของคุณ (ดูรายละเอียดเพิ่มเติมด้านล่าง) จากนั้นเราสามารถผลักดันการเปลี่ยนแปลงของเราไปที่ svn:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
หมายเหตุ 1: คำสั่ง 'git branch -d work' ค่อนข้างปลอดภัย: อนุญาตให้คุณลบสาขาที่คุณไม่ต้องการอีกต่อไปเท่านั้น (เนื่องจากรวมเข้ากับสาขาปัจจุบันของคุณแล้ว) หากคุณดำเนินการคำสั่งนี้โดยไม่ได้ตั้งใจก่อนที่จะรวมงานกับสาขา 'หลัก' คุณจะได้รับข้อความแสดงข้อผิดพลาด
หมายเหตุ 2: ตรวจสอบให้แน่ใจว่าได้ลบสาขาของคุณด้วย 'git branch -d work' ระหว่างการผสานและ dcommit: หากคุณพยายามลบ branch หลังจาก dcommit คุณจะได้รับข้อความแสดงข้อผิดพลาด: เมื่อคุณ 'git svn dcommit' git จะลืมสิ่งนั้น สาขาของคุณถูกรวมเข้ากับ "master" แล้ว คุณต้องลบออกด้วย 'git branch -D work' ซึ่งไม่ได้ทำการตรวจสอบความปลอดภัย
ตอนนี้ฉันสร้างสาขา 'งาน' ใหม่ทันทีเพื่อหลีกเลี่ยงการแฮ็กสาขา 'หลัก' โดยไม่ได้ตั้งใจ:
$> git checkout -b work
$> git branch # show my branches:
master
* work
การรวม 'งาน' ของคุณเข้ากับการเปลี่ยนแปลงบน svn:
นี่คือสิ่งที่ฉันทำเมื่อ 'git svn rebase' เปิดเผยว่าคนอื่นเปลี่ยนที่เก็บ svn ในขณะที่ฉันทำงานในสาขา 'งาน' ของฉัน:
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
มีโซลูชันที่มีประสิทธิภาพมากขึ้น:
เวิร์กโฟลว์ที่นำเสนอนั้นเรียบง่าย: ใช้พลังของคอมไพล์ภายใน 'การอัปเดต / แฮ็ค / dcommit' แต่ละรอบเท่านั้น - แต่จะทิ้งประวัติโครงการระยะยาวไว้เป็นเชิงเส้นเช่นเดียวกับที่เก็บ svn สิ่งนี้ใช้ได้หากคุณต้องการเริ่มใช้ git merges ในขั้นตอนแรกเล็ก ๆ ในโครงการ svn แบบเดิม
เมื่อคุณคุ้นเคยกับการผสานคอมไพล์รู้สึกอิสระที่จะสำรวจขั้นตอนการทำงานอื่น ๆ : ถ้าคุณรู้ว่าสิ่งที่คุณทำคุณสามารถผสมผสานคอมไพล์ด้วยการผสาน SVN ( ใช้ Git-SVN (หรือคล้ายกัน) เพียงเพื่อช่วยให้ออกมาพร้อมกับการผสาน SVN? )