สำหรับการใช้งาน Git นั้น สามารถเริ่มต้นจากเครื่องเราก่อน ก่อนที่จะเริ่มใช้งานนั้น ควรจะต้องรู้จักศัพท์ต่าง ๆ ที่สำคัญ ๆ อย่างเช่น Working Directory, Repository, Stage, Commit, Branch และอื่น ๆ อีกมากมาย รวมถึงหลักการทำงานของ Git และขั้นตอนการทำงานต่าง ๆ
Credit : http://www.git-scm.com/downloads/logos
หลากหลายตำรา มักสอนการใช้งานบน Git Bash ผ่านทาง Command line ซึ่งผมเชื่อว่า Developer สมัยใหม่ ที่เกิดไม่ทันใช้งาน Dos ส่วนใหญ่จะไม่ชอบการเขียนคำสั่งบน Command line นัก บทความตอนนี้ จึงเน้นไปที่ Git GUI ซึ่งเป็นตอนต่อจากบทความตอน [Dev] ใช้ Git เพื่อชีวิต (Source Code) ที่ดีกว่า – การติดตั้ง Git บน Windows
และจะไม่พูดถึงประวัติความเป็นมาและหลักการทำงานของ Git แต่จะพูดถึงศัพท์บางตัว สำหรับผู้เริ่มต้นที่สนใจ จะได้ไม่เสียเวลางมหา เพราะผมงมมาให้แล้ว ซึ่งผมได้ศึกษาการใช้ Git บน Git Bash และ Git GUI ควบคู่กันไป จนพอที่จะใช้งาน Git GUI แทน Git Bash ในการใช้งานพื้นฐานได้เกือบทั้งหมด
ผู้อ่านสามารถทดลองทำตามบทความ เพื่อเรียนรู้ไปด้วยกันได้เลย
สำหรับผู้ที่สนใจประวัติความเป็นมาและหลักการทำงานอย่างละเอียด สามารถศึกษาเพิ่มเติมได้จาก Link ท้ายบทความ (เป็นตำราภาษาไทยด้วยนะ)
List of contents
Working Directory
ศัพท์ตัวแรกที่จะพูดถึงก็คือ Working Directory มันคือ Directory (หรือ Folder) ใด ๆ ที่เราจะให้ Git จัดการให้เรานั่นเอง หรือเรียกง่าย ๆ ว่า Folder งานเรานั่นแหล่ะ
ตัวอย่างภาพด้านล่างนี้ มี Folder ชื่อ Git-Example ข้างในมีไฟล์ a.txt, b.txt ซึ่งเป็น Text file และ Git-Logo-2Color.png ซึ่งเป็น Binary file สมมติว่าเป็น Folder งานละกัน

เพราะฉะนั้น Folder ใด ๆ ก็ตาม เป็น Working Directory ได้ เราเป็นคน Assign ได้เอง ไม่จำเป็นต้องนำไปกองไว้ที่เดียวกัน
หลายคน รวมทั้งผมในตอนแรก เข้าใจว่า ต้องกำหนด Folder ที่จะเก็บงานด้วย Git ไม่ใช่นะคร๊าบบบบ…
Repository
เมื่อเราเลือก Working Directory ได้แล้ว ก็มาถึงขั้นตอนแรก ที่เราจะได้ใช้ Git กันจริง ๆ จัง ๆ โดยเราจะต้องสร้าง Git Repository ขึ้นมาก่อน โดยเราจะสร้างอยู่ใน Working Directory ของเรานั่นแหล่ะ ในเมื่อมันทำอยู่ในเครื่องเรา จึงเรียกว่าเป็น Local Repository
สำหรับบทความตอนนี้ จะพูดถึงแต่ Local Repository เท่านั้น ขอเรียกสั้น ๆ ว่า Repo ละกัน
สำหรับการสร้าง Local Repo นั้น เริ่มจากการใช้คำสั่งต่อไปนี้ ที่ Working Directory บน Git Bash~!!!
1 |
git init |
ไหนบอกจะสอน Git GUI!!
อย่าเพิ่งโวยวายซิ!! จะทำให้ดูก่อนว่า เราสามารถสร้าง Local Repo ได้จากทางไหนได้บ้าง…
สังเกตุรูปด้านล่าง ในวงกลมสีเขียว เมื่อสั่ง git init ที่ Working Directory แล้ว จะมีข้อความแจ้งว่า ได้สร้าง empty Git repository ให้แล้ว ซึ่งจะเกิดเป็น Folder ชื่อ .git อยู่ภายใน Working Directory นั่นเอง
หลังจากสร้าง Local Repo แล้ว ลองตรวจสอบดู ด้วยคำสั่ง…
1 |
git status |
จะเห็นวงกลมสีฟ้าในรูป มีคำว่า master ซึ่งก็คือ ชื่อ Branch หลัก ที่ Git สร้างไว้ให้เป็น Branch เริ่มต้นนั่นเอง
Branch คืออะไร… อ่านไปเรื่อย ๆ ก่อนละกันนะ…

สำหรับการใช้ Git GUI สร้าง Local Repo นั้น เมื่อเปิด Git GUI ขึ้นมา แล้วคลิกไปที่ Create New Repository ตามรูปด้านล่าง (หรือเลือกจากเมนู Repository ก็ได้เหมือนกัน)

Git GUI จะให้เราจะบุ Directory ที่เราจะให้เป็น Working Directory เรียบร้อยแล้ว กดปุ่ม Create

เมื่อ Create แล้ว Git GUI จะมีหน้าตาดังรูปด้านล่าง ในวงกลมสีเขียว จะเป็นรายชื่อไฟล์ที่อยู่ภายใน Working Directory นั้น (ถ้าเป็น Folder เปล่า ๆ ก็จะไม่เห็นไฟล์ใด ๆ)
ส่วนในวงกลมสีฟ้า จะแสดงชื่อ Branch ปัจจุบัน ว่าเป็น master!!

และวิธีสุดท้ายจะสร้าง Local Repo ได้ ง่ายที่สุด คือการใช้ Context menu โดยการคลิกขวาที่ว่าง ใน Folder ที่จะให้เป็น Working Directory แล้วเลือกเมนู Git Init Here
แค่นี้อ่ะ เสร็จแล้ว!!

ไม่ว่าจะสร้าง Local Repo ด้วยวิธีไหนก็ตาม ผลคือ… เหมือนกัน ตรวจสอบง่าย ๆ ด้วยคำสั่ง git status บน Git Bash หรือดูหน้าตาของ Git GUI ที่เปลี่ยนไป
หรือจะไปดูที่ Working Directory เลย จะเห็นว่า มี Folder .git เพิ่มขึ้นมา (เป็น Hidden Folder นะ ถ้าใครตั้งไม่ให้แสดง Hidden File/Folder จะไม่เห็น) และ Context menu ก็จะแสดงเมนูที่เปลี่ยนไป จะไม่มีให้ init แล้ว

User
Git นั้น จำเป็นต้องมีการกำหนด User ที่ใช้งาน อันที่จริงควรจะกำหนดเป็นขั้นตอนแรกตั้งแต่ก่อนสร้าง Repo แต่มันต้องไปทำที่ Git Bash ซึ่งผมเน้นไปที่ Git GUI จึงจำเป็นต้องสร้าง Repo แรกขึ้นมาก่อน ถึงจะเข้าไปกำหนดได้
ที่เมนู Edit (1) บน Git GUI เลือกเมนู Options… (2)

จะมีหน้าต่าง Options ให้เรากำหนดค่าต่าง ๆ ซึ่งจะเห็นว่า จะมี 2 ฝั่ง ที่มีตัวเลือกแทบจะเหมือนกัน โดยฝั่งซ้ายจะเป็น Option ของ Repo ที่เราเปิดอยู่ ส่วนฝั่งขวาจะเป็น Option ที่เป็น Global
ในครั้งแรก ให้กำหนดที่ฝั่ง Global ฝั่งเดียวก่อน โดยจุดที่จำเป็นต้องกำหนด คือ User Name (1) และ Email Address (2) ทั้งสองค่านี้ จะถูกนำไปใช้กำกับทุก Commit ของทุก Repo ในเครื่องเรานั่นเอง ถ้าหากไม่กำหนด จะไม่สามารถ Commit ได้
ส่วนจุดที่แนะนำให้กำหนดไปด้วย คือ Default File Contents Encoding (3) ซึ่งควรกำหนดเป็น Encoding ที่เราใช้งานเป็นหลัก สามารถเปลี่ยนได้ด้วยปุ่ม Change ด้านข้าง จะมี Encoding ให้เลือกเยอะแยะมากมาย ซึ่ง Git GUI จะใช้ Encoding ที่เรากำหนด ในการแสดงผลต่าง ๆ (ไม่มีผลกับไฟล์งานของเรา แค่แสดงให้ดูเฉย ๆ)
เมื่อเสร็จแล้ว กดปุ่ม Save (4)
หากลองเปิด Options ขึ้นมาดูอีกครั้ง จะเห็นว่า ฝั่ง Repo ที่เปิดอยู่ จะนำค่าจากฝั่ง Global มาใส่ให้ หากต้องการกำหนดค่าใด ๆ ให้แตกต่างจาก Global ก็สามารถกำหนดที่ฝั่งซ้ายได้เลย

Stage
ศัพท์ตัวต่อไปก็คือ Stage ซึ่ง Git GUI จะแสดง Stage ของไฟล์ให้เราทราบ ดูจากรูปด้านล่าง ฝั่งซ้าย จะเห็นว่า Git GUI แสดงเป็น 2 โซน คือโซน Unstaged Changes ในแถบสีแดง และโซน Staged Changed (Will Commit) ในแถบสีเขียว
ในครั้งแรก ไฟล์ต่าง ๆ จะอยู่ในโซน Unstaged Changes ถ้าคลิกที่ชื่อไฟล์ Git GUI จะแสดงรายละเอียดของไฟล์นั้น ๆ ที่ฝั่งขวา ในรูปด้านล่าง แสดงว่าไฟล์นี้เป็น Binary file สถานะคือ Untracked และ Not staged
Untracked คือ ไฟล์ที่เราไม่ได้ให้ Git จัดการ ซึ่งตรงนี้ เราสามารถเลือกให้ Git จัดการเฉพาะบางไฟล์ที่อยู่ใน Working Directory ได้ ส่วน Not staged ก็คือส่วนที่บอกให้รู้ว่า ไฟล์มีการเปลี่ยนแปลงไปจากเดิม!!
ในตอนแรก ภายใน Repo ยังว่างเปล่า เพราะฉะนั้น ทุกไฟล์ที่อยู่ใน Working Directory ถือว่ามีการเปลี่ยนแปลงทั้งหมด

สำหรับ Text file ที่อยู่ในโซน Unstaged changes จะแสดงเหมือนกันกับ Binary file และมีการ Preview ให้ดูเนื้อไฟล์ด้วย

เราสามารถบอก Git GUI ว่า ไฟล์ไหนที่เราต้องการ Track โดยการคลิกที่ Icon ด้านหน้าไฟล์ ที่อยู่ในโซน Unstaged Changes ก็จะถูกย้ายเข้าไปอยู่ในโซน Staged Changes
ในทางตรงข้าม ถ้าคลิกที่ Icon หน้าไฟล์ในโซน Staged Changes ก็สามารถย้ายออกไปอยู่ในโซน Unstaged Changes เช่นกัน
ถ้าคลิกที่ชื่อไฟล์ใน Staged Changes จะแสดงรายละเอียดของไฟล์นั้น ๆ ที่ฝั่งขวา ในรูปด้านล่าง แสดงว่าไฟล์นี้มีสถานะคือ Staged for commit และเมื่อเป็น Text file ก็จะแสดงส่วนที่เปลี่ยนแปลงไปจากเดิม ในรูปด้านล่าง แสดงให้เห็นว่าเป็น New file และมีการเพิ่มข้อมูลเข้ามาทั้งหมด 9 บรรทัด แสดงให้เห็นเป็นตัวหนังสือสีเขียว และมีเครื่องหมาย + นำหน้า

ในตอนนี้ Git รับรู้แล้วว่า จะให้เราจัดการเฉพาะไฟล์ b.txt ส่วนอีก 2 ไฟล์ ไม่ต้องสนใจ…
ถ้าเราอยากให้ Git จัดการทุกไฟล์ สามารถคลิกที่ปุ่ม Stage Changed (1) ได้เลย โดยจะมี Dialog (2) ขึ้นมาให้ยืนยันว่าจะ Track ไฟล์ทั้งหมดใช่ไหม

หลังจากกดปุ่ม Stage Changed และยืนยันแล้ว ไฟล์ทั้งหมดจะถูกย้ายเข้าสู่โซน Staged Changes

หากไฟล์ที่เราให้ Git ทำการ Track มีการเปลี่ยนแปลง เราสามารถ Refresh สถานะได้โดยการกดปุ่ม Rescan
จะปิด Git GUI แล้วเปิดใหม่ก็ได้ เพราะฉะนั้น ไม่แนะนำให้เปิด Git GUI ค้างไว้
จากตัวอย่างในรูปด้านล่าง จะเห็นว่ามีการแก้ไขไฟล์ a.txt โดยสถานะจะเป็น Portions staged for commit โดยจะแสดงให้เห็นส่วนที่แตกต่างไปจากเดิม ดังนี้
- บรรทัดที่ถูกแก้ไข แสดงเป็นตัวหนังสือสีแดง และมีเครื่องหมาย – นำหน้า ตามด้วยตัวหนังสือสีเขียว และมีเครื่องหมาย + นำหน้า
- บรรทัดที่ถูกลบ แสดงเป็นตัวหนังสือสีแดง และมีเครื่องหมาย – นำหน้า
- บรรทัดที่เพิ่มใหม่ แสดงเป็นตัวหนังสือสีเขียว และมีเครื่องหมาย + นำหน้า
ส่วนตัวหนังสือสีดำ คือส่วนที่ไมมีการเปลี่ยนแปลง (กรณีไฟล์ที่มีจำนวนบรรทัดเยอะ ๆ Git GUI จะไม่ได้แสดงทั้งไฟล์นะ อย่าเข้าใจผิดว่าเนื้อไฟล์หายไปเน้อออออ)

สรุปเรื่องของ Stage ได้เป็น Chart ได้ตามรูปด้านล่าง
ในวงกลม คือ Stage ที่เราให้ Git จัดการให้นั่นเอง แต่เมื่อไหร่ที่ทำการ Commit ถึงจะถูกเก็บไปอยู่ใน Repo และเข้าสู่ Stage Committed

แล้ว Commit คืออะไร!? อ่านหัวข้อต่อไปกันเลยคร๊าบบบบบ
Commit
การ Commit นั้น จะทำเมื่อต้องการให้ Git เก็บข้อมูลไว้ใน Repo เป็นการถาวร ซึ่งการ Commit นั้น จะนำไฟล์ที่อยู่ในโซน Staged Changes ไปเก็บไว้ บน Git GUI นั้น จะมีปุ่ม Commit (1) ให้ใช้งาน
ถ้าลองกดปุ่ม Commit (1) บน Git GUI จะพบ Dialog แจ้ง Error ตามรูปด้านล่าง ซึ่งจะเป็นคำแนะนำว่า ควรเขียน Message ยังไง

รูปด้านล่างนี้ ในครั้งแรก จะเป็นการทำ Initial Commit (Commit เริ่มต้น) โดยจะต้องเลือก Option เป็น New Commit (1) และใส่ Commit Message (2) ให้เรียบร้อย ก่อนที่จะกดปุ่ม Commit (3)
สำหรับตัวเลือก Amend Last Commit ใช้สำหรับกรณีต้องการให้การ Commit ครั้งนี้ ไปรวมกับ Commit ก่อนหน้าที่อยู่ติดกัน ขอไม่ลงรายละเอียดในจุดนี้นะครับ ไปทดลองกันเองนะ

เมื่อ Commit เรียบร้อย จะมีข้อความแจ้งให้ทราบด้านล่าง
และลองสังเกตุที่โซน Staged Changes นั้น ไม่เห็นรายชื่อไฟล์แล้ว เพราะถูกย้ายไปอยู่ใน Stage Commited แล้วนั่นเอง ส่วนที่แก้ไขไฟล์ a.txt ไปก่อนหน้านี้ ยังอยู่ในโซน Unstaged Changes จึงไม่ถูกเก็บลง Repo ไปด้วย
เพราะฉะนั้น ไฟล์ a.txt ที่ Commit ไปอยู่ใน Repo เรียบร้อยแล้วนั้น จะเป็นไฟล์ก่อนการแก้ไข

สำหรับการใช้งานจริง แนะนำว่า ควรจะแก้ไขเฉพาะไฟล์ที่ต้องการแก้จริง ๆ แล้ว Commit ไปให้หมด เพื่อไม่ให้เกิดความสับสน ส่วนในตัวอย่างด้านบน ต้องการให้ผู้อ่านได้เข้าใจ Stage มากขึ้น (หรืองงกว่าเดิม!?)
Branch
เห็นคำว่า Branch กันมาแล้วใช่ไม๊ครับ ตั้งแต่สร้าง Repo แล้วเต๊อะ มาดูกันต่อว่า Branch นั้นคืออะไร?
Branch นั้น คือกิ่งก้านสาขาของ Source Code เราจะใช้ประโยชน์จาก Branch ได้มากมาย เป็นจุดเด่นของ Git โดย Branch ที่เรารู้จักกันไปแล้ว คือ Branch master
ย้ำกันอีกครั้งว่า Branch master คือ Branch หลัก ที่ Git สร้างให้เราตั้งแต่สร้าง Repo เมื่อเรา Initial Commit เรียบร้อยแล้ว Branch master ถึงจะถูกสร้างขึ้นโดยสมบูรณ์ สังเกตุได้จากการคลิกขวาใน Working Directory จะเห็น Branch ชื่อ master โผล่ขึ้นมาแล้ว (ก่อน Initial Commit จะไม่มีให้เห็น)

บน Git GUI ที่เมนู Branch จะมีให้เราสามารถจัดการกับ Branch ของเราได้ เช่น เมื่อต้องการสร้าง Branch ใหม่ ก็เลือกเมนู Create…

ก็จะมี Create Branch Dialog ขึ้นมาดังรูป ในตัวอย่างจะเป็นการสร้าง Branch ใหม่ชื่อว่า dev_example โดยระบุในช่อง Branch Name (1) แล้วเลือกว่า Branch ที่สร้างใหม่ แตกกิ่งออกมาจาก Branch ไหน โดยเลือกที่ Local Branch (2) ที่ต้องการ (ในตัวอย่าง เลือกจาก Branch master) แล้วกดปุ่ม Create

เมื่อสร้าง Branch ใหม่เรียบร้อยแล้ว Git GUI จะทำการ Checkout ไปที่ Branch ที่เพิ่งสร้างมาใหม่ให้เลย สังเกตุที่ Current Branch แสดงชื่อ Branch ว่า dev_example แล้ว
Checkout ก็คือการเปลี่ยน Branch นั่นแหล่ะ

การสร้าง Branch นั้น Git จะทำกับสิ่งที่อยู่ใน Repo เราจึงเห็นว่าไฟล์ใน Working Directory ที่มีการเปลี่ยนแปลง แต่ยังไม่ได้ Commit ไปนั้น ก็ยังคงอยู่เช่นเดิม
สำหรับการเปลี่ยน Branch สามารถใช้เมนู Branch > Checkout… บน Git GUI ได้เลย หรือจะคลิกขวาใน Working Directory แล้วเลือก Git Branch จาก Context menu แล้วเลือก Branch ที่ต้องการเปลี่ยน ก็สามารถทำได้เช่นกัน
ต่อไป… จะทำการเปลี่ยนชื่อไฟล์ใน Working Directory จาก b.txt เป็น c.txt แล้วแก้ไขข้อมูลใน c.txt เล็กน้อย บน Git GUI จะเห็นทั้งไฟล์ b.txt และ c.txt มีการเปลี่ยนแปลง ทำการย้ายเข้าสู่ Staged Changes ให้เรียบร้อย ส่วนไฟล์ a.txt จะยังไม่แตะต้อง ก็จะเห็นบน Git GUI ดังนี้


ถ้าลองเข้าไปที่เมนู Repository > Visualize All Branch History จะพบกับเครื่องมือตัวใหม่ที่มีชื่อว่า gitk
สามารถเปิดได้จากเมนู Git History บน Context menu ใน Working Directory ได้เช่นกัน

บน gitk จะแสดงประวัติต่าง ๆ ของ Repo (รวมถึงที่อยู่ใน Stage ต่าง ๆ ด้วย)
จุดที่ (1) แสดง Commit ต่าง ๆ ที่เกิดขึ้นเป็นแต่ละแถว โดยจะแสดง Commit Message บรรทัดแรก ให้เห็น และผู้ที่เป็น Committer (2) รวมถึงวัน-เวลา ที่ทำการ Commit (3)
ในจุดที่ (1) จะแสดงให้เห็นว่าแต่ละ Branch ถูก Commit ไปถึงจุดไหน ด้วยกรอบสีเขียว และ Branch ปัจจุบัน จะแสดงด้วยตัวหนา สามารถเปลี่ยน Branch จากที่นี่ ด้วยการคลิกขวาที่ Branch ที่ต้องการ ได้ด้วยนะ
ส่วนอีก 2 บรรทัดที่เขียนว่า Local changes… นั่นคือส่วนที่อยู่ใน Staged แล้ว และบรรทัดที่เขียนว่า Local uncommitted changes… คือส่วนที่ยังอยู่ใน Unstaged ซึ่งสองบรรทัดนี้ หากไม่มีไฟล์อยู่ใน Staged และ Unstaged ก็จะไม่แสดงขึ้นมา
จุดที่ (4) แสดงค่า SHA1 ID ของ Commit ที่กำลังเลือกอยู่ เป็นค่าความถูกต้องที่ไว้อ้างอิงถึง Commit นั้น ๆ นั่นเอง
จุดที่ (5) จะแสดงรายละเอียดต่าง ๆ ของ Commit ที่เลือกในส่วนบน และแสดงรายละเอียดการเปลี่ยนแปลงของไฟล์ต่าง ๆ ใน Commit เรียงต่อ ๆ กันไป โดยจะสัมพันธ์กับจุดที่ (6)

ถ้าเลือกแถวที่เป็น Staged จะเห็นรายละเอียดการเปลี่ยนแปลง และมีการอ้างอิง Commit ที่เป็น Parent ให้ทราบด้วย (วงกลมสีเขียว)
ส่วนรายละเอียด จะเห็นว่า การเปลี่ยนแปลงใน Staged เมื่อเทียบกับ Commit ก่อนหน้านั้น เป็นการเปลี่ยนชื่อไฟล์ b.txt เป็น c.txt นั่นเอง (ต่างจากบน Git GUI ที่แสดงว่าเป็นการลบ b.txt และเพิ่ม c.txt)

ถ้าเลือกไปที่ Unstaged จะแสดงคล้าย ๆ กับที่อยู่ใน Staged เพียงแต่จะไม่มี Parent ของ Commit ก่อนหน้า

กลับไปที่ Git GUI ตรวจสอบ Current Branch ว่ายังอยู่ที่ dev_example ทำการย้ายทุกไฟล์ที่มีการเปลี่ยนแปลงลง Staged แล้ว Commit ให้เรียบร้อย แล้วลองเปิด gitk ดูอีกรอบ จะเห็นเหมือนดังรูปนี้ จะเห็นว่า แสดง Commit สองจุด ซึ่งตำแหน่งที่แสดง Branch dev_example ถูกย้ายไปตำแหน่งใหม่แล้ว
แต่ถ้าลองเลือกไปที่ Commit แรก ลองดูรายละเอียดด้านล่าง ตรงบรรทัด Branch: แล้วลองมา Comment ตอบที่ท้ายบทความกันนะครับ ว่าเป็น Branch อะไร และทำไมถึงเป็นเช่นนั้น ใครตอบได้บ้าง!? [คำถามที่ 1]
ไหน ๆ ก็ไหน ๆ แล้ว ขอให้ผู้อ่านได้ร่วมสนุกไปกับการตอบคำถามไปด้วยซะเลย ช่วยกันทำมาหากินหน่อยนะ

ต่อด้วย [คำถามที่ 2] ให้ลองเปลี่ยน Branch ระหว่างทั้ง 2 Branch ดู แล้วสังเกตุความเปลี่ยนแปลงของไฟล์บน Working Directory และบน gitk
ชักเริ่มจะสนุกละแฮะ…
Branch ยังไม่จบ… ยังเหลือศัพท์อีก 2 ตัว ที่ควรจะรู้ นั่นก็คือ Merge และ Conflict
สำหรับการ Merge คือการรวม Code ของ 2 Branch เข้าด้วยกัน สมมุติต่อจากตัวอย่างที่ทำมาละกันว่า ถ้าเราจะรวม Branch dev_example ไปยัง Branch master นั้น จำเป็นจะต้องเปลี่ยน Branch ไปยัง master ก่อน แล้วจึงสั่งให้ Merge กับ dev_example ซึ่ง Git ก็จะทำการนำ Code ที่อยู่ใน Branch dev_example มารวมกับ master ให้นั่นเอง
เมื่อเปลี่ยน Branch เป็น master แล้ว เราสามารถใช้ Git GUI ทำการ Merge โดยคลิกเข้าไปที่เมนู Merge > Local Merge…

ก็จะพบกับหน้าต่าง Merge Dialog โดยส่วนบนสุด ในวงกลมสีเขียว แสดงข้อความให้ทราบว่า กำลังจะ Merge ไปยัง Branch master (Branch ปัจจุบัน) ให้เลือก Branch dev_example แล้วกดปุ่ม Merge

Git GUI จะแสดงผลการ Merge ให้เราทราบ ซึ่งจากรูปด้านล่าง เป็นการ Merge แบบ Fast-forward เนื่องจากเกิดจากการ Merge dev_example ที่แยกออกมาจาก master ที่ยังอยู่ที่ Commit เดิม
ในรูป จะแสดงให้เห็นเป็นสัญลักษณ์ต่าง ๆ เช่น ตัวเลข + – มากบ้าง น้อยบ้าง คงพอจะเดากันออกใช่ไม๊ว่าหมายถึงอะไร…

ลองเปิด gitk ดู จะเห็นว่า Branch master ย้ายไปอยู่ที่เดียวกับ Branch dev_example แล้ว

ต่อไปให้สร้าง Branch ใหม่มาอีก 2 Branch ชื่อว่า test1 และ test2 โดยคลิกขวาที่ Commit ล่าสุด ที่เห็นบน gitk แล้วเลือกเมนู Create new branch จะมี Make Branch Dialog ขึ้นมา ให้ระบุชื่อ Branch ใหม่ แล้วกดปุ่ม Create


เมื่อสร้าง Branch test1 และ test2 เรียบร้อยแล้ว บน gitk จะแสดงเหมือนรูปด้านล่าง
สรุปว่า ตอนนี้ Commit สุดท้าย อยู่บน Branch ทั้ง 4 Branch

ให้ย้าย Branch ไปที่ test1 และ test2 ทำการแก้ไขไฟล์ c.txt บน Branch ทั้ง 2 Branch ที่คนละตำแหน่งกัน แล้ว Commit ให้เรียบร้อย ดังรูป
ไม่ลงรายละเอียดแล้วนะ คงมองออกกันละเน๊อะ~!! ว่าไฟล์ c.txt เปลี่ยนแปลงยังไงในแต่ละ Branch


หลังจากนั้น ให้ Merge Branch test1 ไปยัง master ด้วย Git GUI ให้เรียบร้อย

ตอนนี้ master ย้ายไปอยู่ตำแหน่งเดียวกันกับ test1 แล้ว เนื่องจากการ Merge เป็นแบบ Fast-forward เช่นเดียวกับตอน Merge กับ dev_example
ต่อไป ให้ Merge Branch test2 ไปยัง master บ้าง เนื่องจากตอนนี้ Commit ล่าสุดที่ master อยู่ เป็นคนละ Commit กับ test2 ไปแล้ว ทำให้เกิดเหตุการณ์ Merge ที่เรียกว่า Three-way merge ซึ่ง Git GUI จะแสดงผลการ Merge ดังรูปด้านล่าง

ถ้าดูบน gitk จะพบว่า หลังจาก Three-way merge แล้วนั้น จะมี Commit ใหม่เกิดขึ้น และใส่ Commit Message ไว้ให้ด้วย โดยจะเป็นการรวมส่วนที่แก้ไขในแต่ละ Branch ที่มา Merge เข้าด้วยกัน จึงจำเป็นต้องเกิดเป็น Commit ใหม่
ถ้าสังเกตุในรายละเอียดของ Commit ที่ Parent จะเห็นว่ามี 2 ตัว ในรูปด้านล่าง แสดงด้วยสีแดง และสีน้ำเงิน และรายละเอียดด้านล่าง จะแสดงสีในแต่ละบรรทัด ตาม Parent ซึ่งก็คือส่วนที่แก้ไขในไฟล์ c.txt บน Parent ทั้ง 2 มารวมกันนั้นเอง…

แล้วถ้าเกิดว่า แก้ไขในจุดเดียวกัน แล้วมา Merge กันล่ะ!? อยากรู้แล้วใช่ไม๊ มาลองกันต่อเลยยยยยย~!!
สร้าง Branch จาก Commit สุดท้ายขึ้นมาใหม่อีก 2 Branch ให้ชื่อว่า test3 และ test4
คราวนี้เรามาแก้ไขไฟล์ a.txt กันบ้าง และเช่นเดิม ให้แก้ไขไฟล์ a.txt บน Branch test3 และ test4 ในตำแหน่งเดียวกัน เสร็จแล้วก็ Commit ให้เรียบร้อย ดังรูปด้านล่าง


แล้วทำการ Merge Branch test3 ไปยัง master ให้เรียบร้อย

ต่อด้วย Merge Branch test4 ไปยัง master…
CONFLICT!!!
เกิด Conflict หรือควาขัดแย้งขึ้นมา เนื่องจากการ Merge ในครั้งนี้ ข้อมูลในไฟล์ a.txt มีการแก้ไขในตำแหน่งเดียวกัน ซึ่ง Git ตัดสินใจแทนเราไม่ได้ว่าจะเลือกจากตัวไหน จึงแจ้งเป็น Error ออกมาให้เห็น ดังรูปด้านล่าง

สังเกตุว่า บน Git GUI จะแสดงผลดังรูปด้านล่าง แสดงให้เห็นว่า ไฟล์ a.txt มี Conflict เกิดขึ้น โดย a.txt อยู่ในโซน Unstaged Changes และ Git นำส่วนที่แตกต่างกัน มารวมกันไว้ให้เราตัดสินใจเอง โดยเพิ่มบรรทัดที่เป็นสีส้ม แสดงขอบเขตของที่มาของข้อมูล เขียนทับลงไปในไฟล์ a.txt ใน Working Directory ของเรา
เนื่องจากว่า ตอนนี้เราอยู่ที่ Branch master บรรทัดสีส้ม แสดงจุดเริ่มต้นว่ามาจาก HEAD !?
HEAD ก็คือ จุดที่เราอยู่ตอนนี้ ก็คือ Branch master ก่อนทำการ Merge นั่นเอง
ข้อมูลที่เห็นในกรอบสีส้ม คือข้อมูลที่มาจาก HEAD หรือ master
ส่วนข้อมูลที่อยู่ในกรอบสีฟ้า คือข้อมูลที่มาจาก test4

วิธีแก้ Conflict ก็คือ ให้เราไปแก้ไขไฟล์ a.txt ใน Working Directory ของเราให้เรียบร้อย ด้วยการ Merge ด้วยมือเราเอง แล้วนำไฟล์ไฟล์ a.txt เข้าสู่โซน Staged Changes เพื่อเตรียม Commit ต่อไป ซึ่ง Git GUI ก็ได้เตรียม Commit Message ไว้ให้เราด้วยแล้ว ถ้าไม่ชอบ ก็แก้ไขได้ตามต้องการ

เมื่อ Commit เรียบร้อย ลองเปิดด้วย gitk ดู จะพบว่า Commit ดังกล่าว คือ Commit ที่เป็นการ Merge นั่นเอง

Tag
มาถึงหัวข้อสุดท้ายในบทความนี้แล้ว ถอนหายใจแพ๊บบบบบ
ฟู่ววววววส์~!!
สำหรับการ Tag นั้น เป็นเหมือนการแปะป้ายไว้ให้รู้ว่า ตำแหน่ง Commit นั้น ๆ คืออะไร แต่การ Tag นั้น ไม่สามารถทำได้บน Git GUI นะ ต้องไปทำบน gitk
วิธีการติด Tag ก็แค่ คลิกขวาที่ Commit ที่ต้องการ แล้วเลือก Create tag

ก็จะพบกับ Make Tag Dialog โดยจะต้องระบุ Tag name (1) ที่ต้องการให้เรียบร้อย ส่วน Tag message (2) หากไม่กำหนด Git จะทำการนำ Commit Message ที่เรากำลังจะติด Tag ไปใส่ไว้ให้ เสร็จแล้วกดปุ่ม Create (3)

เมื่อติด Tag เรียบร้อย จะแสดงเป็นแถบสีเหลืองดังรูปด้านล่าง เมื่อคลิกไปที่ Tag จะแสดงรายละเอียดไว้ด้านล่าง

สำหรับบทความตอนนี้ ขอแนะนำการใช้งาน Git GUI เบื้องต้น (แถม gitk ไปด้วย) แต่เพียงเท่านี้ ที่เหลือก็… ลองผิดลองถูกกันดูนะครับ
สำหรับตอนต่อ ๆ ไป คงจะเริ่มนำไปใช้งานกับภาษาโปรแกรมต่าง ๆ ผู้อ่านอยากให้เขียนเกี่ยวกับการนำไปใช้งานกับภาษาโปรแกรมไหน ลองเสนอกันมาดูนะครับ
อย่าลืมตอบคำถาม 2 ข้อ ที่ถามไว้ด้วยล่ะ
แนะนำ : Git ฉบับอนุบาล ๒, git – ก้าวแรกสู่สังเวียน, Pro Git book
Permalink
ขอบคุณมากครับ
Permalink
ขอบคุณครับ ได้ความรู้เพิ่มเติมเยอะเลย