บทนำสู่ Git Snapshot Model
Git ใช้ Snapshot Model ในการเก็บ Version Control ต่างจากระบบเก่าๆ เช่น SVN ที่ใช้ Delta Storage วิธีการทำงานที่แตกต่างนี้เป็นพื้นฐานสำคัญของ Git ความเข้าใจเกี่ยวกับ Snapshot vs Delta จะช่วยให้คุณใช้ Git ได้อย่างเต็มศักยภาพและเข้าใจวิธีการทำงานของระบบ Version Control สมัยใหม่ Snapshot Model ถูกออกแบบเพื่อให้ Git มีประสิทธิภาพสูงในการทำงาน branch, merge และอื่นๆ ซึ่งเป็นสิ่งสำคัญสำหรับการพัฒนา Modern ที่เน้น Collaboration และ Rapid Iteration
Snapshot Model คืออะไร – ความหมายและหลักการทำงาน
Snapshot คือการบันทึกสถานะเต็มของ Project ในแต่ละ Commit ไม่ใช่เก็บเพียง Difference ของไฟล์ที่เปลี่ยนแปลง ตัวอย่างเช่น หากคุณมี 100 ไฟล์ในโปรเจกต์ และเปลี่ยนแปลงเพียง 1 ไฟล์ Git ก็ยังคงบันทึก Reference ของไฟล์ทั้ง 100 ไฟล์ในสถานะปัจจุบัน นี่อาจฟังดูเหมือนการใช้ Storage มาก แต่ Git มีการบีบอัดและ Deduplication ที่ชาญฉลาดเพื่อให้ไฟล์ Snapshot ไม่ใช้พื้นที่มากเท่าที่คิด
# ตัวอย่าง Snapshot Model
# Commit 1: สร้าง 3 ไฟล์
file1.txt: "content1"
file2.txt: "content2"
file3.txt: "content3"
# Commit 2: แก้ไข file1 เท่านั้น
file1.txt: "updated content1" (เปลี่ยน)
file2.txt: "content2" (ไม่เปลี่ยน - แต่ยังคงเก็บ reference)
file3.txt: "content3" (ไม่เปลี่ยน - แต่ยังคงเก็บ reference)
# Snapshot ทั้ง 2 มี Tree ที่อ้างอิงไปยัง Blobs:
# Snapshot 1: {blob1, blob2, blob3}
# Snapshot 2: {blob1-updated, blob2, blob3}
# Git ใช้ deduplication ดังนั้น blob2 และ blob3 ใช้ร่วมกัน
ข้อดีของ Snapshot Model
- การ Check-out Branch มีความเร็วสูง: เนื่องจากไม่ต้องคำนวณ Differences – Git เพียงแค่อ่าน Snapshot โดยตรง
- แต่ละ Commit เป็นอิสระ: สามารถเข้าถึง State ของ Project ในช่วงเวลาใดก็ได้โดยไม่ต้องอ้างอิงไปถึง Commits อื่น
- Branch และ Merge ทำได้ง่าย: ไม่ต้องเก็บประวัติความสัมพันธ์ที่ซับซ้อน เพราะแต่ละ Commit เป็น Self-contained
- ข้อมูลไม่ขึ้นต่อลำดับเวลา: สามารถเข้าถึง Commit ในลำดับใดก็ได้ ไม่จำเป็นต้องเรียงลำดับเวลา
- Offline Work ได้เต็มที่: เพราะมี Full History ทุกสิ่งอยู่ในเครื่องของคุณ
- Recovery ทำได้ง่าย: ถ้าคุณลบ Branch ไป ยังคงสามารถเข้าถึง Snapshot ผ่าน Reflog ได้
- Parallel Development: หลาย Developer สามารถทำงานพร้อมกันได้อย่างไม่รบกวนกัน
- Merge Flexibility: สามารถ Merge Branch ที่ซับซ้อนได้อย่างถูกต้องเพราะ Git รู้ Common Ancestor
Git vs SVN: สตรัคเจอร์ต่างกันอย่างไร
SVN (Subversion) และ Git เป็นระบบ Version Control ที่นิยมใช้ แต่มีความแตกต่างหลักในวิธีการเก็บข้อมูล:
- SVN (Delta) – เก็บเพียง Difference ระหว่าง Revision หลายๆ ตัวต่อกัน ประหยัด Storage แต่ประวิติยุ่งและต้องการการคำนวณจำนวนมาก เมื่อต้องการเข้าถึง Revision เก่า
- Git (Snapshot) – เก็บ Full Snapshot ของ Project ในแต่ละ Commit ประสิทธิภาพ Check-out เร็ว แต่ใช้ Storage มากกว่า (จริงๆ แล้วมักจะไม่มากเท่าที่คิดเนื่องจากการบีบอัดและ Deduplication)
ตารางเปรียบเทียบ SVN vs Git
ตารางนี้แสดงความแตกต่างสำคัญระหว่าง SVN และ Git:
┌──────────────────────────┬───────────────────┬─────────────────────┐
│ คุณลักษณะ │ SVN (Delta) │ Git (Snapshot) │
├──────────────────────────┼───────────────────┼─────────────────────┤
│ วิธีการเก็บ │ Differences เท่านั้น │ Full Snapshots │
│ ความเร็วในการ Checkout │ ช้า (ต้องคำนวณ) │ เร็ว (อ่านโดยตรง) │
│ ความเร็วในการ Branch │ ช้า │ เร็วมาก │
│ การเข้าถึง Revision เก่า│ ต้องคำนวณความแตกต่าง │ เข้าถึงโดยตรง │
│ Offline Work │ จำกัด │ เต็มที่ │
│ Merge Complexity │ ซับซ้อน │ ง่าย │
│ Repository Size │ เล็ก │ ใหญ่ (แต่มี Pack) │
│ Data Integrity │ ปกติ │ สูงเพราะ SHA-1 │
│ Branching Speed │ ช้า (ต้องเปลี่ยน files) │ เร็ว (เพียง ref) │
│ Collaboration Model │ Centralized │ Distributed │
└──────────────────────────┴───────────────────┴─────────────────────┘
DAG Structure ของ Git – Directed Acyclic Graph
Git ใช้ DAG (Directed Acyclic Graph) เพื่อแสดงความสัมพันธ์ระหว่าง Commits ทำให้สามารถ Branch และ Merge ได้ง่าย DAG คือกราฟที่มีลูกศร (Directed) แต่ไม่มีวัฏจักร (Acyclic) ซึ่งหมายความว่าไม่มีการวนกลับมาหาตัวเอง โครงสร้างนี้เป็นคุณลักษณะหลักที่ทำให้ Git ถูกออกแบบมาเพื่องานทีมที่มี Parallel Development
# ตัวอย่าง DAG Structure ของ Git
main: C1 -> C3 -> C4 -> C6 (HEAD)
^
|
feature: C1 -> C2 -> C5 (HEAD)
# C1 เป็น Base Commit ของทั้ง 2 Branch
# C3 คือ Merge Commit ที่รวม C2 เข้ามา
# Visualization:
# main: ●———●———●———●
# / \
# feature:●———●———●
# ที่ C3 เมื่อมี merge ทั้ง 2 branches มาบรรจบกัน
# ดู DAG Structure
git log --all --graph --oneline
git log --all --graph --pretty=format:'%H %s'
git log --all --decorate --oneline --graph
โครงสร้าง DAG นี้ช่วยให้ Git สามารถ:
- ติดตามประวัติการเปลี่ยนแปลงได้อย่างชัดเจน เห็นได้ว่า Branch ใดมาจาก Branch ใด
- Merge Branch ที่ซับซ้อนได้อย่างถูกต้อง – Git สามารถหา Common Ancestor โดยอัตโนมัติ
- ค้นหา Common Ancestor ระหว่าง Commits – ใช้สำหรับ Merge หรือ Rebase
- Bisect เพื่อหา Commit ที่มี Bug – ค้นหาแบบ Binary
- ป้องกันการสร้างวัฏจักรใน Commit History – ซึ่งจะทำให้ Repository สับสน
- ทำความเข้าใจความสัมพันธ์ระหว่าง Branches อย่างชัดเจน
Git Objects: Blob, Tree, Commit
Git เก็บข้อมูลในรูป Objects หลัก 3 ประเภท (บวก Tag) ซึ่งทำงานร่วมกันเพื่อสร้าง Snapshot Model ที่มีประสิทธิภาพ
- Blob (Binary Large Object): เก็บเนื้อหาของไฟล์ แต่ละ Blob เป็นการเก็บ Snapshot ของไฟล์ที่บีบอัด ถ้า 2 ไฟล์มีเนื้อหาเหมือนกัน จะใช้ Blob เดียวกัน
- Tree: เก็บโครงสร้างของไดเรกทอรี่ และ Reference ไปยัง Blobs และ Trees อื่น ทำให้ Git รู้ว่าไฟล์ใดอยู่ที่ไหนและมี Permission เป็นอย่างไร
- Commit: เก็บข้อมูลเกี่ยวกับการเปลี่ยนแปลง เช่น Author, Message, Timestamp, และ Reference ไปยัง Tree Object และ Parent Commit
- Tag: ชี้ไปยัง Commit ที่ระบุอย่างชัดเจน เช่น Release Version – ใช้ถ้อยคำที่จำง่ายแทน SHA-1 Hash
# ตัวอย่างการเชื่อมต่อของ Objects ใน Snapshot Model
Commit Snapshot #1 (Initial commit)
├── Tree (root)
│ ├── Blob (file1.txt) - hash: abc111
│ └── Blob (file2.js) - hash: def222
├── Author: Alice
├── Message: "Initial commit"
└── Parent: none (first commit)
Commit Snapshot #2 (Update file1)
├── Tree (root)
│ ├── Blob (file1.txt) - hash: ghi333 (new - updated)
│ └── Blob (file2.js) - hash: def222 (same - reused)
├── Author: Bob
├── Message: "Update file1"
└── Parent: Commit Snapshot #1
# Notice: file2.js blob ถูกใช้ซ้ำเพราะไม่มีการเปลี่ยนแปลง
SHA1 Hash และ Commit ID – ตัวระบุ Unique
Git ใช้ SHA1 Hash Algorithm เพื่อสร้าง Unique ID สำหรับแต่ละ Object โปรดดู Git Object Model Guide สำหรับรายละเอียดเพิ่มเติม Hash ที่ยาว 40 ตัวอักษรนี้คำนวณจากเนื้อหา Object ทั้งหมด รวมถึง Author, Date, Message และ Tree Reference
# ตัวอย่าง Commit ID ใน Snapshot Model
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
Author: John Doe
Date: Fri Mar 29 12:00:00 2026 +0700
Snapshot: Update configuration files
This commit represents the complete state of the project
at this point in time. All files are included (either changed
or unchanged from previous snapshot).
# ตัวอักษร 40 ตัวนี้เป็น SHA-1 hash ของ Commit Object ทั้งหมด
# ถ้าเปลี่ยน Author หรือ Date ไหมแน่ hash ก็จะเปลี่ยน
# ใช้ Abbreviated Hash ได้
git log --oneline
# a1b2c3d Update configuration files
# ดู Hash Length
git rev-parse --short=7 HEAD
git rev-parse --short=10 HEAD
# ดู Full Hash
git rev-parse HEAD
ข้อดีของการใช้ SHA1 Hash
- ป้องกันการแก้ไข Commit: หากมีการแก้ไข Commit Hash ก็จะเปลี่ยนไป ทำให้สามารถตรวจจับการแก้ไขได้ทันที
- ความปลอดภัยเกี่ยวกับข้อมูล: SHA-1 Hash เป็นวิธีที่ปลอดภัยในการระบุ Commits
- ตรวจสอบ Integrity: สามารถตรวจสอบ Integrity ของ Objects ได้ง่าย
- Distributed System: สามารถถ่ายโอน Snapshots ระหว่าง Repositories ได้อย่างปลอดภัย
- Collision Resistance: ความเป็นไปได้ที่จะเกิด Hash Collision น้อยมาก (1 ใน 2^160)
Implications for Performance – ประสิทธิภาพของ Snapshot
- Check-out Branch: มีความเร็วสูง เพราะ Git สามารถอ่าน Snapshot โดยตรง ไม่ต้องคำนวณ Differences จากหลายๆ Deltas
- Branching: ไม่มีค่าใช้จ่าย (overhead) เพิ่มเติม การสร้าง Branch เป็นการสร้าง Reference ไปยัง Commit ที่มีอยู่ – ทำได้ในเวลาคงที่
- Repository ขนาดใหญ่: ประสิทธิภาพยังคงแม่นยำ แม้ว่า Repository มีขนาดใหญ่และมี Commits นับล้าน Git ยังสามารถดำเนินการได้อย่างรวดเร็ว
- Offline Work: ทำได้ได้ด้วย Full History ในเครื่องของคุณ ไม่ต้องเชื่อมต่อ Server เพื่อดู History หรือ Diff
- Clone Speed: ความเร็วขึ้นอยู่กับ Network แต่ไม่ขึ้นกับ Server Computation
- Merge Performance: ความเร็วในการ Merge ไม่ขึ้นกับจำนวน Commits ระหว่าง Branches
ตัวอย่าง Workflow ของการสร้าง Snapshots
# 1. สร้าง 3 ไฟล์ (Snapshot ยังไม่บันทึก - อยู่ใน Working Directory)
echo "content1" > file1.txt
echo "content2" > file2.txt
echo "content3" > file3.txt
# 2. Commit สร้าง Snapshot แรก
git add .
git commit -m "First snapshot - Add 3 files"
# Snapshot 1 ถูกบันทึก:
# - Tree Root ชี้ไปยัง 3 Blobs
# - Commit ชี้ไปยัง Tree นี้
# 3. แก้ไข file1 เท่านั้น
echo "updated content1" > file1.txt
# 4. Commit สร้าง Snapshot ที่สอง
git add file1.txt
git commit -m "Second snapshot - Update file1"
# Snapshot 2 ถูกบันทึก:
# - Tree Root ชี้ไปยัง 3 Blobs (file1 ใหม่, file2 & file3 ใช้เดิม)
# - Commit ชี้ไปยัง Tree นี้ และ Parent Commit
# 5. ดู Snapshots
git log --oneline
# Output:
# xyz789 Second snapshot - Update file1
# abc123 First snapshot - Add 3 files
# 6. Checkout Snapshot แรก
git checkout abc123
# Git โหลด Tree และ Blobs จาก Snapshot แรก
# Working Directory จะมีไฟล์ 3 ตัวในสถานะแรก (ก่อนแก้ไข)
# 7. Checkout Snapshot ที่สอง
git checkout xyz789
# Git โหลด Tree และ Blobs จาก Snapshot ที่สอง
# Working Directory จะมีไฟล์ 3 ตัวในสถานะล่าสุด (file1 ถูกแก้ไข)
# 8. ดู Diff ระหว่าง Snapshots
git diff abc123 xyz789
Index (Staging Area) และการเข้าใจกระบวนการ Staging
ก่อนจะสร้าง Snapshot ไฟล์ต้องผ่านขั้นตอน Staging เป็นแบบ Two-step Process ซึ่งให้คุณควบคุมได้มากขึ้นว่าจะบันทึก Snapshot อะไรบ้าง
# 1. Working Directory (ไฟล์ที่คุณแก้ไข)
modified file1.txt
modified file2.txt
untracked file3.txt
# 2. git add - เพิ่มไปยัง Staging Area (Index)
git add file1.txt file2.txt
# Staging Area ตอนนี้มี:
# - file1.txt (modified)
# - file2.txt (modified)
# 3. git commit - สร้าง Snapshot
git commit -m "Update files"
# Snapshot จะเก็บเพียง file1 และ file2 เท่านั้น
# file3 ยังคงเป็น untracked
# 4. ตรวจสอบสถานะ
git status
# Output:
# On branch main
# Changes not staged for commit:
# deleted: file1.txt
# Untracked files:
# file3.txt
# 5. ดู Staging Area
git diff --cached
# 6. ดู Working Directory Changes
git diff
เปรียบเทียบ Snapshot vs Delta ในทางปฏิบัติ
ลองจินตนาการว่าคุณมี Project ที่เปลี่ยนแปลง 3 ครั้ง แล้วดูความแตกต่างระหว่าง Delta และ Snapshot:
# เปรียบเทียบวิธี Delta vs Snapshot
DELTA MODEL (SVN):
─────────────────────────────────
Revision 1: v1 = {A, B, C}
Delta 2: +A' (update A) = {A', B, C}
Delta 3: +C' (update C) = {A', B, C'}
เมื่อต้องการเข้าถึง Revision 1:
- ต้องเอา v1
- เพิ่ม Delta 2
- เพิ่ม Delta 3
- ผลลัพธ์: {A', B, C'} <- ผิด! ต้องเป็น {A, B, C}
จริง ๆ ต้องเอา v1 → ลบ Delta 2 → ลบ Delta 3 → ได้ {A, B, C}
ซึ่งต้องมี Forward และ Backward Deltas ที่ซับซ้อน
SNAPSHOT MODEL (Git):
────────────────────────────
Snapshot 1: S1 = {blob_A, blob_B, blob_C}
Snapshot 2: S2 = {blob_A', blob_B, blob_C} (blob_B ใช้เดิม)
Snapshot 3: S3 = {blob_A', blob_B, blob_C'} (blob_B ใช้เดิม)
เมื่อต้องการเข้าถึง Snapshot 1:
- เพียงแค่โหลด S1 = {blob_A, blob_B, blob_C}
- สร้างเสร็จในทันที
เมื่อต้องการเข้าถึง Snapshot 3:
- เพียงแค่โหลด S3 = {blob_A', blob_B, blob_C'}
- สร้างเสร็จในทันที
ข้อดี:
✓ ไม่ต้องคำนวณ
✓ ไม่ต้องเก็บ Forward/Backward Deltas
✓ ทั้ง 2 Snapshot เข้าถึงได้เร็วเท่า ๆ กัน
✓ blob_B ถูกแชร์ (Deduplication) ประหยัด Storage
✓ Random Access เป็นไปได้อย่างรวดเร็ว
ความสำคัญสำหรับงาน Development Modern
ความเข้าใจ Snapshot Model เป็นกุญแจสำคัญในการใช้ Git อย่างเต็มศักยภาพ การใช้ ผู้ให้บริการโฮสติ้ง Cloud VPS หรือ Cloud Hosting ในการเก็บ Git Repository จะช่วยให้คุณสามารถจัดการ Project ขนาดใหญ่ได้อย่างมีประสิทธิภาพ บริการ Cloud ของ ผู้ให้บริการโฮสติ้ง มีการ Backup อัตโนมัติ High Availability และการบริหารจัดการ Infrastructure ที่ปลอดภัย
นอกจากนี้ Snapshot Model ยังสำคัญสำหรับการทำ Code Review การ Collaboration ระหว่างทีม และการ Continuous Deployment เพราะแต่ละ Snapshot เป็น Complete State ของ Project ที่สามารถ Deploy ได้โดยตรง ทำให้ไม่มีความเสี่ยงในการ Deploy Partial State ที่อาจทำให้ Application มีปัญหา
Advanced Topics: Performance Optimization
เมื่อทำงานกับ Repository ขนาดใหญ่ที่มี Snapshots นับหมื่น คุณสามารถใช้ Optimization Techniques เหล่านี้:
# Garbage Collection - บีบอัดและจัดระเบียบ Repository
git gc
git gc --aggressive
# ดู Repository Statistics
git count-objects
git count-objects -v
# ดู Size ของ Objects
du -sh .git/objects/
du -sh .git/objects/pack/
# Shallow Clone (สำหรับ Repository ขนาดใหญ่)
git clone --depth 1
git clone --depth 5
# Partial Clone (Sparse Checkout)
git clone --sparse
git sparse-checkout add
# ดู Reflog และเก็บ Snapshots ที่สำคัญ
git reflog
git reflog expire --expire=30.days refs/heads/*
สรุป
Git ใช้ Snapshot Model ซึ่งแตกต่างจากระบบ Version Control เก่าๆ ที่ใช้ Delta Storage แบบ Snapshot ทำให้ Git มีประสิทธิภาพสูงในการ Branch, Merge และ Check-out เนื่องจาก Git ไม่ต้องคำนวณ Deltas เมื่อต้องการเข้าถึง Snapshot เก่า ความเข้าใจนี้จะช่วยให้คุณใช้ Git ได้อย่างเต็มศักยภาพ และทำงาน Development ได้อย่างมีประสิทธิภาพมากขึ้น เมื่อทำงานกับ ผู้ให้บริการโฮสติ้ง Cloud Services จำไว้ว่าการรักษา Repository ให้มีคุณภาพและการ Backup ประจำจะช่วยให้การ Deploy และ Maintenance ทำได้สะดวก
