ผู้ใช้ใหม่ๆอาจงงกับรูปแบบการทำงานแบบแยกศูนย์ (decentralized) ของ Mercurial หน้านี้จึงพยายามที่จะอธิบายหลักการพื้นฐานต่างๆเพื่อให้ผู้ใช้เข้าใจ Mercurial ได้ดีขึ้น ดูบทเรียนการใช้งาน Mercurialสำหรับขั้นตอนอย่างการใช้งานอย่างละเอียด

(คำแปล: ภาษาโปรตุเกสบราซิล, ภาษาจีน, ภาษาฝรั่งเศษ, ภาษาเยอรมัน, ภาษาอิตาลี, ภาษาญี่ปุ่น, ภาษาเกาหลี, ภาษารัสเซีย, ภาษาสเปน )

มีอะไรอยู่ใน Repository บ้าง

repository ของ Mercurial ประกอบไปด้วยสองส่วนคือไดเร็คทอรี่สำหรับใช้ทำงาน (working directory) และที่จัดเก็บประวัติ (store):

ที่จัดเก็บประวัติจะทำหน้าที่เก็บประวัติการแก้ไขทั้งหมดของโปรเจค

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

ในไดเร็คทอรี่สำหรับใช้ทำงานจะมีสำเนาของไฟล์ต่างๆ ณ เวลาใดเวลาหนึ่ง (เช่นเวอร์ชั่นจากการแก้ไขครั้งที่สองหรือ rev 2 เป็นต้น) คุณสามารถแก้ไขไฟล์ในไดเร็คทอรี่สำหรับใช้ทำงานได้ตามปกติ และเนื่องจากว่าป้ายกำกับ (tags)และไฟล์ที่ไม่ถูกเก็บประวัติ (ignored files)ก็เป็นส่วนหนึ่งของ repository ด้วยข้อมูลทั้งสองจึงถูกเก็บอยู่ใน repository เช่นกัน

การคอมมิท(บันทึก) การแก้ไข

เมื่อคุณคอมมิทการแก้ไข ไฟล์ต่างๆที่อยู่ในไดเร็คทอรี่สำหรับใช้ทำงานของคุณจะถูกเก็บเป็นเซ็ตของการแก้ไข (changeset) เซ็ตใหม่ (หรือจะเรียกสั้นๆว่า"การแก้ไข (revision)"ใหม่ก็ได้) โดยบรรพบุรุษ (parent)ของเซ็ตของการแก้ไขตัวใหม่นี้ก็คือบรรพบุรุษของไดเร็คทอรี่สำหรับใช้ทำงานในขณะนั้น:

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

การแก้ไข (revision), เซ็ตของการแก้ไข (changeset), ส่วนยอด (head), และส่วนปลาย (tip)

Mercurial จะรวบรวมไฟล์ที่ถูกแก้ไขทั้งหมดไว้ด้วยกันเป็นกลุ่มเดียวสำหรับคอมมิท เราจะเรียกกลุ่มๆนี้ว่าเซ็ตของการแก้ไข หรือสั้นๆว่าการแก้ไข (revision) การแก้ไขแต่ละครั้งจะมีตัวเลขกำกับเพื่อง่ายต่อการระบุ ตัวเลขนี้เรียกว่าครั้งที่แก้ไขซึ่งจะเพิ่มขึ้นตามลำดับ เนื่องจากว่า Mercurial อนุญาติให้ผู้ใช้หลายคนทำงานขนานกันในหลายๆ repository ตัวเลขครั้งที่แก้ไขของผู้ใช้แต่ละคนอาจไม่ตรงกันได้ เพราะฉะนั้น Mercurial จึงมีตัวเลขกำกับอีกเลขนึงเพื่อระบุการแก้ไขเดียวกันในทุกๆ repository เป็นตัวเลขฐานสิบหก ยาว 40 หลัก ที่มีชื่อว่า รหัสประจำเซ็ตการแก้ไข (changeset ID) คุณสามารถใช้รหัสแบบย่อได้ถ้าเป็นรหัสที่สามารถระบุเซ็ตการแก้ไขเจาะจงได้โดยไม่กำกวม เช่น "e38487"

การแตกกิ่งและการรวมประวัติอาจเกิดขึ้นตรงจุดใดก็ได้ใน repository แต่ละกิ่งที่ยังไม่ได้ถูกรวมกับกิ่งอื่นมีชื่อเรียกว่าส่วนยอดของ repository ในรูปภาพด้านบนการแก้ไขครั้งที่ 5 และ 6 คือส่วนยอด แต่การแก้ไขครั้งที่ 6 มีความหมายพิเศษกว่าคือเป็นส่วนปลายของ repository ด้วย ส่วนปลายของ repository คือส่วนยอดที่เป็นการแก้ไขครั้งล่าสุด (ตัวเลขครั้งที่แก้ไขสูงที่สุด) การแก้ไขครั้งที่ 4 มีชื่อเรียกว่าเซ็ตการแก้ไขรวม เพราะว่าเป็นเซ็ตการแก้ไขที่เกิดจากการรวมของกันของบรรพบุรุษอีกสองเซ็ต (คือการแก้ไขครั้งที่ 2 และ 3)

การทำสำเนา (clone), แก้ไข, รวมประวัติการแก้ไข (merge), การดึงประวัติการแก้ไข (pull) และการอัพเดทไดเร็คทอรี่สำหรับใช้ทำงาน (update)

สมมุติว่าอลิซมี repository ดังนี้:

บ๊อบทำสำเนา (clone) repository จากอลิซเป็น repository ส่วนตัวของตัวเองและในไดเร็คทอรี่สำหรับใช้ทำงานของเขามีไฟล์เวอร์ชั่น d ซึ่งก็คือส่วนปลายของ repository:

หลังจากทำสำเนาบ๊อบสามารถทำงานโดยอิสระจากอลิซ บ๊อบแก้ไขไฟล์และคอมมิทสองครั้งทำให้เกิดเวอร์ชั่น e และ f:

ในขณะเดียวกันอลิซก็ทำการแก้ไขและคอมมิทเวอร์ชั่น g เช่นกัน ทำให้ประวัติการแก้ไขใน repository ของอลิซแตกแขนงออกไปจากประวัติการแก้ไขใน repository ของบ๊อบ จึงเกิดการแตกกิ่งขึ้น:

บ๊อบจึงดึงประวัติการแก้ไขจาก repository ของอลิซเพื่อทำให้ประวัติการแก้ไขสอดคล้องกัน การดึงประวัติการแก้ไขจะคัดลอกการแก้ไขทั้งหมดที่ที่อลิซคอมมิทมาไว้ใน repository ของบ๊อบ (ในตัวอย่างนี้คือแค่การแก้ไขเวอร์ชั่น g) สังเกตุว่าการดึงประวัติจะไม่แก้ไขไฟล์ใดๆในไดเร็คทอรี่สำหรับใช้ทำงานของบ๊อบเลยแม้แต่น้อย:

การแก้ไขเวอร์ชั่น g ของอลิซกลายเป็นส่วนยอดใหม่ใน repository ของบ๊อบ และก็เป็นส่วนปลายของ repository อีกด้วยเนื่องจากเป็นการแก้ไขครั้งล่าสุด (ที่มีเลขครั้งที่แก้ไขมากที่สุดใน repository ของบ๊อบ)

จากนั้นบ๊อบจึงทำการรวมประวัติการแก้ไขของส่วนยอดทั้งสองเข้าด้วยกัน นั่นก็คือการรวมการแก้ไขล่าสุดของเขา (เวอร์ชั่น f) เข้ากับส่วนปลายของ repository (เวอร์ชั่น g) ผลลัพธ์ของการรวมก็คือไดเร็คทอรี่สำหรับใช้ทำงานของบ๊อบจะมีบรรพบุรุษ 2 เวอร์ชั่นคือ f และ g นั่นเอง:

หลังจากตรวจสอบดูว่าการรวมประวัติการแก้ไขในไดเร็คทอรี่สำหรับใช้ทำงานของเขาเป็นไปด้วยดี บ๊อบก็คอมมิทและสร้างเซ็ตการแก้ไขรวมใหม่ ซึ่งก็คือเวอร์ชั่น h ในที่จัดเก็บประวัติ (store) ของ repository เขา:

ตอนนี้ถ้าอลิซดึงประวัติการแก้ไขจากบ๊อบ เธอจะเห็นประวัติการแก้ไขจากบ๊อบคือ e, f, และ h ในที่จัดเก็บประวัติใน repository ของเธอด้วย:

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

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

ระบบการทำงานแบบแยกศูนย์

Mercurial เป็นระบบที่ทำงานแบบแยกศูนย์ จึงไม่มีการกำหนดความหมายพิเศษสำหรับ repository กลาง ผู้ใช้มีสิทธิ์เลือกโครงสร้างของ repository ได้ตามต้องการ (ลองดู CommunicatingChanges):

Mercurial ต่างจากระบบเวอร์ชั่นคอนโทรลแบบรวมศูนย์อื่นๆ ในระบบแบบรวมศูนย์การแก้ไขเพื่อทำการทดลองบางอย่างอาจก่อให้เกิดปัญหาได้ถ้าผู้ใช้ไม่ระมัดระวัง แต่ระบบ DVCS อย่าง Mercurial ทำให้การทำการทดลองง่ายและปลอดภัยขึ้นเพราะคุณแค่ต้องทำสำเนาของ repository และก็เริ่มแก้ไขได้เลย repository ต้นฉบับของคุณจะเป็นอิสระจาก repository ทดลองจึงทำให้การทำงานขนานไปได้พร้อมๆกัน ถ้าการทดลองเป็นไปได้ด้วยดี คุณก็แค่ผลักประวัติการแก้ไข (push) กลับไปที่ repository ต้นฉบับ แต่ถ้าคุณไม่ชอบก็แค่ลบ repository ทดลองทิ้งและสร้างสำเนาขึ้นมาทำงานใหม่

Mercurial ไม่เหมาะกับการใช้งานแบบไหนบ้าง?

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

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

คุณสามารถศึกษาวิธีการใช้งาน Mercurial จากตัวอย่างได้จากบทเรียนการใช้งาน Mercurial

ThaiUnderstandingMercurial (last edited 2012-11-11 13:31:09 by abuehl)