<h2>Git เก็บโค้ดทั้งโปรเจกต์ใน 41 ไบต์ได้อย่างไร: ไขปริศนา SHA-1 และระบบควบคุมเวอร์ชันที่อยู่เบื้องหลัง</h2>
<p>Git stores your entire project in 41 bytes... ฟังดูเหลือเชื่อใช่ไหมครับ? ในฐานะนักพัฒนาซอฟต์แวร์และครูสอนโค้ดที่ AiDevThai.com ผมเข้าใจดีว่า Git เป็นเครื่องมือสำคัญที่นักพัฒนาทุกคนต้องรู้จัก แต่มีใครเคยสงสัยไหมว่ามันทำงานยังไงเบื้องลึก? ทำไมเราถึงบอกว่า Git สามารถ "เก็บโค้ดทั้งโปรเจกต์ใน 41 ไบต์" ได้? บทความนี้จะพาทุกคนดำดิ่งไปในโลกของ Git ไขปริศนาของ SHA-1 และโครงสร้างลับที่ทำให้มันเป็นไปได้ รวมถึงกระบวนการตั้งแต่ 'git add' จนถึง 'git push' ที่คุณต้องรู้ เพื่อให้คุณเข้าใจ Git มากกว่าแค่คำสั่งที่ต้องพิมพ์</p>
<div class="key-facts" style="background:#fffbeb;border-left:4px solid #f59e0b;padding:16px 20px;margin:20px 0;border-radius:6px;"><strong>Key Facts ที่คนส่วนใหญ่ไม่รู้</strong><ul><li>Git was created by Linus Torvalds in just 10 days during April 2005 after BitKeeper revoked free licenses</li><li>Every Git commit hash is a SHA-1 generating exactly 40 hexadecimal characters plus 1 newline, totaling 41 bytes of identifier</li><li>GitHub's original codebase was written in Ruby on Rails by Tom Preston-Werner, Chris Wanstrath, and PJ Hyett in October 2007 with only $100,000 seed funding</li></ul></div>
<h3>ทำไมต้องเรียนรู้ Git และมันใช้ทำอะไร?</h3>
<p>Git ไม่ใช่แค่เครื่องมือควบคุมเวอร์ชัน แต่เป็นกระดูกสันหลังของการพัฒนาซอฟต์แวร์สมัยใหม่ มันช่วยให้ทีมงานทำงานร่วมกันบนโค้ดเดียวกันได้อย่างราบรื่น ติดตามการเปลี่ยนแปลง ย้อนกลับไปเวอร์ชันก่อนหน้า และจัดการ Branch ต่างๆ ได้อย่างมีประสิทธิภาพ หากไม่มี Git การพัฒนาโปรเจกต์ขนาดใหญ่จะกลายเป็นความโกลาหลในทันที ลองจินตนาการว่าคุณต้องเขียนโค้ดกับเพื่อนร่วมงานอีก 5 คน โดยไม่มีวิธีติดตามว่าใครแก้ไฟล์ไหนไปแล้วบ้าง นั่นแหละคือฝันร้ายที่ Git เข้ามาช่วยแก้ปัญหาครับ</p>
<p>การเข้าใจการทำงานเบื้องหลังของ Git จะช่วยให้คุณแก้ไขปัญหาได้เมื่อเกิดข้อผิดพลาด และใช้งานมันได้อย่างมีประสิทธิภาพสูงสุด ไม่ว่าคุณจะเพิ่งเริ่มต้นเขียน <a href="https://aidevthai.com/python-%e0%b8%97%e0%b8%b3%e0%b8%87%e0%b8%b2%e0%b8%99%e0%b8%a0%e0%b8%b2%e0%b8%a2%e0%b9%83%e0%b8%99%e0%b8%ad%e0%b8%a2%e0%b9%88%e0%b8%b2%e0%b8%87%e0%b9%84%e0%b8%a3-%e0%b8%88%e0%b8%b2%e0%b8%81%e0%b9%82/">Python ทำงานภายในอย่างไร</a> หรือกำลังสร้าง <a href="https://aidevthai.com/%e0%b8%aa%e0%b8%a3%e0%b9%89%e0%b8%b2%e0%b8%87-saas-%e0%b8%82%e0%b8%b2%e0%b8%a2%e0%b9%80%e0%b8%ad%e0%b8%87-%e0%b8%94%e0%b9%89%e0%b8%a7%e0%b8%a2%e0%b8%97%e0%b8%b8%e0%b8%99%e0%b9%80%e0%b8%a3%e0%b8%b4/">SaaS ขายเอง</a> ที่ซับซ้อน Git คือทักษะพื้นฐานที่ขาดไม่ได้</p>
<h3>สิ่งที่ต้องเตรียม</h3>
<ul>
<li><strong>ติดตั้ง Git:</strong> หากยังไม่มี สามารถดาวน์โหลดได้จาก <a href="https://git-scm.com/downloads" rel="noopener">git-scm.com</a></li>
<li><strong>ความรู้พื้นฐาน Terminal/Command Line:</strong> การใช้งานคำสั่งพื้นฐาน</li>
<li><strong>บัญชี GitHub (ทางเลือก):</strong> เพื่อทดลอง 'git push'</li>
<li><strong>โปรเจกต์โค้ด (หรือสร้างใหม่):</strong> ไฟล์โค้ดง่ายๆ เพื่อใช้เป็นตัวอย่าง</li>
</ul>
<h3>Git เก็บโค้ดทั้งโปรเจกต์ใน 41 ไบต์ ได้อย่างไร: กระบวนการเบื้องลึก</h3>
<p>คำถามที่ว่า Git เก็บโค้ดทั้งโปรเจกต์ใน 41 ไบต์นั้น มาจากความเข้าใจที่ว่า <strong>ทุก Commit ใน Git จะมีรหัส SHA-1 Hash ขนาด 40 ตัวอักษรบวกกับ Newline (รวม 41 ไบต์) ซึ่งเป็นตัวชี้ไปยังสถานะทั้งหมดของโปรเจกต์ ณ ตอนนั้น</strong> นั่นหมายความว่าเพียงแค่คุณรู้ Commit Hash 41 ไบต์นี้ คุณก็สามารถกู้คืนโปรเจกต์ทั้งโปรเจกต์กลับมาได้เลย แต่เบื้องหลังมันทำงานอย่างไร มาดูกันทีละขั้นตอนครับ</p>
<ol>
<li>
<h3>'git add': การบีบอัดและสร้าง Blob Object</h3>
<p>เมื่อคุณใช้คำสั่ง <code>git add <file></code> Git จะเริ่มทำงานโดยการ:
<ul>
<li><strong>บีบอัดเนื้อหาไฟล์ของคุณ:</strong> Git ใช้ algorithms การบีบอัดข้อมูลแบบ <code>zlib deflate</code> เพื่อลดขนาดไฟล์ให้เล็กที่สุด นี่คือสาเหตุหนึ่งที่ Git มีประสิทธิภาพสูงในการจัดการพื้นที่เก็บข้อมูล</li>
<li><strong>สร้าง SHA-1 Hash:</strong> จากนั้น Git จะทำการคำนวณ SHA-1 (Secure Hash Algorithm 1) hash จากเนื้อหาไฟล์ที่บีบอัดแล้วนี้</li>
<pre><code>$ echo "Hello, world!" > hello.txt
$ git init
Initialized empty Git repository in /path/to/myrepo/.git/
$ git add hello.txt
$ find .git/objects -type f
.git/objects/88/4a14ad6b71bf12d93e18a995e8424268e0d4c1
คำอธิบายโค้ด:
-
echo "Hello, world!" > hello.txt: สร้างไฟล์hello.txtพร้อมเนื้อหา -
git init: เริ่มต้น Git repository ใหม่ -
git add hello.txt: เพิ่มไฟล์เข้าสู่ Staging Area ของ Git -
find .git/objects -type f: ค้นหาไฟล์ object ที่ถูกสร้างขึ้นในไดเรกทอรี.git/objects. คุณจะเห็นไฟล์ที่มีชื่อเป็น SHA-1 hash 40 ตัวอักษร เช่น88/4a14ad6b71bf12d93e18a995e8424268e0d4c1
ผลลัพธ์: ไฟล์ที่ถูกบีบอัดนี้จะถูกเก็บเป็น "blob object" ภายในไดเรกทอรี .git/objects. ชื่อของไฟล์ object จะเป็น SHA-1 hash ของข้อมูลนั้นๆ โดย 2 ตัวแรกของ hash จะเป็นชื่อโฟลเดอร์ และอีก 38 ตัวที่เหลือเป็นชื่อไฟล์ สิ่งนี้ทำให้ Git สามารถจัดการไฟล์จำนวนมากได้อย่างรวดเร็ว เนื่องจาก Git's .git/objects directory uses the first 2 characters of SHA-1 hash as folder names, creating exactly 256 possible subdirectories to optimize filesystem performance
'git commit': การสร้าง Tree Object เพื่อเชื่อมโยงไฟล์
หลังจากเพิ่มไฟล์เข้า Staging Area แล้ว เมื่อคุณใช้คำสั่ง git commit -m "Initial commit" Git จะสร้าง "tree object". Tree object เปรียบเสมือน Directory Listing ที่เก็บรายการของไฟล์และโฟลเดอร์ รวมถึง SHA-1 hash ของ blob objects (หรือ tree objects อื่นๆ ในกรณีที่เป็นโฟลเดอร์ย่อย) ที่อยู่ใน Commit นั้นๆ
$ git commit -m "Add hello.txt"
[master (root-commit) 63ea9e3] Add hello.txt
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
$ find .git/objects -type f
.git/objects/63/ea9e30a213e4b779a5e4d2b27a854d9203673c
.git/objects/88/4a14ad6b71bf12d93e18a995e8424268e0d4c1
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391c
$ git cat-file -p 63ea9e30a213e4b779a5e4d2b27a854d9203673c
tree 915234a66e6c1e5445218d6a8947b1968840742f
author Your Name <your.email@example.com> 1678886400 +0700
committer Your Name <your.email@example.com> 1678886400 +0700
Add hello.txt
คำอธิบายโค้ด:
-
git commit -m "Add hello.txt": สร้าง Commit ใหม่พร้อมข้อความ -
find .git/objects -type f: ตอนนี้คุณจะเห็น object เพิ่มขึ้นมาอีก 2 ตัว (Tree Object และ Commit Object ที่เราจะพูดถึงในขั้นตอนถัดไป) -
git cat-file -p <commit-hash>: ใช้ดูเนื้อหาของ Commit Object (ผลลัพธ์ย่อส่วน ไม่แสดง Tree Hash)
ผลลัพธ์: Tree Object จะมี SHA-1 hash เป็นของตัวเอง และจะชี้ไปยัง blob hash ของ hello.txt Git จะสร้าง tree object that maps filenames to their blob SHA-1 hashes in a hierarchical directory structure
'git commit': การสร้าง Commit Object เชื่อมโยงทุกสิ่ง
ทันทีที่คุณ Commit Git จะสร้าง "commit object" ซึ่งเป็นหัวใจสำคัญของ Commit นั้นๆ Commit object จะประกอบด้วย:
- Tree Hash: SHA-1 hash ของ tree object ที่เกี่ยวข้องกับ Commit นี้
- Parent Commit Hash: SHA-1 hash ของ Commit ก่อนหน้า (ถ้ามี) ซึ่งสร้างเป็นสายโซ่ประวัติการเปลี่ยนแปลง
- Author Metadata: ชื่อผู้แต่ง, อีเมล, เวลาที่เขียนโค้ด
- Committer Metadata: ชื่อผู้ Commit, อีเมล, เวลาที่ Commit
- Commit Message: ข้อความอธิบายการเปลี่ยนแปลงของ Commit นั้นๆ
$ git cat-file -p $(git rev-parse HEAD)
tree 915234a66e6c1e5445218d6a8947b1968840742f
author Your Name <your.email@example.com> 1678886400 +0700
committer Your Name <your.email@example.com> 1678886400 +0700
Add hello.txt
คำอธิบายโค้ด:
-
git rev-parse HEAD: ใช้เพื่อหา SHA-1 hash ของ Commit ล่าสุด -
git cat-file -p <commit-hash>: แสดงเนื้อหาของ Commit object มันจะแสดง Tree hash, ข้อมูลผู้แต่ง, ผู้ Commit และ Commit message
ผลลัพธ์: Commit object จะมี SHA-1 hash เป็นของตัวเอง ซึ่งเป็นตัวระบุ Commit ที่ไม่ซ้ำกัน สี่สิบตัวอักษรของ SHA-1 hash นี้คือ "40 ไบต์" ที่เราพูดถึง (บวก 1 ไบต์สำหรับ newline ในทางเทคนิค)
การคำนวณ SHA-1 Hash ของ Commit Object
The commit object gets its own SHA-1 hash calculated from all its content, creating an immutable cryptographic chain นี่คือหัวใจสำคัญที่ทำให้ Git แข็งแกร่ง Hash นี้ไม่ได้คำนวณจากเนื้อหาไฟล์โดยตรง แต่คำนวณจากข้อมูลใน commit object ทั้งหมด (tree hash, parent hash, author, committer, message) หากมีการเปลี่ยนแปลงแม้แต่ตัวอักษรเดียวในข้อมูลเหล่านี้ SHA-1 hash ของ Commit จะเปลี่ยนไปทันที ทำให้ Commit ไม่สามารถเปลี่ยนแปลงได้ (immutable) และสามารถตรวจสอบความถูกต้องของประวัติการเปลี่ยนแปลงทั้งหมดได้
Every Git commit hash is a SHA-1 generating exactly 40 hexadecimal characters plus 1 newline, totaling 41 bytes of identifier. เป็นเอกลักษณ์ที่ไม่ซ้ำกัน เปรียบเสมือนลายนิ้วมือของสถานะโปรเจกต์ทั้งหมด ณ เวลานั้น
การอัปเดต HEAD Reference
หลังจาก Commit สำเร็จ Git จะอัปเดต HEAD reference ในไฟล์ .git/refs/heads/[branch-name] (เช่น .git/refs/heads/master หรือ .git/refs/heads/main) ให้ชี้ไปยัง SHA-1 hash ของ Commit ใหม่ล่าสุด นี่คือวิธีที่ Git รู้ว่า Commit ไหนคือ "ปัจจุบัน" ของ Branch นั้นๆ
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
63ea9e30a213e4b779a5e4d2b27a854d9203673c
คำอธิบายโค้ด:
-
cat .git/HEAD: แสดงว่า HEAD ชี้ไปที่ Branch ไหน -
cat .git/refs/heads/master: แสดง SHA-1 hash ของ Commit ล่าสุดบน Branch master
'git push': การส่งข้อมูลไปยัง GitHub
เมื่อคุณใช้คำสั่ง git push origin master หรือ git push origin main เพื่อส่งโค้ดไปยัง GitHub (หรือ Remote Repository อื่นๆ) Git จะทำการ:
-
Delta Compression: Git ไม่ได้ส่งไฟล์ทั้งหมดไปใหม่ทุกครั้ง แต่มันจะคำนวณ
delta compressionหรือส่วนต่างระหว่าง object ที่มีอยู่แล้วบน Remote กับ object ใหม่ใน Local ของคุณ และส่งไปเฉพาะส่วนที่เปลี่ยนแปลงเท่านั้น ทำให้การ Push ทำได้รวดเร็วและใช้แบนด์วิธน้อยลงมาก -
Pack File: Delta compression objects จะถูกรวมอยู่ใน
pack fileซึ่งเป็นรูปแบบไฟล์ที่ถูกบีบอัดอย่างมีประสิทธิภาพสูงสุด - การตรวจสอบบน GitHub: GitHubReceives the pack file, verifies SHA-1 integrity of all objects, then updates the remote branch reference atomically การตรวจสอบ SHA-1 integrity นี้สำคัญมากเพื่อให้มั่นใจว่าข้อมูลไม่เสียหายระหว่างการส่ง และไม่มีใครแก้ไขประวัติ Commit ได้โดยไม่ถูกตรวจจับ
หากคุณอยากรู้ว่าแพลตฟอร์มอย่าง GitHub สร้างรายได้อย่างไร ลองดูบทความ หาเงินจาก Freelance บน Upwork/Fiverr สำหรับ Dev ไทย ซึ่งหลายงานมักจะเกี่ยวข้องกับการใช้ Git/GitHub ด้วย
<h3>สรุปภาพรวม: Git เก็บทั้งโปรเจกต์ใน 41 ไบต์ ได้อย่างไร</h3>
<p>Git บรรลุ "การเก็บโค้ดทั้งโปรเจกต์ใน 41 ไบต์" ได้เนื่องจากหลักการที่เป็น Directed Acyclic Graph (DAG) และ Content-Addressable Storage:</p>
<ul>
<li><strong>Content-Addressable Storage:</strong> ทุก object ใน Git (blob, tree, commit) ถูกระบุด้วย SHA-1 hash ของเนื้อหาของมัน หากคุณมี SHA-1 hash คุณจะสามารถดึงคืนเนื้อหาต้นฉบับได้เสมอ</li>
<li><strong>Chain of Commits:</strong> Commit object แต่ละตัวเชื่อมโย
Originally published on AI Dev Thai. Daily AI tutorials, coding guides, and tech insights in Thai.
Top comments (0)