git - ข้ามความมุ่งมั่นเฉพาะเมื่อรวม


200

ฉันใช้ Git มาประมาณหนึ่งปีแล้วและคิดว่ามันยอดเยี่ยม แต่ฉันเพิ่งเริ่มโครงการรุ่นที่สองและเริ่มสาขาใหม่สำหรับมัน ฉันกำลังดิ้นรนเล็กน้อยกับวิธีที่ดีที่สุดในการจัดการสิ่งต่าง ๆ ที่กำลังจะเกิดขึ้น

ฉันมีสองสาขาเรียกว่า master10 (สำหรับ v1) และ master20 (สำหรับ v2) ฉันทำการแก้ไขข้อบกพร่องใน v1 บน branch master10 และพัฒนาสิ่งใหม่ ๆ ของ master20 เมื่อใดก็ตามที่ฉันจะทำให้การแก้ไขข้อผิดพลาดผมผสานเข้า v2 git merge master10โดยการตรวจสอบและการทำ จนถึงตอนนี้ดีมาก

อย่างไรก็ตามตอนนี้ฉันได้ทำการเปลี่ยนแปลงใน v1 ที่ฉันไม่ต้องการใน v2 แต่ฉันต้องการรวมการแก้ไขข้อบกพร่องอื่น ๆ ต่อไป ฉันจะบอก Git ให้ข้ามการกระทำนั้น ๆ (หรือช่วงของการกระทำ) ได้อย่างไร แต่การก้าวไปข้างหน้าฉันยังต้องการรวมการแก้ไขข้อบกพร่องอื่น ๆ

ฉันคิดว่าgit rebaseอาจเป็นสิ่งที่ฉันต้องการ แต่อ่านหมอและหัวของฉันเกือบจะระเบิด

ฉันคิดว่าสิ่งที่ฉันต้องการคือสิ่งที่คล้ายกับคำสั่ง "git sync" ที่บอก git ว่าขณะนี้มีสองสาขากำลังซิงค์กันและในอนาคตจะรวมเฉพาะการคอมมิชชันจากจุดซิงค์นี้

ความช่วยเหลือใด ๆ ชื่นชม

คำตอบ:


289

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

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

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

คำสั่งแรกผสานทุกอย่างก่อนของคุณ ข้อความบันทึกการผสานเริ่มต้นจะอธิบายว่าคุณกำลังผสาน "branch 'maint' (ส่วนแรก)"

คำสั่งที่สองผสานการบำรุงรักษาที่ลำบาก ~ 3 กระทำ แต่ตัวเลือก "-s ของเรา" บอก git ให้ใช้ "กลยุทธ์การผสาน" พิเศษซึ่งในความเป็นจริงการทำงานโดยเพียงแค่รักษาต้นไม้ที่คุณกำลังผสานและละเว้นการกระทำ ) คุณกำลังรวมอย่างสมบูรณ์ แต่มันยังคงเป็นการผสานแบบใหม่ที่กระทำร่วมกับ HEAD และดูแลรักษา ~ 3 ในฐานะผู้ปกครองดังนั้นกราฟการแก้ไขในตอนนี้จึงบอกว่าการรวม maint ~ 3 ดังนั้นในความเป็นจริงคุณอาจต้องการใช้ตัวเลือก -m เพื่อ 'git merge' เช่นกันเพื่ออธิบายว่าการบำรุงรักษา ~ 3 กระทำจริง ๆ ถูกเพิกเฉย!

คำสั่งสุดท้ายเพียงรวมส่วนที่เหลือของการบำรุงรักษา (maint ~ 2..maint) เป็นหลักเพื่อให้คุณซิงค์ทั้งหมดอีกครั้ง


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

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

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

3
บ่อยครั้งที่ง่ายกว่าที่จะระบุชื่อการกระทำ ดังนั้นคุณเพียงแค่ต้องดูบันทึกการคอมไพล์ของสาขาที่ต้องรวมและจดแฮชของการกระทำที่ไม่ควรรวมเข้าด้วยกันและบันทึกก่อน - แทนการนับการกระทำ ...
zwirbeltier

14
@ MarkBooth: ความมุ่งมั่นที่คุณต้องการข้ามอาจมีความขัดแย้งอย่างมากกับสาขาที่คุณต้องการผสานมันง่ายกว่าที่จะเพียงแค่ข้ามมันแทนที่จะแก้ไขความขัดแย้งแล้วคืนค่าการเปลี่ยนแปลงนั้นและแก้ไขข้อขัดแย้งอีกครั้ง
SztupY

39

IMHO สิ่งที่สมเหตุสมผลที่สุดในการทำคือการรวมทุกอย่างแล้วใช้ git revert (commit_you_dont_want) เพื่อลบมันที่จะลบออก

ตัวอย่าง:

git merge master
git revert 12345678

หากคุณมีข้อผูกพัน "ที่จะเพิกเฉย" หลายรายการหรือต้องการแก้ไขข้อความย้อนกลับ:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

จากนั้นประวัติของคุณอาจมีลักษณะดังนี้:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

หากคุณมีข้อขัดแย้งที่เกี่ยวข้องกับการ "เพิกเฉย" เหล่านี้เท่านั้นคุณสามารถใช้:

git merge master -X ours

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

หากคุณมีข้อขัดแย้งไม่เพียง แต่มุ่งมั่นที่จะ "เพิกเฉย" คุณควรแก้ไขด้วยตนเองและคุณอาจต้องแก้ไขอีกครั้งในระหว่างการคืนค่า


2
ถ้าคุณต้องการรวมผู้ที่ถูกเปลี่ยนกลับเข้ามาในสาขาเป็นปัญหา Git จะไม่สนใจพวกเขาหรือไม่?
Anriëtte Myburgh

@ AnriëtteMyburghคุณสามารถคืนค่าการพลิกกลับที่จะรวมไว้ในภายหลัง - สิ่งที่คุณไม่สามารถทำได้อย่างง่ายดายด้วยกลยุทธ์ "ผสานของเรา"
Lily Chung

ขอบคุณนี่คือสิ่งที่ฉันต้องการมีผู้ที่มีอายุมากกว่าสองสามคนในสาขาคุณลักษณะที่ฉันไม่ต้องการเป็นเจ้านายและเป็นกลุ่มที่ฉันต้องการเป็นหลัก สวยและสะอาด
Vale Trujillo

17

ความมุ่งมั่นรวมถึงบรรพบุรุษ คุณไม่สามารถรวมการกระทำได้หากไม่รวมการกระทำก่อนหน้า

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


1
ขอบคุณรับเชอร์รี่จะทำงาน ไม่ดีเท่าที่ฉันหวังไว้ แต่มันจะทำ
แบรดโรบินสัน


3

โฆษณาประเภทหนึ่งในโครงการของฉันซึ่งโดยทั่วไปแล้วจะห่อหุ้มกระบวนการที่ @araqnid อธิบายไว้

เป็นผู้ช่วยที่แนะนำ GIT โฟลว์ต่อไปนี้:

  • มีการแจ้งเตือนรายวัน / รายสัปดาห์เกี่ยวกับการรวมที่ค้างอยู่จากสาขาการบำรุงรักษาไปยังสาขา dev / master
  • ผู้ดูแลสาขาตรวจสอบสถานะและตัดสินใจด้วยตนเองว่าจะต้องใช้การคอมมิททั้งหมดหรือไม่และทำการบล็อกพวกเขาหรือขอให้ผู้พัฒนาบล็อกตัวเอง ในตอนท้ายสาขาการบำรุงรักษาจะรวมเข้ากับ upsteam

คำพูดจากหน้าโครงการ:

ขึ้นอยู่กับเวิร์กโฟลว์เป็นไปได้ที่จะมีการบำรุงรักษาหรือสาขาเฉพาะลูกค้าพร้อมกับสาขาหลัก สาขาเหล่านี้เรียกว่าสาขา LTS

บ่อยครั้งที่ hot fix เข้าสู่สาขาที่มีการรายงานข้อผิดพลาดจากนั้นคอมมิชชันจะถูกรวมกลับเข้าไปในสาขาหลัก

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

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

นอกจากนี้ในกรณีที่มีการเก็บเชอร์รี่จากอาจารย์ลงในสาขาการบำรุงรักษาการกระทำที่เกิดขึ้นจะถูกปิดกั้นในต้นแบบ


0

สร้างสาขาที่สามสำหรับการเปลี่ยนแปลงที่คุณต้องการใน master10 แต่ไม่ใช่ใน master20 พิจารณา master10 เป็น "master" ของคุณสาขาที่มั่นคงที่สุดของทุกคนเสมอ สาขาทุกสาขาอื่น ๆ ต้องการที่จะซิงค์กับตลอดเวลา


ฉันเดาว่ามันสามารถใช้งานได้ แต่ฉันได้เข้าสู่สถานะนี้แล้วและสาขาที่สามอาจทำให้ฉันสับสนมากยิ่งขึ้น :)
แบรดโรบินสัน

0

แทนที่จะเป็นrevertหรือcherry-pickในกรณีนี้คุณต้องได้รับคอมไพล์เพื่อพิจารณาการเปลี่ยนแปลงที่คุณกำลังจะข้ามไปจะเก่ากว่าที่คุณทำ

ดังนั้น:

  1. รวมการคอมมิชชันล่าสุดก่อนคอมมิทที่คุณต้องการข้าม แน่นอนว่าจะรวมการกระทำทั้งหมดก่อนหน้า git merge ccc
  2. รวมความมุ่งมั่นที่คุณต้องการข้าม git merge fff --no-commit
  3. ยกเลิกการเปลี่ยนแปลงทั้งหมดยกเลิกการเปลี่ยนแปลงทั้งหมด (อาจมีคำสั่งที่เข้าใจผิดได้สำหรับเรื่องนี้ แต่ฉันจะทำส่วนนี้ใน UI - แต่คุณรู้วิธี)
  4. ทำการผสานให้เสร็จสมบูรณ์ git merge --continue
  5. ผสานคอมมิชชันหลังจากที่คุณต้องการข้าม git merge source-branch-head

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

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