Differences between revisions 2 and 4 (spanning 2 versions)
Revision 2 as of 2008-11-19 15:40:23
Size: 19371
Comment: Changed tutorial index link to Thai index
Revision 4 as of 2008-11-21 17:28:27
Size: 20693
Comment: Edit contents to make reading easier.
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
== บทเรียน - รวมการแก้ไขจากหลายๆ repository ==

''(หน้านี้เป็นหน้าที่ 7 จาก 9 ของ[:ThaiTutorial:บทเรียน]การใช้งาน Mercurial  หน้าก่อนหน้าคือ [:ThaiTutorialExport], หน้าถัดไปคือ [:ThaiTutorialConflict])''

ใน [:ThaiTutorialExport] เราได้เรียนวิธีการแบ่งปันการแก้ไขกับบุคคลอื่น ในบทนี้เราจะเรียนรู้วิธีการ[:Merge:รวมการแก้ไข]โดยการ[:Pull:ดึงการแก้ไข]จาก [:Repository:repository] ที่มีการแก้ไขที่แตกต่างกั

ก่อนอื่นเราจะต้องสร้าง repository สำหรับรวมการแก้ไข  เราต้อง[:Clone:ทำสำเนา] `my-hello` repository อีกแล้ว:
== บทเรียน - รวมประวัติการแก้ไขจาก repository อื่น ==

''(บทนี้เป็นบทที่ 7 จาก 9 บทของ[:ThaiTutorial:บทเรียนการใช้งาน Mercurial] บทก่อนหน้าคือ [:ThaiTutorialExport:แบ่งปันสิ่งที่คุณแก้ไขกับบุคคลอื่นๆ], บทถัดไปคือ [:ThaiTutorialConflict:รวมประวัติการแก้ไขที่ขัดแย้งกัน])''

ใน[:ThaiTutorialExport:บทที่แล้ว]เราได้เรียนวิธีการแบ่งปันการแก้ไขกับบุคคลอื่นโดยการส่งออกการแก้ไข ในบทนี้เราจะเรียนรู้วิธีการ[:Merge:รวมการแก้ไข]โดยการ[:Pull:ดึงการแก้ไข]จาก [:Repository:repository] อื่

ก่อนอื่นเราจะต้องสร้าง repository สำหรับเป็นที่รวมการแก้ไขซะก่อนโดย[:Clone:ทำสำเนา] repository `my-hello` อีกครั้ง:
Line 16: Line 16:
ทีนี้เราจะแก้ไฟล์ `hello.c` โดยเพิ่มคำอธิบายในส่วนคอมเม้นต์ เราจะแก้ไฟล์ `hello.c` โดยเพิ่มคำอธิบายในส่วนคอมเม้นต์
Line 35: Line 35:
จากนั้นเราต้องบันทึกและปิด editor และ[:Commit:คอมมิท]การแก้ไขของเรา ครั้งนี้เราจะประหยัดเวลาลงหน่อยนึงโดยการใช้ตัวเลือก `-m` กับคำสั่ง `commit` เพื่อจะด้ไม่ต้องไปพิมพ์คำอธิบาย changeset editor: จากนั้นเราต้องบันทึกและปิดโปรแกรม editor และ[:Commit:คอมมิท]การแก้ไขของเรา ครั้งนี้เราจะประหยัดเวลาลงหน่อยโดยการใช้ตัวเลือก `-m` กับคำสั่ง `commit` เพื่อใส่คำอธิบายของเซ็ตการแก้ขที่เราจะคอมมิทเลยแทนที่จะช้โปรแกรม editor:
Line 41: Line 41:
ตอนนี้เรามีการแก้ไขครั้งนึงกับไฟล์ `hello.c` ใน repository `my-hello-new-output` และอีกการแก้ไขนึงกับไฟล์ `hello.c` ใน repository `my-hello-desc` เราจะ''รวม''การแก้ไขที่แตกต่างกันในสอง repository นี้ยังไงล่ะ? และจะมีปัญหาอะไรหรือเปล่าถ้าเราต้องการดึงการเปลี่ยนแปลงจาก repository นึงไปในอีก repository นึง?

ไม่ต้องเป็นห่วง จะไม่มีปัญหาอะไรหรอก ระหว่างที่เราอยู่ใน `my-hello-desc` เราสามารถลองดึงการแก้ไขจาก `my-hello-new-output` และดูกันว่าจะเกิดอะไรขึ้น:
ตอนนี้ไฟล์ `hello.c` ใน repository `my-hello-new-output` และ repository `my-hello-desc` ต่างก็ถูกแก้ไข เราจะ''รวมการแก้ไข''ที่แตกต่างกันในสอง repository นี้ยังไงล่ะ? และจะมีปัญหาอะไรหรือเปล่าถ้าเราต้องการดึงประวัติการเปลี่ยนแปลงจาก repository นึงไปอีก repository นึง?

ไม่ต้องห่วง การทำแบบนี้จะไม่มีปัญหาอะไรหรอก ตอนนี้ระหว่างที่เราอยู่ใน `my-hello-desc` เรามาลองดึงประวัติการแก้ไขจาก `my-hello-new-output` และดูกันว่าจะเกิดอะไรขึ้น:
Line 56: Line 56:
Mercurial บอกว่ามันได้เพิ่ม [:Head:head] อีกอันนึงใน repository ของเรา ถ้าเราอยากดู heads เราต้องใช้คำสั่ง `heads`: Mercurial บอกว่ามันได้เพิ่ม[:Head:ส่วนยอด]อีกอันนึงใน repository ของเรา ถ้าเราอยากดูส่วนยอดทั้งหมดเราต้องใช้คำสั่ง `heads`:
Line 73: Line 73:
Mercurial มาพร้อมกับ [:UsingExtensions:extension] ที่สามารถแสดงกราฟประวัติการแก้ไขของ repository ในแบบ ASCII ได้นั่นก็คือ: [:GraphlogExtension] คุณเพียงแค่ต้องใช้งาน extension นี้ในไฟล์ `~/.hgrc` ของคุณ (หรือในไฟล์ `Mercurial.ini` ในวินโดวส์) โดยเพิ่มบรรทัด  {{{hgext.graphlog = }}} ในส่วน `[extensions]` แบบนี้: ถ้าคุณสนใจ Mercurial มาพร้อมกับ[:UsingExtensions:ส่วนเพิ่มความสามารถ]ที่สามารถแสดงกราฟประวัติการแก้ไขของ repository ในแบบ ASCII ได้นั่นก็คือ: [:GraphlogExtension] คุณเพียงแค่ต้องเปิดการใช้งานส่วนเพิ่มความสามารถนี้ในไฟล์ `~/.hgrc` ของคุณ (หรือในไฟล์ `Mercurial.ini` ในวินโดวส์) โดยเพิ่มบรรทัด {{{hgext.graphlog = }}} ในส่วน `[extensions]` แบบนี้:
Line 80: Line 80:
หลังจากคุณเริ่มใช้งาน extension นี้แล้วคุณจะสามารถใช้คำสั่งใหม่คือ `glog` ได้ทันที (ลองดู `hg help glog`): หลังจากคุณเปิดการใช้งานส่วนเพิ่มความสามารถนี้แล้วคุณจะสามารถใช้คำสั่งใหม่คือ `glog` ได้ทันที (ลองดู `hg help glog`):
Line 107: Line 107:
ในกราฟนี้ คุณจะเห็นว่าเราได้ดึง changeset `86794f718fb1` เข้ามาใน repository (ซึ่งก็เป็น[:Tip:ปลาย]ของ repository ด้วย) เนื่องจากว่าทั้ง changeset `86794f718fb1` และ `c3844fde99f0` ของเราถูกคอมมิทโดยมี changeset ฐานเดียวกันคือ `82e55d328c8c` ([:Parent:บรรพบุรุษ]) จึงเกิดกิ่งการแก้ไขที่แยกกัน – หรือที่มีชื่อเรียกสั้นๆว่า [:Branch:branch] ในตัวอย่างนี้ branch จะมีชีวิตที่ค่อนข้างสั้น และการจัดการกับการแตกกิ่งแบบนี้ก็เป็นเรื่องที่ง่ายมากใน Mercurial

ระหว่างที่ดูผลลัพธ์ของคำสั่ง `pull` คุณอาจจะคิดว่ามันดูคล้ายๆกับผลลัพธ์ในบท [:ThaiTutorialShareChange] นี่นา เพราะอย่างนั้นคุณอาจจะถามว่า: ทำไมไม่ลองใช้คำสั่ง [:Update:update] เลยล่ะ อย่างที่เราทำในบท !ThaiTutorialShareChange? ไม่มีปัญหา เรามาลองดูและดูว่าจะเกิดอะไรขึ้น:
ในกราฟด้านบนคุณจะเห็นว่าเราได้ดึงเซ็ตการแก้ไข `86794f718fb1` เข้ามาใน repository (ซึ่งก็เป็น[:Tip:ส่วนปลาย]ของ repository ด้วย) เนื่องจากว่าทั้งเซ็ตการแก้ไข `86794f718fb1` และ `c3844fde99f0` ของเราถูกคอมมิทโดยมีเซ็ตการแก้ไข[:Parent:บรรพบุรุษ]เดียวกันคือ `82e55d328c8c` จึงเกิด[:Branch:กิ่ง]การแก้ไขที่แยกจากกัน ในตัวอย่างนี้กิ่งแต่ละกิ่งมีชีวิตที่ค่อนข้างสั้น  การจัดการกับการแตกกิ่งแบบนี้ก็เป็นเรื่องที่ง่ายมากใน Mercurial

ระหว่างที่ดูผลลัพธ์ของคำสั่ง `pull` คุณอาจจะคิดว่ามันก็ดูคล้ายๆกับผลลัพธ์ในบท[:ThaiTutorialShareChange:แบ่งปันสิ่งที่คุณแก้ไขกับ repository อื่น]นี่นา เพราะอย่างนั้นคุณอาจจะถามว่า: ทำไมไม่ลองใช้คำสั่ง [:Update:update] เลยล่ะ? ไม่มีปัญหา เรามาลองดูว่าจะเกิดอะไรขึ้นถ้าเราทำอย่างที่ว่า:
Line 116: Line 116:
โอ๊ะโอ มีบางอย่างที่แตกต่างไปแล้ว อย่างที่คุณเห็น Mercurial ระมัดระวังมากและไม่พยายามทำอะไรโง่ๆถ้าเรามองข้ามการแจ้งเตือน "(+1 heads)" ังจากที่เราใช้คำสั่ง `pull` เพราะฉะนั้นเราสามารถแน่ใจได้ว่า Mercurial จะเตือนเราดีๆว่าเราน่าจะทำอย่างอื่นมากกว่า ซึ่งในกรณีนี้ก็คือ เราควรจะรวมการแก้ไข

แต่ก่อนที่เราจะรวมการแก้ไขเรามาตรวจสอบก่อนดีกว่าว่าตอนนี้เรากำลังทำงานอยู่กับ changeset ไหน  เราสามารถใช้คำสั่ง `parents` เพื่อการนี้ (ดู [:Parent]):
โอ๊ะโอ มีบางอย่างที่แตกต่างไปแล้ว อย่างที่คุณเห็น Mercurial ระมัดระวังและพยายามที่จะไม่ทำอะไรแย่ๆถ้าเราไม่ทันเห็นสถานะ "(+1 heads)" ตรงท้ายๆผลัพธ์ของคำสั่ง `pull` Mercurial จะเตือนเราดีๆว่าเราน่าจะทำอย่างอื่นมากกว่า ซึ่งในกรณีนี้ก็คือเราน่าจะรวมประวัติการแก้ไข

ก่อนที่เราจะรวมประวัติการแก้ไขเรามาตรวจสอบกันก่อนดีกว่าว่าตอนนี้เรากำลังทำงานอยู่กับ changeset ไหนโดยใช้คำสั่ง `parents` (ดู [:Parent:บรรพบุรุษ]):
Line 128: Line 128:
คำสั่งนี้บอกเราว่าตอนนี้[:WorkingDirectory:ไดเร็คทอรี่ทำงาน]ของเราอิงกับ changeset `c3844fde99f0` – ซึ่งก็แน่นอนเพราะว่านั่นเป็น changeset ที่เราเพิ่งคอมมิทไป สิ่งสำคัญที่เราจะต้องเข้าใจก็คือ การดึงการแก้ไขเข้ามาเป็นการดึงมาเก็บไว้ที่ ''store'' ของ repository ของเราเท่านั้นแต่ไม่ได้แก้ไขข้อมูลใดๆในไดเร็คทอรี่ทำงานของเราเลยแม้แต่น้อย ลองดูผลลัพธ์ของคำสั่ง `glog` อีกทีสิ: มี changeset นึงที่ถูกให้สัญลักษณ์ด้วยเครื่องหมาย "`@`" นั่นหมายความว่า changeset นั้นเป็นบรรพบุรุษของไดเร็คทอรี่ที่เรากำลังทำงานอยู่ หรืออีกนัยนึงก็คือ เรากำลัง "อยู่ที่" `c3844fde99f0`

โอเค เรามาลองรวมการแก้ไขกันเลยดีกว่า การรวมการแก้ไขฟังดูค่อนข้างยากเนอะ? แต่จริงๆแล้วมันเป็นอะไรที่ง่ายมาก เรามาลองทำตามขั้นตอนที่อยู่ในบรรทัดสุดท้ายของผลลัพธ์จากคำสั่ง `pull` กันดู:
คำสั่งนี้บอกเราว่าตอนนี้[:WorkingDirectory:ไดเร็คทอรี่สำหรับใช้ทำงาน]ของเราตรงกับเซ็ตการแก้ไข `c3844fde99f0` อยู่ – ซึ่งก็แน่นอนเพราะว่านั่นเป็นเซ็ตการแก้ไขที่เราเพิ่งคอมมิทไป สิ่งสำคัญที่เราจะต้องเข้าใจก็คือ การดึงประวัติการแก้ไขเป็นการดึงมาเก็บไว้ที่''ที่จัดเก็บประวัติ''ของ repository เท่านั้น แต่ไม่ได้อัพเดทข้อมูลใดๆในไดเร็คทอรี่สำหรับใช้ทำงานของเราเลยแม้แต่น้อย ลองดูผลลัพธ์ของคำสั่ง `glog` อีกทีสิ: มีเซ็ตการแก้ไขนึงที่ถูกให้สัญลักษณ์ด้วยเครื่องหมาย "`@`" นั่นก็หมายความว่าเซ็ตการแก้ไขนั้นเป็นบรรพบุรุษของไดเร็คทอรี่ที่เรากำลังทำงานอยู่ หรือจะพูดอีกแบบก็คือเรากำลังทำงาน"อยู่ตรง"เซ็ตการแก้ไข `c3844fde99f0`

โอเค อธิบายมาซะยาวจนเบื่อแล้ว เรามาลองรวมการแก้ไขกันเลยดีกว่า การรวมการแก้ไขฟังดูค่อนข้างยากเนอะ? แต่จริงๆแล้วมันเป็นอะไรที่ง่ายมาก ลองทำตามคำแนะนำจาก Mercurial ที่อยู่ในบรรทัดสุดท้ายของผลลัพธ์จากคำสั่ง `pull` ดู:
Line 139: Line 139:
แค่นั้นแหละ! Mercurial ได้ทำการรวมการเปลี่ยนแปลงให้คุณโดยอัตโนมัติเพราะว่าการเปลี่ยนแปลงทั้งสองนั้นไม่มีอะไรที่ขัดแย้งกันเลย (เราจะพูดถึงการเปลี่ยนแปลงที่มีความขัดแย้งในบท [:ThaiTutorialConflict]) ทีนี้ถ้าเราลองดูเนื้อหาของไฟล์ `hello.c` ในไดเร็คทอรี่ทำงานเราจะเห็นว่าไฟล์มีเนื้อหาจากการเปลี่ยนแปลงทั้งที่มาจาก `my-hello-new-output` และ `my-hello-desc` ตามคาด

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

โอเค ตอนนี้เรายังไม่ได้คอมมิทผลของการรวม ก่อนที่เราจะทำลองมาดูกันว่าผลลัพธ์ของคำสั่ง `parents` จะเป็นยังไง (เราใช้คำสั่งย่อ `par`):
เรียบร้อย! Mercurial รวมการเปลี่ยนแปลงให้คุณโดยอัตโนมัติเพราะว่าการเปลี่ยนแปลงทั้งสองนั้นไม่มีอะไรที่ขัดแย้งกันเลย (เราจะพูดถึงการเปลี่ยนแปลงที่มีความขัดแย้งใน[:ThaiTutorialConflict:บทถัดไป]) ถ้าเราลองดูเนื้อหาของไฟล์ `hello.c` ในไดเร็คทอรี่สำหรับใช้ทำงานเราจะเห็นว่าไฟล์มีเนื้อหาจากการเปลี่ยนแปลงที่มาจาก `my-hello-new-output` และ `my-hello-desc` ทั้งคู่ตามที่คาดไว้

โดยทั่วๆไป กรณีตัวอย่างนี้เป็นกรณีที่มักจะเกิดขึ้นบ่อยเป็นอันดับสอง กรณีที่เกิดบ่อยที่สดนั้นยิ่งง่ายกว่านี้อีก นั่นก็คอการแก้ไขทั้งสองที่ถูกรวมเป็นการแก้ไขที่เกิดขึ้นกับคนละไฟล์ ซึ่งก็หมายความว่าเวลาคุณใช้คำสั่ง `merge` จะไม่มี''ไฟล์''อะไรที่จะต้องรวมเนื้อหาด้วยซ้ำ

ตอนนี้เรายังไม่ได้คอมมิทผลของการรวมการแก้ไข ก่อนที่เราจะทำลองมาดูกันว่าผลลัพธ์ของคำสั่ง `parents` จะเป็นยังไง (เราใช้คำสั่งย่อ `par`):
Line 160: Line 160:
คำสั่งนี้บอกเราว่าไดเร็คทอรี่ทำงานของเรานั้นอิงกับ changesets ''สอง''อัน: หรือจะเรีกว่ามีบรรพบุรุษสองอันก็ได้ สังเกตุว่าบรรพบุรุษทั้งสองได้ถูกเรียงลำดับ: บรรพบุรุษแรก (parent 1) คือ changeset ก่อนหน้าของเรานั่นก็คือ `c3844fde99f0` ที่เราเพิ่มคำอธิบายใน `hello.c`  changeset นี้เป็นบรรพบุรุษของไดเร็คทอรี่ทำงานของเราก่อนที่เราจะใช้คำสั่ง `merge` ส่วนบรรพบุรุษที่สอง (parent 2) คือ changeset `86794f718fb1` ซึ่งเราได้ดึงมาจากอีก repository นึงและเป็น changeset ที่เราเพิ่งรวมเข้าไป

ลองใช้คำสั่ง `glog` อีกทีแล้วเราจะเห็นว่าสัญลักษณ์ `@` อยู่กับบรรพบุรุษทั้งสองแล้ว:
คำสั่งนี้บอกเราว่าไดเร็คทอรี่สำหรับใช้ทำงานของเรานั้นมีเซ็ตการแก้ไขที่เป็นบรรพบุรุษ''สอง''เซ็ต โดยสังเกตุว่าบรรพบุรุษทั้งสองได้ถูกเรียงลำดับดังนี้: บรรพบุรุษแรก (parent 1) คือเซ็ตการแก้ไขก่อนหน้าของเรานั่นก็คือ `c3844fde99f0` ที่เราเพิ่มคำอธิบายใน `hello.c` ซึ่งเซ็ตการแก้ไขนี้เป็นบรรพบุรุษของไดเร็คทอรี่สำหรับใช้ทำงานของเราก่อนที่เราจะใช้คำสั่ง `merge` ส่วนบรรพบุรุษเซ็ตที่สอง (parent 2) คือ `86794f718fb1` ซึ่งเราได้ดึงมาจากอีก repository นึงและเป็นเซ็ตการแก้ไขที่เราเพิ่งรวมเข้าไป

ลองใช้คำสั่ง `glog` อีกทีแล้วเราจะเห็นว่าสัญลักษณ์ `@` อยู่ที่บรรพบุรุษทั้งสองแล้ว:
Line 189: Line 189:
/!\ หมายเหตุ: ถ้าคุณเกิดเปลี่ยนใจและต้องการยกเลิกการรวมก่อนที่จะคอมมิทอะไร คุณจะต้องใช้คำสั่ง "`hg update -C -r.`" เพื่อย้อนกลับไปที่ revision 2 การใช้คำสั่ง `hg revert -r2 --all` จะแค่ยกเลิกการรวมเนื้อหาของไฟล์ในไดเร็คทอรี่ทำงานของคุณ แต่จะ __ไม่แก้ไขบรรพบุรุษของไดเร็คทอรี่ทำงานกลับเป็นบรรพบุรุษเดียว__ (ดู [:Revert]) /!\ หมายเหตุ: ถ้าคุณเกิดเปลี่ยนใจและต้องการยกเลิกการรวมก่อนที่จะคอมมิทอะไร คุณจะต้องใช้คำสั่ง "`hg update -C -r`" เพื่อย้อนกลับไปที่ revision 2 การใช้คำสั่ง `hg revert -r2 --all` จะแค่ยกเลิกการรวมเนื้อหาของไฟล์ในไดเร็คทอรี่สำหรับใช้ทำงานของคุณ แต่จะ __ไม่แก้ไขบรรพบุรุษของไดเร็คทอรี่สำหรับใช้ทำงานกลับเป็นบรรพบุรุษเดียว__ (ดู [:Revert])
Line 197: Line 197:
คำสั่งนี้จะไม่แสดงผลลัพธ์ใดๆ ตอนนี้การรวมไฟล์ได้ถูกบันทึกใน store ของ repository เราเป็น [:MergeChangeset:merge changeset] ใหม่แล้วและเราสามารถดูประวัติได้โดยใช้คำสั่ง `glog`: คำสั่งนี้จะไม่แสดงผลลัพธ์ใดๆ การรวมไฟล์ได้ถูกบันทึกในที่จัดเก็บประวัติของ repository เป็น[:MergeChangeset:เซ็ทการแก้ไขรวม]ใหม่แล้ว และเราสามารถดูประวัติได้โดยใช้คำสั่ง `glog`:
Line 231: Line 231:
เรายังสามารถแสดงเนื้อหาที่เปลี่ยนแปลงในการรวมไฟล์โดยใช้คำสั่ง `annotate` เพื่อแสดงข้อมูลของ changeset ในแต่ละบรรทัดของไฟล์ได้
หมายเหตุ: revision 2 คือการแก้ไขที่เราทำกับ repository `my-hello-desc` และ revision 3 คือการแก้ไขที่เราดึงมาจาก `my-hello-new-output` แะรวมเข้าไปกับ repository `my-hello-desc`
เรายังสามารถแสดงเนื้อหาที่เปลี่ยนแปลงในการรวมไฟล์โดยใช้คำสั่ง `annotate` เพื่อแสดงข้อมูลของเซ็ตการแก้ไขในแต่ละบรรทัดของไฟล์ได้
หมายเหตุ: การแก้ไขครั้งที่ 2 คือการแก้ไขที่เราทำกับ repository `my-hello-desc` และการแก้ไขครั้งที่ 3 คือการแก้ไขที่เราดึงมาจาก `my-hello-new-output` เพื่อรวมเข้าไปกับ repository `my-hello-desc`
Line 255: Line 255:
เรามาลองดูกันว่าถ้าเกิดการเปลี่ยนแปลงทั้งสองมีการแก้ไขที่[:Conflict:ขัดแย้ง]เราจะทำอย่างไรในบท [:ThaiTutorialConflict] เรามาลองดูกันว่าถ้าเกิดการเปลี่ยนแปลงทั้งสองมีการแก้ไขที่[:Conflict:ขัดแย้ง]กันเราจะทำอย่างไรในบท [:ThaiTutorialConflict:รวมประวัติการแก้ไขที่ขัดแย้งกัน]
Line 259: Line 259:
CategoryThai

บทเรียน - รวมประวัติการแก้ไขจาก repository อื่น

(บทนี้เป็นบทที่ 7 จาก 9 บทของ[:ThaiTutorial:บทเรียนการใช้งาน Mercurial] บทก่อนหน้าคือ [:ThaiTutorialExport:แบ่งปันสิ่งที่คุณแก้ไขกับบุคคลอื่นๆ], บทถัดไปคือ [:ThaiTutorialConflict:รวมประวัติการแก้ไขที่ขัดแย้งกัน])

ใน[:ThaiTutorialExport:บทที่แล้ว]เราได้เรียนวิธีการแบ่งปันการแก้ไขกับบุคคลอื่นโดยการส่งออกการแก้ไข ในบทนี้เราจะเรียนรู้วิธีการ[:Merge:รวมการแก้ไข]โดยการ[:Pull:ดึงการแก้ไข]จาก [:Repository:repository] อื่น

ก่อนอื่นเราจะต้องสร้าง repository สำหรับเป็นที่รวมการแก้ไขซะก่อนโดย[:Clone:ทำสำเนา] repository my-hello อีกครั้ง:

$ cd ..
$ hg clone my-hello my-hello-desc
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved

เราจะแก้ไฟล์ hello.c โดยเพิ่มคำอธิบายในส่วนคอมเม้นต์

$ cd my-hello-desc
$ vi hello.c

เปลี่ยนบรรทัดที่สองจาก:

 * hello.c

เป็น:

 * hello.c - hello, world

จากนั้นเราต้องบันทึกและปิดโปรแกรม editor และ[:Commit:คอมมิท]การแก้ไขของเรา ครั้งนี้เราจะประหยัดเวลาลงหน่อยโดยการใช้ตัวเลือก -m กับคำสั่ง commit เพื่อใส่คำอธิบายของเซ็ตการแก้ไขที่เราจะคอมมิทเลยแทนที่จะใช้โปรแกรม editor:

$ hg commit -m "Add description of hello.c"

ตอนนี้ไฟล์ hello.c ใน repository my-hello-new-output และ repository my-hello-desc ต่างก็ถูกแก้ไข เราจะรวมการแก้ไขที่แตกต่างกันในสอง repository นี้ยังไงล่ะ? และจะมีปัญหาอะไรหรือเปล่าถ้าเราต้องการดึงประวัติการเปลี่ยนแปลงจาก repository นึงไปอีก repository นึง?

ไม่ต้องห่วง การทำแบบนี้จะไม่มีปัญหาอะไรหรอก ตอนนี้ระหว่างที่เราอยู่ใน my-hello-desc เรามาลองดึงประวัติการแก้ไขจาก my-hello-new-output และดูกันว่าจะเกิดอะไรขึ้น:

$ hg pull ../my-hello-new-output
pulling from ../my-hello-new-output
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)

Mercurial บอกว่ามันได้เพิ่ม[:Head:ส่วนยอด]อีกอันนึงใน repository ของเรา ถ้าเราอยากดูส่วนยอดทั้งหมดเราต้องใช้คำสั่ง heads:

$ hg heads
changeset:   3:86794f718fb1
tag:         tip
parent:      1:82e55d328c8c
user:        mpm@selenic.com
date:        Mon May 05 01:20:46 2008 +0200
summary:     Express great joy at existence of Mercurial

changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

ถ้าคุณสนใจ Mercurial มาพร้อมกับ[:UsingExtensions:ส่วนเพิ่มความสามารถ]ที่สามารถแสดงกราฟประวัติการแก้ไขของ repository ในแบบ ASCII ได้นั่นก็คือ: [:GraphlogExtension] คุณเพียงแค่ต้องเปิดการใช้งานส่วนเพิ่มความสามารถนี้ในไฟล์ ~/.hgrc ของคุณ (หรือในไฟล์ Mercurial.ini ในวินโดวส์) โดยเพิ่มบรรทัด hgext.graphlog =  ในส่วน [extensions] แบบนี้:

[extensions]
hgext.graphlog = 

หลังจากคุณเปิดการใช้งานส่วนเพิ่มความสามารถนี้แล้วคุณจะสามารถใช้คำสั่งใหม่คือ glog ได้ทันที (ลองดู hg help glog):

$ hg glog
o  changeset:   3:86794f718fb1
|  tag:         tip
|  parent:      1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Mon May 05 01:20:46 2008 +0200
|  summary:     Express great joy at existence of Mercurial
|
| @  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

ในกราฟด้านบนคุณจะเห็นว่าเราได้ดึงเซ็ตการแก้ไข 86794f718fb1 เข้ามาใน repository (ซึ่งก็เป็น[:Tip:ส่วนปลาย]ของ repository ด้วย) เนื่องจากว่าทั้งเซ็ตการแก้ไข 86794f718fb1 และ c3844fde99f0 ของเราถูกคอมมิทโดยมีเซ็ตการแก้ไข[:Parent:บรรพบุรุษ]เดียวกันคือ 82e55d328c8c จึงเกิด[:Branch:กิ่ง]การแก้ไขที่แยกจากกัน ในตัวอย่างนี้กิ่งแต่ละกิ่งมีชีวิตที่ค่อนข้างสั้น การจัดการกับการแตกกิ่งแบบนี้ก็เป็นเรื่องที่ง่ายมากใน Mercurial

ระหว่างที่ดูผลลัพธ์ของคำสั่ง pull คุณอาจจะคิดว่ามันก็ดูคล้ายๆกับผลลัพธ์ในบท[:ThaiTutorialShareChange:แบ่งปันสิ่งที่คุณแก้ไขกับ repository อื่น]นี่นา เพราะอย่างนั้นคุณอาจจะถามว่า: ทำไมไม่ลองใช้คำสั่ง [:Update:update] เลยล่ะ? ไม่มีปัญหา เรามาลองดูว่าจะเกิดอะไรขึ้นถ้าเราทำอย่างที่ว่า:

$ hg update
abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes

โอ๊ะโอ มีบางอย่างที่แตกต่างไปแล้ว อย่างที่คุณเห็น Mercurial ระมัดระวังและพยายามที่จะไม่ทำอะไรแย่ๆถ้าเราไม่ทันเห็นสถานะ "(+1 heads)" ตรงท้ายๆผลลัพธ์ของคำสั่ง pull Mercurial จะเตือนเราดีๆว่าเราน่าจะทำอย่างอื่นมากกว่า ซึ่งในกรณีนี้ก็คือเราน่าจะรวมประวัติการแก้ไข

ก่อนที่เราจะรวมประวัติการแก้ไขเรามาตรวจสอบกันก่อนดีกว่าว่าตอนนี้เรากำลังทำงานอยู่กับ changeset ไหนโดยใช้คำสั่ง parents (ดู [:Parent:บรรพบุรุษ]):

$ hg parents
changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

คำสั่งนี้บอกเราว่าตอนนี้[:WorkingDirectory:ไดเร็คทอรี่สำหรับใช้ทำงาน]ของเราตรงกับเซ็ตการแก้ไข c3844fde99f0 อยู่ – ซึ่งก็แน่นอนเพราะว่านั่นเป็นเซ็ตการแก้ไขที่เราเพิ่งคอมมิทไป สิ่งสำคัญที่เราจะต้องเข้าใจก็คือ การดึงประวัติการแก้ไขเป็นการดึงมาเก็บไว้ที่ที่จัดเก็บประวัติของ repository เท่านั้น แต่ไม่ได้อัพเดทข้อมูลใดๆในไดเร็คทอรี่สำหรับใช้ทำงานของเราเลยแม้แต่น้อย ลองดูผลลัพธ์ของคำสั่ง glog อีกทีสิ: มีเซ็ตการแก้ไขนึงที่ถูกให้สัญลักษณ์ด้วยเครื่องหมาย "@" นั่นก็หมายความว่าเซ็ตการแก้ไขนั้นเป็นบรรพบุรุษของไดเร็คทอรี่ที่เรากำลังทำงานอยู่ หรือจะพูดอีกแบบก็คือเรากำลังทำงาน"อยู่ตรง"เซ็ตการแก้ไข c3844fde99f0

โอเค อธิบายมาซะยาวจนเบื่อแล้ว เรามาลองรวมการแก้ไขกันเลยดีกว่า การรวมการแก้ไขฟังดูค่อนข้างยากเนอะ? แต่จริงๆแล้วมันเป็นอะไรที่ง่ายมาก ลองทำตามคำแนะนำจาก Mercurial ที่อยู่ในบรรทัดสุดท้ายของผลลัพธ์จากคำสั่ง pull ดู:

$ hg merge
merging hello.c
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

เรียบร้อย! Mercurial รวมการเปลี่ยนแปลงให้คุณโดยอัตโนมัติเพราะว่าการเปลี่ยนแปลงทั้งสองนั้นไม่มีอะไรที่ขัดแย้งกันเลย (เราจะพูดถึงการเปลี่ยนแปลงที่มีความขัดแย้งใน[:ThaiTutorialConflict:บทถัดไป]) ถ้าเราลองดูเนื้อหาของไฟล์ hello.c ในไดเร็คทอรี่สำหรับใช้ทำงานเราจะเห็นว่าไฟล์มีเนื้อหาจากการเปลี่ยนแปลงที่มาจาก my-hello-new-output และ my-hello-desc ทั้งคู่ตามที่คาดไว้

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

ตอนนี้เรายังไม่ได้คอมมิทผลของการรวมการแก้ไข ก่อนที่เราจะทำลองมาดูกันว่าผลลัพธ์ของคำสั่ง parents จะเป็นยังไง (เราใช้คำสั่งย่อ par):

$ hg par
changeset:   2:c3844fde99f0
user:        mpm@selenic.com
date:        Tue May 06 20:10:35 2008 +0200
summary:     Add description of hello.c

changeset:   3:86794f718fb1
tag:         tip
parent:      1:82e55d328c8c
user:        mpm@selenic.com
date:        Mon May 05 01:20:46 2008 +0200
summary:     Express great joy at existence of Mercurial

คำสั่งนี้บอกเราว่าไดเร็คทอรี่สำหรับใช้ทำงานของเรานั้นมีเซ็ตการแก้ไขที่เป็นบรรพบุรุษสองเซ็ต โดยสังเกตุว่าบรรพบุรุษทั้งสองได้ถูกเรียงลำดับดังนี้: บรรพบุรุษแรก (parent 1) คือเซ็ตการแก้ไขก่อนหน้าของเรานั่นก็คือ c3844fde99f0 ที่เราเพิ่มคำอธิบายใน hello.c ซึ่งเซ็ตการแก้ไขนี้เป็นบรรพบุรุษของไดเร็คทอรี่สำหรับใช้ทำงานของเราก่อนที่เราจะใช้คำสั่ง merge ส่วนบรรพบุรุษเซ็ตที่สอง (parent 2) คือ 86794f718fb1 ซึ่งเราได้ดึงมาจากอีก repository นึงและเป็นเซ็ตการแก้ไขที่เราเพิ่งรวมเข้าไป

ลองใช้คำสั่ง glog อีกทีแล้วเราจะเห็นว่าสัญลักษณ์ @ อยู่ที่บรรพบุรุษทั้งสองแล้ว:

$ hg glog
@  changeset:   3:86794f718fb1
|  tag:         tip
|  parent:      1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Mon May 05 01:20:46 2008 +0200
|  summary:     Express great joy at existence of Mercurial
|
| @  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

/!\ หมายเหตุ: ถ้าคุณเกิดเปลี่ยนใจและต้องการยกเลิกการรวมก่อนที่จะคอมมิทอะไร คุณจะต้องใช้คำสั่ง "hg update -C -r" เพื่อย้อนกลับไปที่ revision 2 การใช้คำสั่ง hg revert -r2 --all จะแค่ยกเลิกการรวมเนื้อหาของไฟล์ในไดเร็คทอรี่สำหรับใช้ทำงานของคุณ แต่จะ ไม่แก้ไขบรรพบุรุษของไดเร็คทอรี่สำหรับใช้ทำงานกลับเป็นบรรพบุรุษเดียว (ดู [:Revert])

ขั้นตอนสุดท้ายก็อย่าลืมคอมมิท[:LocalModifications:การแก้ไขในเครื่องของเรา]ตามที่คำสั่ง merge ก่อนหน้าได้แนะนำให้เราทำ:

$ hg commit -m "Merged changes from my-hello-new-output"

คำสั่งนี้จะไม่แสดงผลลัพธ์ใดๆ การรวมไฟล์ได้ถูกบันทึกในที่จัดเก็บประวัติของ repository เป็น[:MergeChangeset:เซ็ทการแก้ไขรวม]ใหม่แล้ว และเราสามารถดูประวัติได้โดยใช้คำสั่ง glog:

$ hg glog
@    changeset:   4:d2ecac0134d8
|\   tag:         tip
| |  parent:      2:c3844fde99f0
| |  parent:      3:86794f718fb1
| |  user:        mpm@selenic.com
| |  date:        Tue May 06 23:44:19 2008 +0200
| |  summary:     Merged changes from my-hello-new-output
| |
| o  changeset:   3:86794f718fb1
| |  parent:      1:82e55d328c8c
| |  user:        mpm@selenic.com
| |  date:        Mon May 05 01:20:46 2008 +0200
| |  summary:     Express great joy at existence of Mercurial
| |
o |  changeset:   2:c3844fde99f0
|/   user:        mpm@selenic.com
|    date:        Tue May 06 20:10:35 2008 +0200
|    summary:     Add description of hello.c
|
o  changeset:   1:82e55d328c8c
|  user:        mpm@selenic.com
|  date:        Fri Aug 26 01:21:28 2005 -0700
|  summary:     Create a makefile
|
o  changeset:   0:0a04b987be5a
   user:        mpm@selenic.com
   date:        Fri Aug 26 01:20:50 2005 -0700
   summary:     Create a standard "hello, world" program

เรายังสามารถแสดงเนื้อหาที่เปลี่ยนแปลงในการรวมไฟล์โดยใช้คำสั่ง annotate เพื่อแสดงข้อมูลของเซ็ตการแก้ไขในแต่ละบรรทัดของไฟล์ได้ หมายเหตุ: การแก้ไขครั้งที่ 2 คือการแก้ไขที่เราทำกับ repository my-hello-desc และการแก้ไขครั้งที่ 3 คือการแก้ไขที่เราดึงมาจาก my-hello-new-output เพื่อรวมเข้าไปกับ repository my-hello-desc

$ hg annotate hello.c
0: /*
2:  * hello.c - hello, world
0:  *
0:  * Placed in the public domain by Bryan O'Sullivan
0:  *
0:  * This program is not covered by patents in the United States or other
0:  * countries.
0:  */
0:
0: #include <stdio.h>
0:
0: int main(int argc, char **argv)
0: {
0:      printf("hello, world!\n");
3:      printf("sure am glad I'm using Mercurial!\n");
0:      return 0;
0: }

เรามาลองดูกันว่าถ้าเกิดการเปลี่ยนแปลงทั้งสองมีการแก้ไขที่[:Conflict:ขัดแย้ง]กันเราจะทำอย่างไรในบท [:ThaiTutorialConflict:รวมประวัติการแก้ไขที่ขัดแย้งกัน]


CategoryTutorial CategoryThai

ThaiTutorialMerge (last edited 2009-05-19 19:30:55 by localhost)