HEAD, Branch, Tag ใน Git ชี้ไปที่ไหน? เข้าใจ Reference ให้ถ่องแท้

HEAD, Branch และ Tag เป็น References ในระบบ Git ทั้งสามชี้ไปยัง Commits แต่มีวิธีทำงานและลักษณะเด่นต่างกัน ความเข้าใจเกี่ยวกับความแตกต่างระหว่างพวกมันเป็นสิ่งจำเป็นสำหรับการใช้ Git อย่างมีประสิทธิภาพในการจัดการ Version Control

HEAD คืออะไร และบทบาทของมัน

HEAD เป็นตัวชี้พิเศษในระบบ Git ที่ชี้ไปยัง Commit ปัจจุบันที่เราทำงานอยู่ ปกติแล้ว HEAD ชี้ไปยัง Branch ไม่ใช่ Commit โดยตรง ซึ่งเรียกว่า “Symbolic Reference” เมื่อเราสร้าง Commit ใหม่ Branch ที่ HEAD ชี้ไปจะเลื่อนไปยัง Commit ที่เพิ่งสร้างใหม่

ตัวอย่างเช่น ถ้า HEAD ชี้ไปยัง main branch และเราสร้าง Commit ใหม่ชื่อ abc123 main branch จะเลื่อนไปยัง abc123 และ HEAD ยังคงชี้ไปยัง main (ผ่าน Symbolic reference)

Symbolic HEAD vs Detached HEAD

  • Symbolic HEAD – ชี้ไปยัง Branch โดยอ้อม (ตัวอย่าง: refs/heads/main) ซึ่งเป็นสถานะปกติและปลอดภัยในการทำงาน
  • Detached HEAD – ชี้ไปยัง Commit โดยตรง (ตัวอย่าง: abc123) ซึ่งเกิดจากการ Checkout เข้าไปยัง Commit เก่า

เมื่ออยู่ใน Detached HEAD State คุณสามารถสำรวจและทดลอง Code เวอร์ชันเก่าได้อย่างปลอดภัย แต่ต้องระวังการสร้าง Commit ใหม่เพราะว่า Commits นั้นจะไม่เชื่อมต่อกับ Branch ใดๆ หากคุณสลับ Branch การเปลี่ยนแปลงที่ยังไม่ได้บันทึก (Stash) อาจสูญหาย

Branch เป็น Reference ต่อ Commits

Branch คือ Reference ที่ชี้ไปยัง Commit หนึ่งตัว โดยทั่วไปแล้ว Branch ชี้ไปยัง Commit ล่าสุด (Tip) ของสาขาการพัฒนา เมื่อเราสร้าง Commit ใหม่ Branch จะเลื่อนไปยัง Commit ที่เพิ่งสร้างขึ้น โดยอัตโนมัติ

main   -> C4
feature-> C2
release-> C3

Historical timeline:
C1 (initial commit)
 |
 C2 (feature branch point)
 |  \
 C3  C4 (main branch)
 |   |
 ... (more commits)

Branch Name จะถูกเก็บไว้ในไฟล์ข้อความที่เรียบง่าย (.git/refs/heads/) ซึ่งบรรจุ SHA-1 Hash ของ Commit ที่ Branch ชี้ไปยัง สิ่งนี้ทำให้ Branch ใน Git มีน้ำหนักเบา (Lightweight) และรวดเร็วในการสร้าง

Lightweight Tag vs Annotated Tag

  • Lightweight Tag – Reference ธรรมดาชี้ไปยัง Commit ประกอบด้วยเพียง Name และ Commit Hash เท่านั้น เหมาะสำหรับการใช้งานชั่วคราว
  • Annotated Tag – Object ที่บันทึก Tagger Author, Date, และ Message ต่างจาก Lightweight Tag ทำให้เหมาะสำหรับการทำเครื่องหมาย Release ที่เป็นทางการ

Annotated Tag มี SHA-1 Hash ของตัวเอง ซึ่งแตกต่างจาก Commit Hash ที่ Tag ชี้ไปยัง ทำให้ Tag Object นี้ถูกเก็บเป็น Object จริง ในขณะที่ Lightweight Tag เป็นเพียง Reference ไฟล์

สร้าง Tags ด้วยคำสั่ง Git

# สร้าง Lightweight Tag
git tag v1.0

# ดู Tags ทั้งหมด
git tag

# สร้าง Annotated Tag ด้วย Message
git tag -a v1.0 -m "Release version 1.0"

# สร้าง Annotated Tag บน Commit เฉพาะ
git tag -a v1.0 abc123 -m "Release v1.0"

# ดู Details ของ Tag
git show v1.0

# ลบ Tag
git tag -d v1.0

เมื่อใช้ Annotated Tag คุณได้บันทึก Metadata ซึ่งมีประโยชน์สำหรับการติดตามเวอร์ชันรีลีส และสามารถลงนามด้วย GPG key เพื่อความปลอดภัยเพิ่มเติม

Refs เก็บอยู่ที่ไหนใน .git Directory

.git/
  refs/
    heads/      # Local Branches
      main
      develop
      feature/new-api
    remotes/    # Remote Branches
      origin/
        main
        develop
    tags/       # Tags
      v1.0
      v2.0
  HEAD         # Current position (Symbolic Reference)
  packed-refs  # Optimized refs storage

Reference เป็นองค์ประกอบสำคัญในการนำทาง Git Repository และเข้าใจพวกมันจะช่วยให้คุณใช้ Git ได้อย่างชาญฉลาด

Branch Tracking และ Remote References

นอกจาก Local Branches แล้ว Git ยังมี Remote Branches ซึ่งชี้ไปยัง Commits ล่าสุดบนเซิร์ฟเวอร์ Remote Remote Branch อยู่ใน .git/refs/remotes/ ชื่อตามรูปแบบ origin/branch-name

# ดู Remote Branches ทั้งหมด
git branch -r

# Set up Tracking Branch
git branch --track develop origin/develop

# หรือใช้ shortcut ในการ Checkout
git checkout develop  # Git สร้าง Tracking Branch โดยอัตโนมัติ

# ดู Branch ที่มี Tracking Info
git branch -vv

Tracking Branch ช่วยให้ Git รู้ว่าต้องการ Pull หรือ Push ไปยัง Remote Branch ไหน โดยอัตโนมัติ ดู Git Flow Branching Strategy เพื่อเข้าใจแนวทางปฏิบัติที่ดี

ความสำคัญของการเข้าใจ References

References เป็นพื้นฐานของการทำงาน Git ทั้งหมด ดังนี้:

References ก่อตัวเป็น “Smart Pointers” ที่ทำให้ Git มีความยืดหยุ่นและทรงพลัง ในการจัดการ Version Control