ความแตกต่างและวิธีใช้ git add และ git commit สำหรับบันทึกการเปลี่ยนแปลง
ในบทความที่ผ่านมา เราได้เรียนรู้ตั้งแต่การติดตั้ง Git, การสร้าง Repository บน GitHub, ไปจนถึงการคัดลอก Repository ของผู้อื่นมายัง PC ของเราด้วยคำสั่ง `git clone` ตอนนี้คุณพร้อมที่จะเริ่มต้นการพัฒนาโดยใช้ Git และ GitHub แล้ว
ในครั้งนี้ เราจะมาเน้นที่คำสั่งสำคัญ 2 คำสั่งที่ใช้บ่อยที่สุดในการบันทึกการเปลี่ยนแปลงในการพัฒนา นั่นคือ `git add` และ `git commit` หลายคนอาจคิดว่า "ทั้งสองคำสั่งก็ใช้บันทึกการเปลี่ยนแปลงเหมือนกันไม่ใช่เหรอ?" แต่จริงๆ แล้วทั้งสองมีหน้าที่แตกต่างกันโดยสิ้นเชิง การเข้าใจความแตกต่างนี้เป็นกุญแจสำคัญในการใช้งาน Git ได้อย่างเชี่ยวชาญ มาทำความเข้าใจกันให้ถ่องแท้เลย!
แนวคิดพื้นฐานของ Git: ทบทวน "3 สถานที่"
เพื่อที่จะเข้าใจความแตกต่างระหว่าง `git add` และ `git commit` ก่อนอื่นเรามาทบทวนแนวคิดเกี่ยวกับ "3 สถานที่" ซึ่งเป็นพื้นฐานของเวิร์กโฟลว์ใน Git กันก่อน แนวคิดนี้จะช่วยให้บทบาทของทั้งสองคำสั่งชัดเจนขึ้น
- ไดเรกทอรีที่ทำงาน (Working Directory): คือโฟลเดอร์บน PC ที่คุณใช้แก้ไขไฟล์ต่างๆ จริงๆ
- พื้นที่เตรียมการ (Staging Area): เป็นเหมือน "ห้องรอ" สำหรับพักการเปลี่ยนแปลงที่คุณต้องการจะบันทึก (commit) ชั่วคราว
- ที่เก็บข้อมูลในเครื่อง (Local Repository): เป็นที่สำหรับบันทึกและจัดเก็บการเปลี่ยนแปลงจากพื้นที่เตรียมการในรูปแบบของประวัติ (commit) อย่างเป็นทางการ
อาจจะเข้าใจง่ายขึ้นถ้าเปรียบเทียบกระบวนการนี้กับการ "ไปซื้อของ"
- เดินเลือกของในร้าน แล้วหยิบสินค้า (การเปลี่ยนแปลงไฟล์) ใส่ตะกร้า (ทำงานในไดเรกทอรีที่ทำงาน)
- นำสินค้าที่ต้องการจะซื้อใส่รถเข็น (ใช้
git addเพื่อเพิ่มไปยังพื้นที่เตรียมการ) - ไปที่เคาน์เตอร์ชำระเงิน จ่ายเงินสำหรับสินค้าทั้งหมดในรถเข็นเพื่อยืนยันการซื้อ (ใช้
git commitเพื่อบันทึกลงในที่เก็บข้อมูลในเครื่อง)
จะเห็นได้ว่า `git add` คือการ "เลือก" เหมือนการใส่ของลงรถเข็น ส่วน `git commit` คือการ "ยืนยันการซื้อ" เพื่อบันทึกข้อมูล ซึ่งบทบาทของทั้งสองนั้นแตกต่างกันโดยสิ้นเชิง
หน้าที่ของ `git add`: "เลือก" การเปลี่ยนแปลงที่จะคอมมิต
หน้าที่หลักของคำสั่ง `git add` คือการเลือกเฉพาะการเปลี่ยนแปลงจากไดเรกทอรีที่ทำงานที่คุณต้องการจะรวมไว้ในคอมมิตถัดไป แล้วส่งไปยังพื้นที่เตรียมการ ทำไมถึงต้องมีขั้นตอนที่ยุ่งยากแบบนี้?
นั่นก็เพื่อเก็บประวัติการเปลี่ยนแปลงในหน่วยที่มีความหมาย ตัวอย่างเช่น สมมติว่าคุณกำลังทำงานสองอย่างพร้อมกัน คือ "แก้ไขคำผิดในส่วนหัว" และ "พัฒนาฟังก์ชันส่วนท้ายใหม่" หากคุณรวมการเปลี่ยนแปลงทั้งสองอย่างไว้ในคอมมิตเดียว เมื่อกลับมาดูประวัติในภายหลัง ก็อาจจะสับสนว่า "คอมมิตนี้ทำอะไรไปบ้างนะ?"
นี่คือจุดที่ `git add` เข้ามามีบทบาท ก่อนอื่นคุณสามารถ `git add` เฉพาะไฟล์ที่แก้ไขคำผิดแล้วคอมมิต จากนั้นจึงค่อย `git add` ไฟล์ของฟังก์ชันส่วนท้ายแล้วคอมมิตเป็นอีกอันหนึ่ง วิธีนี้จะทำให้ประวัติการเปลี่ยนแปลงของคุณสะอาดและเป็นระเบียบมาก ดังนั้น `git add` จึงเป็นขั้นตอนสำคัญในการเพิ่มคุณภาพของคอมมิตของคุณ
หน้าที่ของ `git commit`: "บันทึก" การเปลี่ยนแปลง
หน้าที่ของคำสั่ง `git commit` คือการบันทึกการเปลี่ยนแปลงทั้งหมดที่อยู่ในพื้นที่เตรียมการให้เป็น "จุดบันทึก" หนึ่งจุดอย่างถาวรในที่เก็บข้อมูลในเครื่อง นี่คือหัวใจของการควบคุมเวอร์ชันของ Git
การคอมมิตจะต้องมี "ข้อความคอมมิต (commit message)" ประกอบเสมอ นี่คือบันทึกสั้นๆ ที่อธิบายว่า "มีการเปลี่ยนแปลงอะไรบ้าง" ในจุดบันทึกนั้น การเขียนข้อความคอมมิตที่ดีมีความสำคัญอย่างยิ่งต่อการทำความเข้าใจประวัติการทำงานของตัวคุณเองในอนาคตและของสมาชิกในทีม
git commit -m "แก้ไขลิงก์นำทางในส่วนหัว"
ทันทีที่คุณรันคำสั่งนี้ เนื้อหาในพื้นที่เตรียมการจะถูกถ่ายภาพเป็นสแนปช็อตและบันทึกลงใน repository พร้อมกับ ID ที่ไม่ซ้ำกัน ประวัติที่ถูกคอมมิตแล้วจะไม่หายไป ตราบใดที่คุณไม่ได้ตั้งใจไปแก้ไขมัน
ปฏิบัติจริง! วิธีใช้ add และ commit
เรามาใช้โฟลเดอร์ `my-first-repo` เพื่อตรวจสอบการทำงานของ `git add` และ `git commit` กับการจัดการไฟล์จริงๆ กัน
เตรียมการ: แก้ไขไฟล์สองไฟล์พร้อมกัน
ก่อนอื่น ให้แก้ไขและบันทึกทั้งไฟล์ `index.html` และ `style.css`
- `index.html`: เพิ่มแท็ก `
` หรือทำการเปลี่ยนแปลงอื่นๆ
- `style.css`: เพิ่มสไตล์สำหรับ `body` หรือทำการเปลี่ยนแปลงอื่นๆ
ในสถานะนี้ หากรัน `git status` จะมีการรายงานว่าไฟล์สองไฟล์มีการเปลี่ยนแปลง
git status
กรณีที่ 1: คอมมิตเพียงไฟล์เดียว
ในสถานการณ์ "ต้องการคอมมิตเฉพาะการเปลี่ยนแปลงของ HTML ก่อน" ให้ใช้ `git add` เพื่อระบุเฉพาะไฟล์ที่ต้องการคอมมิต
git add index.html
ณ จุดนี้ หากดู `git status` จะเห็นว่ามีเพียง `index.html` เท่านั้นที่ถูกจัดเตรียม (staged) ส่วน `style.css` ยังคงอยู่ในไดเรกทอรีที่ทำงาน
[ภาพ: ผลลัพธ์ของ git status แสดง index.html เป็นสีเขียว และ style.css เป็นสีแดง]
ในสถานะนี้ ให้ทำการคอมมิต
git commit -m "อัปเดตโครงสร้าง HTML"
เท่านี้ การเปลี่ยนแปลงของ `index.html` ก็ถูกบันทึกเรียบร้อยแล้ว หากรัน `git status` อีกครั้ง จะเห็นว่าเหลือเพียงการเปลี่ยนแปลงของ `style.css` เท่านั้น
กรณีที่ 2: คอมมิตการเปลี่ยนแปลงทั้งหมดพร้อมกัน
ต่อไป เรามาลองคอมมิตการเปลี่ยนแปลงที่เหลือของ `style.css` และการเปลี่ยนแปลงของไฟล์ `script.js` ที่เพิ่มเข้ามาใหม่พร้อมกันดู ก่อนอื่น สร้างไฟล์ใหม่
echo "console.log('Hello, Git!');" > script.js
จากนั้น ใช้ `git add .` เพื่อเตรียมการเปลี่ยนแปลงทั้งหมดในไดเรกทอรีปัจจุบัน (การแก้ไข `style.css` และการเพิ่ม `script.js` ใหม่) ในครั้งเดียว
git add .
สุดท้าย คอมมิตการเปลี่ยนแปลงทั้งหมดนี้พร้อมกัน
git commit -m "ปรับสไตล์ CSS และเพิ่มไฟล์ JS"
เท่านี้ การเปลี่ยนแปลงทั้งหมดก็ถูกบันทึก และไดเรกทอรีที่ทำงานก็กลับสู่สถานะที่สะอาด หากรัน `git status` ควรจะแสดงข้อความว่า "nothing to commit, working tree clean"