ฉันจะวางการเปลี่ยนแปลงที่ไม่ได้ผูกมัดไว้ในขณะที่ทำงานอย่างอื่นได้อย่างไร


98

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

คำตอบ:


133

คุณมีตัวเลือกมากมาย:

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

    hg shelve --all --name "UnfinishedChanges"
    
    hg unshelve --name "UnfinishedChanges"
    

    อัปเดต / แก้ไข : เมอร์คิวเรียลเวอร์ชันใหม่กว่าอาจจำเป็นต้องใช้

    hg shelve -n "UnfinishedChanges"
    hg unshelve "UnfinishedChanges"
    

    คุณยังสามารถใช้--nameเป็นทางเลือกอื่นได้-nแต่ Mercurial ดูเหมือนจะไม่ชอบ--nameอีกต่อไป นอกจาก--allนี้ไม่จำเป็นต้องใช้อีกต่อไปและในความเป็นจริงแล้ว Mercurial จะประหลาดกว่านั้น

  2. Patch คิวmqรายการที่ใช้ สิ่งนี้ไม่ได้แตกต่างจากการเก็บเข้าลิ้นชักในบางประเด็น แต่มีพฤติกรรมที่แตกต่างกัน ผลลัพธ์สุดท้ายจะเหมือนกันการเปลี่ยนแปลงจะถูกลบออกและสามารถเลือกใช้ซ้ำได้ในภายหลัง เมื่อถูกผลักแพตช์จะเป็นชุดการเปลี่ยนแปลงเชิงตรรกะเมื่อเปิดขึ้นมาจะถูกบันทึกไว้ที่อื่นและไม่ได้เป็นส่วนหนึ่งของประวัติการเปลี่ยนแปลงชุด

    hg qnew "UnfinishedWork"
    hg qrefresh
    hg qpop
    
    hg qpush "UnfinishedWork"
    
  3. ยอมรับในเครื่องอัปเดตเป็นชุดการเปลี่ยนแปลงก่อนหน้าและทำงานต่อไปและใช้ประโยชน์จากสาขาที่ไม่ระบุชื่อ (หรือหลายหัว) หากคุณต้องการการเปลี่ยนแปลงคุณสามารถรวมหัวได้ หากคุณไม่ต้องการการเปลี่ยนแปลงคุณสามารถตัดชุดการเปลี่ยนแปลงได้

    hg commit -m"Commiting unfinished work in-line."
    hg update -r<previous revision>
    
    hg strip -r<revision of temporary commit>
    
  4. มอบหมายให้สาขาที่มีชื่อ จากนั้นเวิร์กโฟลว์จะเหมือนกับตัวเลือกที่ 3 - ผสานหรือสตริปเมื่อคุณพร้อม

    hg branch "NewBranch"
    hg commit -m"Commiting unfinished work to temporary named branch."
    hg update <previous branch name>
    

โดยส่วนตัวแล้วฉันใช้ตัวเลือก 3 หรือ 4 เนื่องจากฉันไม่รังเกียจที่จะลอกชุดการเปลี่ยนแปลงหรือการตรวจสอบโค้ดบางส่วน (ตราบเท่าที่ไม่ได้รับการผลักดันในที่สุด) สามารถใช้ร่วมกับPhaseใหม่ได้เพื่อซ่อนชุดการเปลี่ยนแปลงในเครื่องของคุณจากผู้ใช้รายอื่นหากจำเป็น

ฉันยังใช้rebaseคำสั่งเพื่อย้ายชุดการเปลี่ยนแปลงไปรอบ ๆ เพื่อหลีกเลี่ยงการผสานที่การผสานจะไม่เพิ่มอะไรในประวัติของรหัส การผสานฉันมักจะบันทึกสำหรับกิจกรรมระหว่างสาขาที่สำคัญ (เช่นสาขาการเผยแพร่) หรือกิจกรรมจากสาขาคุณลักษณะที่มีอายุการใช้งานยาวนานขึ้น นอกจากนี้ยังมีhisteditคำสั่งที่ฉันใช้สำหรับการบีบอัดชุดการเปลี่ยนแปลงโดยที่ "การพูดคุย" ของพวกเขาจะลดค่าลง

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

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


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

@Erik เป็นไปได้ แต่ฉันไม่มีประสบการณ์ในการใช้งาน
Adam Houldsworth

2
คุณสามารถใช้บุ๊กมาร์กเพื่อช่วยในตัวเลือกที่ 3 - คุณสามารถใช้อันหนึ่งเพื่อติดป้ายกำกับการแก้ไขที่คุณสร้างขึ้นเพื่อซ่อนการเปลี่ยนแปลงของคุณ พวกเขาไม่สามารถทำงานได้ด้วยตัวเอง
Steve Kaye

--allไม่รู้จักตัวเลือกนี้ มันเป็นพฤติกรรมเริ่มต้นที่จะระงับการเปลี่ยนแปลงทั้งหมดอยู่ดี
naXa

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

23

โดยส่วนตัวแล้วฉันไม่ชอบคำตอบใด ๆ ที่โพสต์ไว้:

  1. ฉันไม่ชอบโคลนแยกทางเพราะผมชอบแต่ละโครงการจะมีเพียงหนึ่งไดเรกทอรี การทำงานกับไดเรกทอรีที่แตกต่างกันในเวลาเดียวกันทำให้ประวัติของไฟล์ล่าสุดของบรรณาธิการของฉันยุ่งเหยิง ฉันมักจะเปลี่ยนไฟล์ผิดเสมอ ฉันจึงไม่ทำแบบนั้นอีกต่อไป
  2. ฉันใช้shelveสำหรับการแก้ไขอย่างรวดเร็ว (เพียงเพื่อย้ายการเปลี่ยนแปลงที่ไม่ได้รับคำแนะนำไปยังสาขาอื่นหากฉันรู้ว่าฉันทำผิด) คุณกำลังพูดถึงวันไม่มีทางที่ฉันจะเก็บบางสิ่งไว้เป็นเวลาหลายวัน
  3. ฉันคิดว่าmqมันซับซ้อนเกินไปสำหรับสถานการณ์ธรรมดา ๆ แบบนี้

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

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

hg ci -m "Working on new stuff"

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

hg bookmark new-stuff

กลับไปที่ชุดการเปลี่ยนแปลงก่อนการปรับเปลี่ยนเหล่านี้

hg update A

จากตรงนี้คุณทำงานและสร้างชุดการเปลี่ยนแปลง C ตอนนี้คุณมี 2 หัว (B และ C) คุณจะได้รับการเตือนเมื่อคุณพยายามผลักดัน คุณสามารถผลักดันสาขาได้เพียงสาขาเดียวโดยระบุหัวหน้าสาขานั้น:

hg push -r C

หรือจะเปลี่ยนเฟสของnew-stuffสาขาเป็นความลับก็ได้ การเปลี่ยนแปลงลับจะไม่ถูกพุช

hg phase -r new-stuff --secret --force

ขอบคุณสำหรับคำตอบโดยละเอียด! ฉันชอบอ่านเวิร์กโฟลว์ของผู้คนสำหรับปัญหาเหล่านั้น (ธรรมดา?)
Erik

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

12

หากต้องการรักษาการเปลี่ยนแปลงที่ไม่ถูกต้องในเครื่องวิธีที่ง่ายที่สุดสำหรับฉันคือบันทึกเป็นไฟล์แก้ไข

hg diff > /tmp/`hg id -i`.patch

และเมื่อคุณต้องการกลับสู่สถานะก่อนหน้า:

hg up <REV_WHERE_SAVED>
hg patch --no-commit /tmp/<REV_WHERE_SAVED>.patch

ฉันจะเปลื้องผ้า/tmpและhg id -iมันจะใช้ได้กับ Windoze ด้วย
anatoly techtonik

และhg upไม่จำเป็นต้องมี
anatoly techtonik

1
@techtonik จะเกิดอะไรขึ้นถ้าฉันใช้โปรแกรมแก้ไขในการแก้ไขอื่น โดยเฉพาะอย่างยิ่งหากมีการแก้ไขไฟล์ที่ถูกแก้ไข
mapcuk

Mercurial จะพยายามรวมเข้าด้วยกันและคุณจะต้องจัดการกับความขัดแย้งอยู่ดี
anatoly techtonik

6

คุณสามารถโคลน repo ของคุณได้หลายครั้ง ฉันมักจะมีรูทโคลนจากนั้นก็มีลูกหลายตัวจากที่นั่น ตัวอย่าง:

  • MyProject.Root
  • MyProject.BugFix1
  • MyProject.BugFix2
  • MyProject.FeatureChange1
  • MyProject.FeatureChange2

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

ดังนั้นในกรณีของคุณคุณเพียงแค่โคลน repo ใหม่และเริ่มทำงาน ปล่อยให้งาน 'Shelved' ของคุณอยู่คนเดียวใน repo อื่น ๆ มันง่ายมาก

ข้อเสียเพียงอย่างเดียวคือการใช้พื้นที่ดิสก์ แต่หากเป็นข้อกังวลคุณจะไม่ได้ใช้ DVCS เลย;) โอ้และมันจะสร้างมลพิษให้กับรายการ "โครงการล่าสุด" ของ Visual Studio แต่สิ่งที่เฮ้

[แก้ไขความคิดเห็นต่อไปนี้]: -

สรุปได้ว่า ... สิ่งที่คุณทำนั้นดีและเป็นเรื่องปกติ ฉันขอยืนยันว่ามันเป็นวิธีที่ดีที่สุดในการทำงานเมื่อสิ่งต่อไปนี้เป็นจริง: 1) มันมีอายุสั้น 2) คุณไม่จำเป็นต้องร่วมมือกับนักพัฒนาคนอื่น ๆ 3) การเปลี่ยนแปลงไม่จำเป็นต้องออกจากพีซีของคุณจนกว่าจะกระทำ / เวลาผลักดัน


เหตุผลใดที่ไม่ใช้สาขา? นี่คือสิ่งที่พวกเขามีไว้และเร็วกว่าการทำ repo-cloning มาก
Adam Houldsworth

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

1
@AdamHouldsworth ในทางเทคนิคเหล่านี้เป็นสาขา ... การสร้างสาขาที่มีชื่อสำหรับชิ้นงานอายุสั้นเป็นเรื่องที่โง่มาก เป็นการละเมิดวัตถุประสงค์ที่ตั้งชื่อสาขาซึ่งมีไว้สำหรับเรื่องราวการทำงานที่ยาวนาน
nbevans

@NathanE หากคุณคิดว่าสาขาที่มีชื่อสำหรับงานอายุสั้นนั้น "โง่ไปหมด" ก็ยังมีการแยกสาขาการเก็บเข้าลิ้นชักหรือคิวการแก้ไขแบบไม่ระบุชื่อเป็นตัวเลือกอื่น ๆ ที่มีน้ำหนักเบา ในความคิดของฉันการโคลนซ้ำนั้นโง่พอ ๆ กันเมื่อต้องเผชิญกับตัวเลือกอื่น ๆ - ข้อดีอย่างหนึ่งที่เป็นไปได้คือการเปิดโค้ดสองชุดในอินสแตนซ์ VS สองชุด แต่ฉันแทบไม่ต้องทำเช่นนี้โดยใช้โคลนเป็นหลัก ไม่ให้บริการฉัน เพื่อความชัดเจนฉันไม่ได้เป็นผู้ลงคะแนน
Adam Houldsworth

@NathanE พวกเขาไม่ได้เป็นเอกสิทธิ์สำหรับ "เรื่องราวการทำงานที่ยาวนาน" นั่นเป็นเพียงสิ่งที่พวกเขาทำได้ดีหากคุณติดตามการบูรณาการอย่างต่อเนื่อง ตรงจากเอกสาร : "สาขาเกิดขึ้นหากสายการพัฒนาแตกต่างกัน" หากคุณเก็บรายการงานเพื่อทำงานอย่างอื่นสำหรับฉันสิ่งนี้ดูเหมือนจะแตกต่างกันโดยไม่คำนึงว่าจะมีอายุนานเท่าใด
Adam Houldsworth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.