Git คือระบบควบคุมเวอร์ชันแบบกระจายศูนย์ (Distributed VCS) ที่ช่วยให้ทีมพัฒนาซอฟต์แวร์สามารถบันทึกการเปลี่ยนแปลงของโค้ด ติดตามประวัติ และทำงานร่วมกันได้อย่างมีประสิทธิภาพสูงสุด
ระบบที่ทำหน้าที่บันทึกการเปลี่ยนแปลงของไฟล์หรือชุดไฟล์เมื่อเวลาผ่านไป เพื่อให้คุณสามารถเรียกดูเวอร์ชันเฉพาะในอดีตกลับมาได้ [1]
"ถ้าคุณเป็นกราฟิกดีไซเนอร์หรือนักพัฒนาเว็บ คุณย่อมต้องการเก็บทุกเวอร์ชันของงานไว้ VCS คือสิ่งที่ฉลาดที่สุดที่จะนำมาใช้" [1]
เก็บฐานข้อมูลการเปลี่ยนแปลงไว้บนเครื่องคอมพิวเตอร์เพียงเครื่องเดียว ง่ายแต่เสี่ยงต่อการสูญหายหากฮาร์ดดิสก์พัง [2]
มีเซิร์ฟเวอร์กลางเก็บไฟล์ทุกเวอร์ชัน ทุกคนดึงไฟล์จากที่นี่ ข้อดีคือจัดการง่าย แต่ถ้าเซิร์ฟเวอร์ล่ม ทุกคนทำงานต่อไม่ได้ [2]
ไคลเอนต์ไม่ได้แค่ดึงไฟล์ล่าสุด แต่ "โคลน" (Mirror) ฐานข้อมูลทั้งหมดมาไว้ที่เครื่องตัวเอง ทำให้ทำงานได้แม้ไม่มีอินเทอร์เน็ตและสำรองข้อมูลได้สมบูรณ์ [3]
ถือกำเนิดขึ้นในปี 2005 โดย Linus Torvalds เพื่อใช้พัฒนา Linux Kernel โดยเน้นแก้ปัญหาของระบบแบบเดิม [3]
ความแตกต่างที่สำคัญที่สุดของ Git คือวิธีการเก็บข้อมูล [4]
เก็บข้อมูลเป็นรายการของ "ความเปลี่ยนแปลง" (Changeset) ของแต่ละไฟล์ตามลำดับเวลา
เก็บภาพรวม (Snapshot) ของไฟล์ทั้งหมด ณ ขณะนั้น ถ้าไฟล์ไหนไม่เปลี่ยน Git จะไม่ออกไฟล์ใหม่ แต่จะชี้ลิงก์ไปที่ไฟล์เดิม [4]
ไฟล์ใน Git จะอยู่ในสถานะใดสถานะหนึ่งต่อไปนี้เสมอ [5]
คุณได้แก้ไขไฟล์แล้ว แต่ยังไม่ได้บันทึกลงในฐานข้อมูล (Working Directory)
คุณได้เลือกไฟล์ที่แก้ไขแล้ว เพื่อเตรียมไว้สำหรับการ Commit ครั้งต่อไป (Staging Area)
ข้อมูลถูกบันทึกลงในฐานข้อมูลของ Git อย่างปลอดภัยแล้ว (.git directory)
สิ่งแรกที่ต้องทำหลังติดตั้ง Git คือการระบุตัวตนของคุณ เพราะข้อมูลนี้จะถูกฝังอยู่ในทุก Commit [5]
# ตั้งชื่อผู้ใช้
$ git config --global user.name "John Doe"
# ตั้งอีเมล (สำคัญสำหรับ GitHub/GitLab)
$ git config --global user.email johndoe@example.com
# ตรวจสอบค่าที่ตั้งไว้
$ git config --list
หมายเหตุ: ใช้ --global เพื่อตั้งค่าเพียงครั้งเดียวสำหรับทุกโปรเจกต์ในเครื่องนี้ [5]
สำหรับเริ่มโปรเจกต์ใหม่ หรือนำโฟลเดอร์ที่มีอยู่เข้าสู่ Git
$ git init --bare djrepo.git
คำสั่งนี้จะสร้างโฟลเดอร์ย่อย .git ขึ้นมา [5]
สำหรับดาวน์โหลดโปรเจกต์ที่มีอยู่แล้วจาก Server (เช่น GitHub)
$ git clone <url>
คุณจะได้สำเนาประวัติทั้งหมดของโปรเจกต์นั้นมา [5]
$ git clone djrepo.git djlocal
คำสั่งนี้จะสร้างโคัดลอกต้นฉบับมาพัฒนาต่อยอดไว้ในโฟล์เดอร์ชื่อ djlocal
git status
คำสั่ง git add เป็นคำสั่งอเนกประสงค์ที่สำคัญมาก [7]
# เพิ่มไฟล์เดียว
$ git add README.md
# เพิ่มทุกไฟล์ในโฟลเดอร์ปัจจุบัน
$ git add .
💡 คิดซะว่าเป็นการ "เพิ่มเนื้อหานี้ลงใน Commit ถัดไป" ไม่ใช่แค่การเพิ่มไฟล์เข้าโปรเจกต์ [7]
คำสั่ง git status บอกแค่ชื่อไฟล์ แต่ git diff บอกเนื้อหาที่เปลี่ยน [1]
ดูสิ่งที่แก้ไปแต่ยังไม่ได้ Add
$ git diff
ดูสิ่งที่จะถูก Commit (เทียบกับ Commit ล่าสุด)
$ git diff --staged
# หรือ --cached [2]
การ Commit คือการบันทึก Snapshot ของ Staging Area ลงในประวัติ [3]
$ git commit -m "ข้อความอธิบายสิ่งที่ทำ"
ใช้ -a เพื่อ Stage ไฟล์ที่ถูก Track อยู่แล้วทั้งหมดอัตโนมัติ [3]
$ git commit -a -m "Update existing files"
master (หรือ main) [6]
HEAD ชี้ที่ master, master ชี้ที่ C3
$ git branch testing
สร้างตัวชี้ใหม่ชื่อ testing แต่ยังไม่ได้ย้ายไปที่นั่น [6]
$ git checkout testing
ย้าย HEAD ไปชี้ที่ testing และเปลี่ยนไฟล์ใน Directory ให้ตรงกับ snapshot นั้น [8]
$ git checkout -b feature-login
นิยมใช้มากที่สุด [9]
การ Branch ใน Git ทำได้เร็วและ "ราคาถูก" (ใช้ทรัพยากรน้อย) จึงควรทำบ่อยๆ [10]
แยกการพัฒนาฟีเจอร์ใหม่ออกมา (เช่น iss53) เพื่อไม่ให้กระทบกับโค้ดหลักที่ใช้งานอยู่ จนกว่าจะเสร็จสมบูรณ์ [9]
เมื่อเจอบั๊กใน Production สามารถสลับกลับมาที่ master สร้าง branch hotfix แก้ไขด่วน แล้ว Merge กลับ โดยไม่ต้องรอฟีเจอร์อื่นเสร็จ [11]
ทดลองไอเดียใหม่ๆ ถ้าไม่เวิร์คก็แค่ลบทิ้ง (git branch -d) โดยไม่ทำให้ history หลักสกปรก [10]
สลับไปมาระหว่างงานต่างๆ ได้ทันทีโดยไม่ต้องกังวลเรื่องไฟล์ตีกัน [10]
เมื่อทำงานใน Branch เสร็จแล้ว เราจะนำกลับมารวมที่ Branch หลัก
# 1. กลับไปที่ branch หลัก
$ git checkout master
# 2. สั่ง merge branch ที่ต้องการเข้ามารวม
$ git merge hotfix
ถ้าประวัติเป็นเส้นตรง Git แค่เลื่อนตัวชี้ master ไปข้างหน้า (ไม่ต้องสร้าง Commit ใหม่) [12]
ถ้าประวัติแยกขาดจากกัน Git จะสร้าง "Merge Commit" ใหม่ที่มีพ่อแม่ 2 ทาง เพื่อรวมผลลัพธ์ [13]
เกิดขึ้นเมื่อบรรทัดเดียวกันในไฟล์เดียวกัน ถูกแก้ไขต่างกันในสอง Branch [14]
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
Git จะหยุดกระบวนการ Merge และใส่เครื่องหมายไว้ในไฟล์เพื่อให้คุณตัดสินใจ [15]
เปิดไฟล์ที่มีปัญหา เลือกว่าจะใช้โค้ดส่วนไหน แล้วลบเครื่องหมาย <<<, ===, >>> ออกให้หมด [16]
ใช้คำสั่ง git add <filename> เพื่อบอก Git ว่าแก้เสร็จแล้ว [16]
ใช้คำสั่ง git commit เพื่อยืนยันการ Merge ให้สมบูรณ์ [17]
Remote คือเวอร์ชันของโปรเจกต์ที่โฮสต์อยู่บนอินเทอร์เน็ตหรือเครือข่ายอื่น (เช่น GitHub, GitLab) [18]
$ git remote -v
output:
origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push)
เป็นชื่อเรียกเล่น (Shortname) มาตรฐานที่ Git ตั้งให้โดยอัตโนมัติเมื่อคุณสั่ง git clone จาก Server [18]
การนำข้อมูลจาก Server ลงมาที่เครื่อง
git fetchgit merge ทันทีเมื่อคุณพร้อมแบ่งปันงานกับทีม คุณต้อง "Push"
# รูปแบบคำสั่ง
$ git push <remote> <branch>
# ตัวอย่างการใช้งานจริง
$ git push origin master
คำสั่งนี้จะทำงานได้ก็ต่อเมื่อ:
pull มา Merge ก่อน) [20]git init
เริ่มสร้าง Repo ใหม่
git clone
คัดลอก Repo จาก Server
git add
เตรียมไฟล์ (Stage)
git commit
บันทึกประวัติ
git status
เช็คสถานะไฟล์
git branch
จัดการ Branch
git merge
รวม Branch
git pull
ดึงงานจาก Server
git push
ส่งงานขึ้น Server
Git ให้เครื่องมือ แต่ไม่ได้ให้ "กฎ" ในการใช้งาน หากไม่มีกลยุทธ์ที่ตกลงกัน ทีมจะเจอปัญหา Merge Conflict และการ Deploy ที่ล่าช้า [1, 2]
โครงสร้างชัดเจน เหมาะกับการปล่อยซอฟต์แวร์เป็นเวอร์ชัน (Versioned Software) [3]
เรียบง่าย เน้นความเร็ว เหมาะสำหรับ Web Apps และ CI/CD [4]
ขั้นสูง รวมโค้ดบ่อยที่สุด ลด Conflict เหมาะกับทีมที่มีระบบ Automated Test แข็งแกร่ง [5]
โมเดลแบบดั้งเดิม (The Old Guard) ที่แยก Master (Production) ออกจาก Develop (Integration) อย่างชัดเจน [6]
แนวคิด "Simple Sandwich" ที่ลดความซับซ้อนเหลือแค่ Master และ Feature Branches เหมาะสำหรับ Web/SaaS [15]
"อะไรก็ตามที่อยู่ใน Main Branch จะต้องพร้อม Deploy เสมอ" [15]
ระดับ Elite: นักพัฒนาทุกคน Commit โค้ดเข้าสู่ Main (Trunk) บ่อยๆ (วันละหลายครั้ง) [20]
Main Branch (The Trunk)
⬇️ Short-lived branches (hours)
⬇️ No long integration hell
| Strategy | Release Frequency | Team Maturity | Best For |
|---|---|---|---|
| Git Flow | รายเดือน / ไตรมาส | ปานกลาง - สูง | Open Source, ซอฟต์แวร์ที่ต้องติดตั้ง (Mobile Apps) [24] |
| GitHub Flow | รายวัน / ต่อเนื่อง | เริ่มต้น - ปานกลาง | Web Apps, SaaS, ทีมขนาดเล็ก-กลาง [4] |
| Trunk-Based | หลายครั้งต่อวัน | สูง (Elite) | ทีม DevOps ที่เชี่ยวชาญ, องค์กรใหญ่ (Google/Netflix) [20] |
💡 คำแนะนำ: เริ่มต้นด้วย GitHub Flow หากคุณเป็นทีมเว็บทั่วไป เพราะสมดุลดีที่สุดระหว่างความง่ายและความเร็ว [25]
ปฏิบัติการ: จำลองการทำงานร่วมกันด้วย Git, GitHub และ PythonAnywhere
จับคู่ 2 คน เพื่อเริ่มทำปฏิบัติการนี้
mysite (ค่า Default)เปิด Bash Console บน PythonAnywhere แล้วรันคำสั่ง:
$ zip -r mysite.zip mysite
mysite.zip ลงมาที่เครื่องคอมพิวเตอร์ของคุณสร้าง Public Repository ชื่อ mysite บน GitHub
เพิ่มไฟล์ README.md โดยระบุข้อมูลดังนี้:
*บรรทัดที่ 2 เว้นว่างไว้สำหรับเพื่อน
ไปที่ Settings -> Collaborators ของ Repo ที่เพิ่งสร้าง
wichit2s (อาจารย์)💡 สำคัญ: ทำทั้ง 2 คน (ต่างคนต่างสร้าง Repo ของตัวเอง)
$ git clone https://github.com/YourUser/mysite.git
mysite.zip แล้วนำไฟล์ทั้งหมดในโฟลเดอร์ mysite ไปใส่ในโฟลเดอร์ที่ Clone มา
.gitignore แล้วนำเนื้อหาจาก Link นี้ไปใส่
gist.githubusercontent.com/.../.gitignore
สลับบทบาท! ตอนนี้ให้ไปทำงานบน Repo ของเพื่อน
ไปที่หน้า GitHub ของเพื่อน กดปุ่ม Fork เพื่อสร้างสำเนามาเป็นของเรา
$ git clone https://github.com/YourUser/FriendRepo.git
แก้ไขไฟล์ README.md โดยเติมข้อมูลของคุณลงในบรรทัดที่ 2
$ git add README.md
$ git commit -m "Add collaborator info"
$ git push
*ตอนนี้ข้อมูลอยู่ที่ Fork ของเรา ยังไม่ไปที่ต้นฉบับของเพื่อน
ไปที่หน้า Fork ของคุณบน GitHub กดปุ่ม "Compare & pull request" ส่งคำขอรวมโค้ดไปยัง Repo ต้นฉบับของเพื่อน
เจ้าของ Repo (เพื่อน) เข้าไปดู PR ตรวจสอบความถูกต้อง แล้วกดปุ่ม "Merge pull request"
🎉 เมื่อเสร็จสิ้น ใน README.md ของทั้งคู่จะมีข้อมูลครบ 2 คน
ส่งลิงก์ GitHub Repository ของตัวเอง
(ที่มี Code Django และ README.md ที่มีชื่อครบ 2 คนแล้ว)