Hg: วิธีทำ rebase เช่น rebase ของคอมไพล์


207

ใน Git ฉันสามารถทำสิ่งนี้:

1. เริ่มทำงานกับคุณสมบัติใหม่:
$ git co -b newfeature-123 # (สาขาการพัฒนาคุณลักษณะท้องถิ่น)
ทำไม่กี่กระทำ (M, N, O)

ปรมาจารย์ A --- B --- C
                \
newfeature-123 M --- N --- O

2. ดึงการเปลี่ยนแปลงใหม่จากต้นแบบต้นน้ำ:
$ git pull
(อัปเดตข้อมูลหลักด้วย ff-commits)

ปรมาจารย์ A --- B --- C --- D --- E --- F
                \
newfeature-123 M --- N --- O

3. Rebase off master เพื่อให้ฟีเจอร์ใหม่ของฉัน 
สามารถพัฒนาต่อการเปลี่ยนแปลงต้นน้ำล่าสุด:
(จาก newfeature-123)
$ git rebase master

ปรมาจารย์ A --- B --- C --- D --- E --- F
                            \
newfeature-123 M --- N --- O


ฉันต้องการรู้วิธีการทำสิ่งเดียวกันใน Mercurial และฉันได้ค้นหาเว็บเพื่อหาคำตอบ แต่สิ่งที่ดีที่สุดที่ฉันสามารถหาได้คือ: git rebase - สามารถ hg ทำได้

ลิงค์นั้นมี 2 ตัวอย่าง:
1. ฉันจะยอมรับสิ่งนี้: (แทนที่การแก้ไขจากตัวอย่างด้วยสิ่งเหล่านั้นจากตัวอย่างของฉันเอง)

hg up -CF  
สาขา hg -f newfeature-123  
การปลูกถ่าย hg -a -b newfeature-123 

ไม่เลวร้ายนักยกเว้นว่าจะทิ้งไว้ข้างหลัง pre-rebase MNO ในฐานะ unmerged head และสร้าง 3 คอมมิชชันใหม่ M ', N', O 'ที่เป็นตัวแทนของพวกเขาแยกออกจากการปรับปรุงการฉีด

โดยทั่วไปปัญหาคือฉันท้ายด้วยสิ่งนี้:

ปรมาจารย์ A --- B --- C --- D --- E --- F
                \ \
newfeature-123 \ M '--- N' --- O '
                  \
newfeature-123 M --- N --- O

มันไม่ดีเพราะมันทิ้งไว้ข้างหลังความมุ่งมั่นที่ไม่พึงประสงค์ที่ควรทิ้งไว้

  1. ตัวเลือกอื่นจากลิงค์เดียวกันคือ
hg qimport -r M: O
hg qpop -a
hg up F
สาขา hg newfeature-123
hg qpush -a
hg qdel -r qbase: qtip

และนี่จะส่งผลให้กราฟที่ต้องการ:

ปรมาจารย์ A --- B --- C --- D --- E --- F
                            \
newfeature-123 M --- N --- O

แต่คำสั่งเหล่านี้ (ทั้งหมด 6 คำสั่ง!) ดูเหมือนจะซับซ้อนกว่า

$ git rebase master

ฉันต้องการทราบว่านี่เป็น Hg เทียบเท่าเท่านั้นหรือหากมีวิธีอื่นที่ใช้งานง่ายเช่น Git


7
"สิ่งนี้ไม่ดีเพราะมันทิ้งไว้ข้างหลังการกระทำที่ไม่พึงประสงค์ในท้องถิ่นที่ควรทิ้งไว้" - จริง ๆ แล้วคอมไพล์ทำสิ่งเดียวกัน มันไม่ได้เปลี่ยนหรือลบคอมมิชชันในสาขาดั้งเดิมมันแค่สร้างสิ่งใหม่ที่ใช้การเปลี่ยนแปลงชุดเดียวกันกับด้านบนของมาสเตอร์ คุณยังคงสามารถเข้าถึงของเก่าที่ใช้git reflogและพวกเขาจะไม่หายไปทั้งหมดจนกว่าพวกเขาจะได้รับการเก็บขยะ หากคุณต้องการให้พวกเขาอยู่ในสาขาที่มีชื่อเพื่อที่คุณจะได้ไม่ต้องใช้ reflog ให้ทำgit branch feature-123_originalก่อนที่จะทำการรีบูต
MatrixFrog

5
คำถามแบบสุ่ม: คุณได้ทำการเชื่อมโยงการเปลี่ยนแปลง / แยกตัวคุณเองหรือมีเครื่องมือที่ทำเช่นนั้นหรือไม่?
Amir Rachum

2
เพียงแค่พวกเขาเองด้วย TextWrangler ตั้งค่าเป็น "เขียนทับ"
jpswain

คำตอบ:


235

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

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

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

ตอนนี้ไปเลือกคำตอบของ VonC ในขณะที่ฉันวางสบู่ไว้ :)


18
หมายเหตุ: ปิดแน่นอน Git ไม่ตรงช่วยให้คุณสามารถที่จะเขียนประวัติศาสตร์เท่านั้นที่จะสร้างใหม่ได้อย่างง่ายดาย ( utcc.utoronto.ca/~cks/space/blog/tech/GitNewHistory ) ด้วยการเพิ่ม RebaseExtension Mercurial จะมอบวิธีการที่สะดวกสบายเหมือนเดิมในการแทนที่ประวัติเก่าด้วยประวัติใหม่ ทำไม? เนื่องจากการผสานไม่ใช่คำตอบที่ถูกต้องเสมอไปโดยเฉพาะอย่างยิ่งเมื่อการเปลี่ยนแปลงของคุณควรถูกมองว่าเป็นวิวัฒนาการด้านบนของ F และไม่ใช่การย้อนกลับ (P รวมอยู่ด้านบนของ O)
VonC

19
VonC ฉันเห็นด้วยการผสานไม่ใช่ทางเลือกที่ถูกต้องเสมอไป แต่ฉันคิดว่าความแตกต่างคือสิ่งที่ต้องการให้ประวัติ VCS ของคน ๆ หนึ่งสามารถบอกได้ ผมคิดว่าประวัติศาสตร์ควรเสมอจะสามารถที่จะตอบคำถามเช่น "สิ่งที่เป็นวิธีการที่ผมพยายามที่จะบูรณาการมันเป็นครั้งแรกที่ไม่ทำงานออกไปและผมคิดว่าไม่มีประโยชน์ที่เวลา" นักวิทยาศาสตร์เก็บสมุดบันทึกด้วยปากกาพร้อมหน้าตัวเลขและวิศวกรซอฟต์แวร์ AFAIC ควรบันทึกทุกไบต์ที่พวกเขาเคยพิมพ์ การเขียนซ้ำประวัติศาสตร์แม้กระทั่งความเป็นบิดามารดา แต่แน่นอนว่า CollapseExtension, HistEdit ฯลฯ ละเมิดนั้น มันเป็นเรื่องของการเลือกส่วนบุคคลโดยสิ้นเชิง
Ry4an Brase

14
+1 สำหรับตัวเลือกส่วนบุคคล ด้วย Git ฉันจึงใช้ rebase สำหรับ diverges เล็ก ๆ น้อย ๆ และรวมสำหรับที่ไม่สำคัญ สิ่งนี้ช่วยให้ฉันรักษาประวัติรวมที่ฉันรู้สึกว่าสำคัญ แต่ทำให้บันทึกสะอาดและเป็นเส้นตรงเกือบตลอดเวลา
คอส

16
นอกจากนี้ฉันยังทำรายการรีแอคทีฟมากมายเพราะฉันมักจะทำคอมมิชชันเล็ก ๆ จำนวนมากจากนั้นเข้าร่วมติดฉลากและทำความสะอาดจากนั้นรวมพวกเขากลับเข้ากับสาขาหลัก (หรือรีบาสบนสุด) ฉันชอบการเข้ารหัสและการจัดการการเปลี่ยนแปลงเป็นขั้นตอนแยกต่างหาก
คอส

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

104

คุณอาจจะมองหาRebase ขยาย (นำมาใช้เป็นส่วนหนึ่งของSummerOfCode 2008 )

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

ได้รับจาก :

ข้อความแสดงแทน

ถึง:

ข้อความแสดงแทน


ตามความเห็นด้านล่างโดยsteprobe :

ในกรณีที่คุณไม่ได้ดึงการเปลี่ยนแปลงและคุณมีสองสาขาใน repo ของคุณคุณสามารถทำได้ ( โดยใช้keepbranches ):

hg up newfeature-123 
hg rebase -d master --keepbranches

( --keepbranches: รับชื่อสาขาเดิม)

Mojcaกล่าวถึง:

ฉันชอบใช้hg rebase --source {L1's-sha} --dest {R2's-sha}แต่ฉันไม่รู้ว่าฉันจะเพิ่มได้--keepbranchesในตอนท้าย

ตามที่แสดงด้านล่างโดยJonathan Blackburn :

 hg rebase -d default --keepbranches

1
ฉันดูส่วนขยาย Rebase แล้ว แต่ก็ยังไม่ชัดเจนสำหรับฉัน คุณช่วยอธิบายขั้นตอนในการทำสิ่งที่ฉันได้อธิบายไว้ข้างต้นได้ไหม
jpswain

6
ในกรณีที่คุณไม่ได้ดึงการเปลี่ยนแปลงและคุณมีสองสาขาใน repo ของคุณคุณสามารถทำได้: hg up newfeature-123ตามด้วยhg rebase -d master --keepbranches
steprobe

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

@steprobe: ขอบคุณสำหรับคำแนะนำในการใช้ --keepbranches ฉันชอบใช้hg rebase --source {L1's-sha} --dest {R2's-sha}แต่ฉันไม่รู้ว่าฉันจะเพิ่มได้--keepbranchesในตอนท้าย สิ่งนี้ถูกกล่าวถึงในคำตอบอันดับต่ำ ๆ อื่น ๆ แต่มันก็ดีที่เขียนไว้ในคำตอบนี้ด้วย
Mojca

@ Mojca ไม่มีปัญหา ฉันได้แก้ไขคำตอบแล้ว
VonC

44

สมมติว่าคุณมีการติดตั้ง Hg ที่ทันสมัยคุณสามารถเพิ่ม:

[extensions]
rebase = 

เป็น ~ / .hgrc

แล้วคุณสามารถใช้คำสั่งhg rebase, หรือhg pull --rebasehg help rebase


2
เพียงเพิ่มคำสั่งนี้ในเงื่อนไขของคำสั่งคุณจะต้องดำเนินการดังนี้: hg rebase -s o -d f
Simple-Solution

21

ฉันไม่คิดว่าคำตอบข้างต้นจะบรรลุเป้าหมายของ OP ซึ่งก็คือการรักษาสาขางานของเขาเพียงแค่ rebased กับจุดต่อมาในสาขาหลัก

สมมติว่าฉันเริ่มต้นด้วยกราฟนี้ (สร้างโดยใช้ส่วนขยาย Graphlog ความรักที่จริงจังสำหรับ Graphlog)

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

ถ้าฉันในสาขา feature3 และต้องการที่จะ rebase มันออกจาก againagainagain hg rebase -d defaultกระทำฉันเข้าใจว่าฉันจะวิ่ง นี่คือผลลัพธ์ต่อไปนี้:

@  89dada24591e Feature 3 commit 2 tip 
|
o  77dcce88786d Feature 3 branch commit 1  
|
o  af630ccb4a80 default againagainagain  
|
o  e9f850ac41da foo  

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

ใน Git ผลลัพธ์จะเป็นดังนี้:

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

ขอให้สังเกตว่าสาขาย่อย feature3 ยังคงมีอยู่ทั้งสองกระทำยังคงอยู่ในสาขา feature3 และไม่สามารถมองเห็นได้ตามค่าเริ่มต้น โดยไม่ต้องรักษาสาขางานฉันไม่เห็นว่าสิ่งนี้แตกต่างจากการรวมหน้าที่อย่างไร

UPDATE : ฉันค้นพบการ--keepbranchesตั้งค่าสถานะที่รองรับโดยการรีบูต hg และฉันยินดีที่จะรายงานทุกอย่างที่เป็น okey-dokey ใช้hg rebase -d default --keepbranchesฉันทำซ้ำพฤติกรรม Git ที่ฉันอยาก สองนามแฝงในภายหลังและฉันกำลัง rebasing เหมือนไม่มีใครทำธุรกิจของ


7
เพิ่งค้นพบแฟล็ก --keepbranches เมื่อรีบูต แก้ไขปัญหา. นี่เป็นรหัสของฉันหรือเปล่าฉันจะทำให้เป็นค่าเริ่มต้น แต่นั่นเป็นเพียงฉัน
Jonathan Blackburn

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

3

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

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

x265 ร่วมสมทบหน้าอธิบายวิธีการใหม่กระทำชุดของการเปลี่ยนแปลงที่คุณกำลังทำงานเพื่อให้ได้พวกเขาพร้อมสำหรับการส่งให้กับโครงการ x265 (รวมถึงการใช้ TortoiseHG เพื่อคอมมิทการเปลี่ยนแปลงบางอย่าง แต่ไม่ใช่ทั้งหมดในไฟล์เดี่ยว ๆ เช่น git gui stage / unstage diff hunk เพื่อคอมมิท)

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

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

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