== บทเรียน - ทำการแก้ไขแรก == ''(บทนี้เป็นบทที่ 4 จาก 9 บทของ[[ThaiTutorial|บทเรียนการใช้งาน Mercurial]] บทก่อนหน้าคือ [[ThaiTutorialHistory|ดูประวัติการแก้ไขใน repository]], บทถัดไปคือ [[ThaiTutorialShareChange|แบ่งปันสิ่งที่คุณแก้ไขกับ repository อื่น]])'' ต่อจาก[[ThaiTutorialHistory|บทที่แล้ว]] ตอนนี้เราอยู่ใน repository `my-hello` ที่เราเพิ่งทำสำเนามาใน[[ThaiTutorialClone|บทที่ 2]] วิธีการใช้ Mercurial ที่ดีสำหรับการพัฒนาโปรแกรมก็คือการแยกการแก้ไขที่เกี่ยวข้องกันออกมาเป็น [[Repository|repository]] ต่างหาก (ดู [[WorkingPractices]]) การทำแบบนี้จะช่วยให้การแก้ไขเรื่องต่างๆกันไม่มาปนกันอยู่ใน repository เดียวและทำให้ง่ายต่อการทดสอบ เรามาลองเริ่มแก้ไขโดยใช้วิธีนี้กันดู จุดประสงค์(อันยิ่งใหญ่)ของเราก็คือ...ให้โปรแกรม "hello, world" เราพิมพ์ผลลัพธ์เพิ่มอีกบรรทัดนึง ก่อนอื่นให้เราสร้าง repository ใหม่ชื่อ `my-hello-new-output` โดย[[Clone|ทำสำเนา]]จาก `my-hello` (ผลลัพธ์ที่ได้มาจาก Mercurial 1.0): {{{ $ hg clone my-hello my-hello-new-output updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} สังเกตุว่าเราได้ตั้งชื่อสำหรับ repository ใหม่ด้วยชื่อที่สื่อความหมายเพื่อบ่งบอกว่าเราจะใช้ repository ใหม่นี้เพื่ออะไร เนื่องจากว่าการทำสำเนาใน Mercurial นั้นง่ายมากเราอาจจะทำสำเนา repository ต่างๆมากมายระหว่างการทำงาน ถ้าเราไม่ตั้งชื่อ repository ให้ดีๆเราอาจจะลืมได้ว่า repository แต่ละอันมีไว้เพื่ออะไร (ดู RepositoryNaming) โอเค ถึงเวลาที่เราจะทำการแก้ไขใน repository ใหม่ล่ะ เข้าไปใน[[WorkingDirectory|ไดเร็คทอรี่สำหรับใช้ทำงาน]]ของ repository จากนั้นก็แก้ไขซอร์สโค้ดด้วยโปรแกรมตัวโปรดของคุณ: {{{ $ cd my-hello-new-output $ vi hello.c }}} เนื้อหาเริ่มต้นของ `hello.c` เป็นแบบนี้: {{{#!cplusplus numbers=off /* * hello.c * * Placed in the public domain by Bryan O'Sullivan * * This program is not covered by patents in the United States or other * countries. */ #include int main(int argc, char **argv) { printf("hello, world!\n"); return 0; } }}} เรามาแก้ {{{main}}} ให้พิมพ์ข้อความอีกบรรทัดนึงกันเถอะ: {{{#!cplusplus numbers=off (...) int main(int argc, char **argv) { printf("hello, world!\n"); printf("sure am glad I'm using Mercurial!\n"); return 0; } }}} หลังจากแก้ไขเสร็จก็บันทึกไฟล์และออกจากโปรแกรมของเรา ตอนนี้เราก็พร้อมที่จะสร้าง[[ChangeSet|เซ็ตการแก้ไข]]ใหม่แล้ว แต่จะเกิดอะไรขึ้นถ้าเกิดมีคนมาขัดจังหวะแล้วเราดันลืมไปว่าอะไรจะถูกคอมมิทไปบ้างล่ะ? ไม่ต้องห่วง เพราะเรายังมีคำสั่ง `status` {{{ $ hg status M hello.c }}} ผลลัพธ์จากคำสั่งแค่สั้นๆ ตัวอักษร `M` บอกเราว่าไฟล์ `hello.c` ได้ถูกแก้ไข (modified) และการแก้ไขนี้จะอยู่ในเซ็ตการแก้ไขเมื่อเราคอมมิท ถ้าคุณขี้เกียจพิมพ์คำสั่งยาวๆแบบ `hg status` ก็สามารถใช้คำสั่งแบบย่อ `hg st` ได้เพราะ Mercurial อนุญาติให้เราย่อคำสั่งได้ตราบใดที่พอย่อแล้วไม่กำกวมสำหรับ Mercurial {{{ $ hg st M hello.c }}} ถ้าเราอาจจะอยากดูว่ามีอะไรถูกแก้ไขไปบ้างก็ใช้คำสั่ง `diff`: {{{ $ hg diff diff -r 82e55d328c8c hello.c --- a/hello.c Fri Aug 26 01:21:28 2005 -0700 +++ b/hello.c Mon May 05 00:27:56 2008 +0200 @@ -12,5 +12,6 @@ int main(int argc, char **argv) { printf("hello, world!\n"); + printf("sure am glad I'm using Mercurial!\n"); return 0; } }}} ในกรณีที่เราอยากยกเลิกสิ่งที่เราแก้ไขและเริ่มต้นใหม่เราสามารถใช้คำสั่ง `revert` เพื่อดึงไฟล์ `hello.c` ก่อนที่จะถูกแก้ไขกลับมาได้ (หรือจะใช้ตัวเลือก `--all` เพื่อดึงเวอร์ชั่นก่อนแก้ไขของทุกๆไฟล์กลับมา) เช็คให้แน่ใจก่อนล่ะว่านี่เป็นสิ่งที่เราอยากทำจริงๆ (ดู [[Revert]]). {{{ $ hg revert hello.c }}} คำสั่ง `revert` จะเปลี่ยนชื่อไฟล์ที่ถูกแก้ไขจาก `hello.c` เป็น `hello.c.orig` และกู้ไฟล์ `hello.c` เวอร์ชั่นก่อนที่จะถูกแก้ไขกลับมาแทน และเมื่อเรายกเลิกการแก้ไขคำสั่ง `status` จะแสดงสถานะของไฟล์ `hello.c.orig` ว่าเป็นไฟล์ที่ไม่ถูกเก็บประวัติโดย Mercurial (โดยแสดงเครื่องหมาย "?" นำหน้าชื่อไฟล์) {{{ $ hg st ? hello.c.orig }}} ถ้าเราเกิดเปลี่ยนใจและอยากใช้ไฟล์ที่เราเพิ่งแก้ไปก็แค่ลบไฟล์ `hello.c` ทิ้งและเปลี่ยนชื่อไฟล์ `hello.c.orig` เป็น `hello.c` เท่านี้ก็เรียบร้อย {{{ $ rm hello.c $ mv hello.c.orig hello.c $ hg st M hello.c }}} การสร้างเซ็ตการแก้ไขมีชื่อเรียกอีกชื่อนึงว่าการ[[Commit|คอมมิท]]เซ็ตการแก้ไขนั้น เราทำการคอมมิทโดยใช้คำสั่ง `commit` คำสั่ง `commit` นี้มีชื่อย่อว่า: `ci` ("check in"), เพราะฉะนั้นเราสามารถใช้คำสั่งแบบย่อนี้ได้: {{{ $ hg ci }}} คำสั่งนี้จะเปิดโปรแกรม editor ขึ้นมาพร้อมกับบรรทัดแปลกๆสองสามบรรทัด ''หมายเหตุ:'' โปรแกรม editor ที่ Mercurial ใช้โดยปกติคือ `vi` แต่เราสามารถเปลี่ยนค่านี้ได้ได้โดยตั้งค่าตัวแปร environment ที่ชื่อ `EDITOR` หรือ [[HGEDITOR]] {{{ HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: -- HG: user: mpm@selenic.com HG: branch 'default' HG: changed hello.c }}} บรรทัดแรกของ editor จะเป็นบรรทัดว่างๆ ไว้ให้เราใส่คำอธิบายของเซ็ตการแก้ไขนี้ ส่วนบรรทัดต่อๆไปก็จะบอกชื่อผู้ใช้ ชื่อกิ่งของไดเร็คทอรี่สำหรับใช้งาน และไฟล์ต่างๆที่จะถูกคอมมิทในไดเร็คทอรี่สำหรับใช้ทำงานนี้ ปกติชื่อของกิ่งคือ "default" (ดู NamedBranches) Mercurial เอาค่า "user" มาจากไฟล์ {{{~/.hgrc}}} จากค่าของ "username" ในส่วน "ui" (ดู [[http://www.selenic.com/mercurial/hgrc.5.html#ui|hgrc(5)]]) เราสามารถระบุชื่อผู้ใช้ได้เองโดยใช้ตัวเลือก -u (ดู `hg help ci` หรือ [[http://www.selenic.com/mercurial/hg.1.html#commit|hg.1.html#commit]]) เราจะต้องใส่คำอธิบายเพื่อที่จะคอมมิทเซ็ตการแก้ไขแต่ละเซ็ต (ดู [[ChangeSetComments]]) ลองพิมพ์อะไรประมาณนี้ดู: {{{ Express great joy at existence of Mercurial HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: -- HG: user: mpm@selenic.com HG: branch 'default' HG: changed hello.c }}} จากนั้นเราต้องบันทึกและปิดโปรแกรม editor ซะและถ้าทุกอย่างเป็นไปด้วยดีคำสั่ง `commit` จะจบการทำงานโดยไม่พิมพ์ผลลัพธ์ใดๆออกมา ถ้าคุณออกจากโปรแกรม editor โดยที่ยังไม่ได้บันทึกหรือพิมพ์คำอธิบายใดๆ คำสั่ง `commit` จะยกเลิกการคอมมิท ทั้งนี้เพื่อให้คุณสามารถเปลี่ยนใจไม่คอมมิทการแก้ไขของคุณได้ ลองมาดูว่าหลังจากคอมมิทแล้วคำสั่ง {{{status}}} จะบอกอะไรกับเรานะ? {{{ $ hg st }}} ไม่มีอะไรเลย! สิ่งที่เราแก้ไขได้ถูกคอมมิทเป็นเซ็ตการแก้ไขแล้วเพราะฉะนั้นจึงไม่มีไฟล์ใดๆที่ถูกแก้และยังไม่ได้ถูกคอมมิท นอกจากนั้น[[Tip|ส่วนปลาย]]ของ repository ของเราก็ตรงกับไดเร็คทอรี่สำหรับใช้ทำงานแล้วด้วย เรายังสามารถใช้คำสั่ง [[Parent|parents]] เพื่อดูว่าไดเร็คทอรี่สำหรับใช้ทำงานของเราก็ตรงกับเซ็ทการแก้ไขที่ถูกคอมมิทล่าสุดแล้วเช่นกัน (ลองดู [[Update]] ด้วย) (ในกรณีนี้เรามีบรรพบุรุษแค่อันเดียวซึ่งก็เป็นปกติหลังจากคอมมิท เราจะได้เห็นบรรพบุรุษสองอันในบท[[ThaiTutorialMerge|รวมประวัติการแก้ไขที่ขัดแย้งกัน]]): {{{ $ hg par changeset: 2:86794f718fb1 tag: tip user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial }}} โอเค! เราได้คอมมิทเซ็ตการแก้ไขใหม่เข้าไปใน repository เรียบร้อยแล้ว ลองมาดูประวัติการแก้ไขของเรากัน: {{{ $ hg log changeset: 2:86794f718fb1 tag: tip user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial (...) }}} ''หมายเหตุ:'' ชื่อผู้ใช้, วันที่, และ [[ChangeSetID|รหัสประจำเซ็ตการแก้ไข]]อาจต่างไปในเครื่องของคุณ จากที่เราได้เรียนในบท [[ThaiTutorialClone|ทำสำเนา repository ที่มีอยู่]] เราจะเห็นว่าเซ็ตการแก้ไขใหม่นี้จะอยู่แค่ใน repository นี้เท่านั้น จุดนี้เป็นจุดที่สำคัญมากในการทำความเข้าใจการทำงานของ Mercurial อ่านบทต่อไปได้เลยเพื่อ [[ThaiTutorialShareChange|แบ่งปันสิ่งที่เราแก้ไขกับ repository อื่น]] ---- CategoryTutorial CategoryThai