คู่มือ Git ฉบับสมบูรณ์: จากรากฐานสู่ระดับองค์กร (The Complete Git Handbook)

The Complete Git Handbook: From Fundamentals to Enterprise Workflows

คู่มือนี้ครอบคลุมการใช้งาน Git ตั้งแต่พื้นฐานการควบคุมเวอร์ชัน ไปจนถึงเทคนิคขั้นสูงสำหรับทีมระดับองค์กร เนื้อหาเขียนเป็นภาษาไทยพร้อมศัพท์เทคนิคภาษาอังกฤษ มีตัวอย่างโค้ด แผนภาพ และตารางเปรียบเทียบประกอบทุกหัวข้อ เหมาะสำหรับนักพัฒนาทุกระดับที่ต้องการใช้ Git อย่างมืออาชีพและมีประสิทธิภาพ


1. บทนำสู่การควบคุมเวอร์ชัน (Introduction to Version Control)

1.1 ระบบควบคุมเวอร์ชัน (Version Control System) คืออะไร และทำไมถึงจำเป็น

ระบบควบคุมเวอร์ชัน (Version Control System — VCS) คือซอฟต์แวร์ที่บันทึกการเปลี่ยนแปลงของไฟล์หรือชุดไฟล์ตลอดเวลา เพื่อให้สามารถเรียกคืนเวอร์ชันใดก็ได้ในอนาคต

เหตุผลที่จำเป็น:

1.2 วิวัฒนาการ: Local → Centralized → Distributed

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#fabd2f', 'clusterBkg': '#282828', 'titleColor': '#fabd2f', 'edgeLabelBackground': '#282828', 'fontFamily': 'monospace'}}}%%
flowchart TD
    subgraph ERA1["🕰️ ยุคที่ 1: Local VCS (1970s–1980s)"]
        direction LR
        L1["RCS\nRevision Control System"]
        L2["SCCS\nSource Code Control System"]
        L3["💾 ฐานข้อมูล Patch\nบน Machine เดียว"]
        L1 --> L3
        L2 --> L3
    end

    subgraph ERA2["🏢 ยุคที่ 2: Centralized VCS (1990s–2000s)"]
        direction LR
        C1["CVS\nConcurrent Versions System"]
        C2["SVN\nApache Subversion"]
        C3["🖥️ Central Server\nเก็บประวัติทั้งหมด"]
        C1 --> C3
        C2 --> C3
    end

    subgraph ERA3["🌐 ยุคที่ 3: Distributed VCS (2005–ปัจจุบัน)"]
        direction LR
        D1["Git\n(Linus Torvalds, 2005)"]
        D2["Mercurial\n(hg)"]
        D3["🗂️ ทุก Node มีประวัติ\nครบถ้วน (Full Clone)"]
        D1 --> D3
        D2 --> D3
    end

    ERA1 -->|"ข้อจำกัด: ทำงานคนเดียว"| ERA2
    ERA2 -->|"ข้อจำกัด: Single Point of Failure"| ERA3

    style ERA1 fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
    style ERA2 fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style ERA3 fill:#3c3836,stroke:#b8bb26,color:#ebdbb2

เปรียบเทียบสามยุค:

คุณสมบัติ Local VCS Centralized VCS (SVN) Distributed VCS (Git)
การทำงานออฟไลน์
Single Point of Failure ✅ (Server down = ทำงานไม่ได้) ✅ ไม่มี
ความเร็ว เร็ว ช้า (Network) เร็วมาก (Local)
Branch ยาก ยาก/ช้า เร็ว/ง่ายมาก
Merge ยาก ปานกลาง ยอดเยี่ยม
พื้นที่ดิสก์ น้อย น้อย (Client) มากกว่า (Full History)

1.3 แนวคิดหลัก (Core Concepts)

1.3.1 พื้นที่การทำงานสามส่วน (Three Areas)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'secondaryColor': '#3c3836', 'background': '#282828', 'mainBkg': '#3c3836', 'nodeBorder': '#fabd2f', 'fontFamily': 'monospace'}}}%%
flowchart LR
    WD["📁 Working Directory\n(พื้นที่ทำงาน)\nไฟล์ที่เราแก้ไขโดยตรง"]
    SA["📋 Staging Area\n(Index / พื้นที่พักไฟล์)\nเตรียมไฟล์ก่อน Commit"]
    REPO["🗄️ Repository\n(.git directory)\nฐานข้อมูลประวัติทั้งหมด"]
    REMOTE["☁️ Remote Repository\n(GitHub/GitLab)\nเซิร์ฟเวอร์กลาง"]

    WD -->|"git add"| SA
    SA -->|"git commit"| REPO
    REPO -->|"git push"| REMOTE
    REMOTE -->|"git fetch / pull"| REPO
    REPO -->|"git checkout / restore"| WD

    style WD fill:#cc241d,stroke:#fb4934,color:#fbf1c7
    style SA fill:#d79921,stroke:#fabd2f,color:#282828
    style REPO fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style REMOTE fill:#076678,stroke:#83a598,color:#fbf1c7

1.3.2 Snapshot vs Delta

Git ใช้ระบบ Snapshot ไม่ใช่ Delta:

Delta:  v1 → Δ1 → Δ2 → Δ3   (ต้อง replay ทุก delta เพื่อได้ v4)
Snapshot: v1   v2   v3   v4  (เข้าถึงทุก version ได้โดยตรง)

1.4 Git Object Model

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
graph TD
    TAG["🏷️ Tag Object\nv1.0.0\n(SHA: a1b2c3)"]
    COMMIT2["📦 Commit Object\n2nd commit\n(SHA: f3e4d5)"]
    COMMIT1["📦 Commit Object\n1st commit\n(SHA: 9a8b7c)"]
    TREE2["🌳 Tree Object\nroot/\n(SHA: 1c2d3e)"]
    TREE1["🌳 Tree Object\nroot/\n(SHA: 4f5e6d)"]
    BLOB1["📄 Blob Object\nmain.py\n(SHA: 7a8b9c)"]
    BLOB2["📄 Blob Object\nREADME.md\n(SHA: 2b3c4d)"]
    BLOB3["📄 Blob Object\nmain.py v2\n(SHA: 5e6f7a)"]

    TAG --> COMMIT2
    COMMIT2 --> COMMIT1
    COMMIT2 --> TREE2
    COMMIT1 --> TREE1
    TREE2 --> BLOB3
    TREE2 --> BLOB2
    TREE1 --> BLOB1
    TREE1 --> BLOB2

    style TAG fill:#b16286,stroke:#d3869b,color:#fbf1c7
    style COMMIT1 fill:#076678,stroke:#83a598,color:#fbf1c7
    style COMMIT2 fill:#076678,stroke:#83a598,color:#fbf1c7
    style TREE1 fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style TREE2 fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style BLOB1 fill:#3c3836,stroke:#a89984,color:#ebdbb2
    style BLOB2 fill:#3c3836,stroke:#a89984,color:#ebdbb2
    style BLOB3 fill:#3c3836,stroke:#a89984,color:#ebdbb2

Object ทั้ง 4 ประเภท:


2. การติดตั้งและการยืนยันตัวตน (Installation & Authentication)

2.1 การติดตั้ง Git

2.1.1 Windows

# วิธีที่ 1: ใช้ winget (Windows Package Manager)
winget install --id Git.Git -e --source winget

# วิธีที่ 2: ใช้ Chocolatey
choco install git

# วิธีที่ 3: ดาวน์โหลด Installer จาก https://git-scm.com/download/win
# เลือก Options ที่แนะนำ:
# - "Git from the command line and also from 3rd-party software"
# - "Use bundled OpenSSH"
# - "Use the OpenSSL library"
# - "Checkout Windows-style, commit Unix-style line endings" (CRLF → LF)
# - "Use Windows' default console window" หรือ MinTTY

2.1.2 macOS

# วิธีที่ 1: Homebrew (แนะนำ)
brew install git

# วิธีที่ 2: Xcode Command Line Tools
xcode-select --install

# วิธีที่ 3: MacPorts
sudo port install git

# ตรวจสอบเวอร์ชัน
git --version
# git version 2.44.0

2.1.3 Linux

# Ubuntu / Debian
sudo apt update && sudo apt install git -y

# Fedora / RHEL / CentOS
sudo dnf install git -y

# Arch Linux / Void Linux / Manjaro
sudo pacman -S git        # Arch/Manjaro
sudo xbps-install -S git  # Void Linux

# Alpine Linux
sudo apk add git

# ตรวจสอบเวอร์ชัน
git --version

2.2 การตั้งค่าตัวตน (Identity Configuration)

# ===== ตั้งค่า Global (ใช้กับทุก Repository) =====

# ชื่อผู้ใช้ (จะปรากฏใน Commit)
git config --global user.name "Jonathan Quatermain"

# อีเมล (ควรตรงกับ GitHub/GitLab)
git config --global user.email "jonnyq@bigtech.com"

# Text Editor เริ่มต้น
git config --global core.editor "vim"            # Vim
git config --global core.editor "nano"           # Nano
git config --global core.editor "code --wait"    # VS Code

# Default Branch Name (แนะนำ: main แทน master)
git config --global init.defaultBranch main

# ดูการตั้งค่าทั้งหมด
git config --global --list

# ดูไฟล์ config โดยตรง (~/.gitconfig)
cat ~/.gitconfig

ตัวอย่าง ~/.gitconfig ที่สมบูรณ์:

[user]
    name = Jonathan Quatermain
    email = jonnyq@bigtech.com
    signingkey = ABCDEF1234567890

[core]
    editor = code --wait
    autocrlf = input      # Linux/macOS: input, Windows: true
    whitespace = fix
    excludesfile = ~/.gitignore_global

[init]
    defaultBranch = main

[pull]
    rebase = false        # merge (ค่าเริ่มต้น)

[push]
    default = current     # push branch ปัจจุบันไป remote เสมอ

[commit]
    gpgsign = true        # เซ็น GPG ทุก Commit

[alias]
    st = status
    co = checkout
    sw = switch
    br = branch
    lg = log --oneline --graph --decorate --all
    unstage = restore --staged
    last = log -1 HEAD

2.3 การตั้งค่า Authentication

2.3.1 SSH Key (แนะนำ)

# ===== 1. สร้าง SSH Key Pair =====
ssh-keygen -t ed25519 -C "jonnyq@bigtech.com"
# หรือ RSA 4096 bits (สำหรับระบบเก่า)
ssh-keygen -t rsa -b 4096 -C "jonnyq@bigtech.com"

# บันทึกที่: ~/.ssh/id_ed25519 (private key)
#           ~/.ssh/id_ed25519.pub (public key)

# ===== 2. เพิ่ม Key เข้า ssh-agent =====
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# ===== 3. คัดลอก Public Key =====
cat ~/.ssh/id_ed25519.pub
# นำไปวางที่ GitHub: Settings → SSH and GPG keys → New SSH key

# ===== 4. ทดสอบการเชื่อมต่อ =====
ssh -T git@github.com
# Hi attapon! You've successfully authenticated...

# ===== 5. Clone ด้วย SSH =====
git clone git@github.com:username/repo.git

2.3.2 Personal Access Token (PAT) สำหรับ HTTPS

# สร้าง PAT ที่: GitHub → Settings → Developer settings → Personal access tokens
# เลือก Scope: repo, workflow, read:org

# ===== วิธีที่ 1: เก็บ Credential ด้วย Git Credential Manager =====
# ติดตั้ง git-credential-manager
git config --global credential.helper manager

# ===== วิธีที่ 2: เก็บไว้ใน Keychain (macOS) =====
git config --global credential.helper osxkeychain

# ===== วิธีที่ 3: Cache ชั่วคราว (1 ชั่วโมง) =====
git config --global credential.helper 'cache --timeout=3600'

# ===== วิธีที่ 4: ฝัง Token ใน URL (ไม่แนะนำ ใช้เฉพาะ CI/CD) =====
git clone https://<TOKEN>@github.com/username/repo.git

# Clone ด้วย HTTPS + PAT
git clone https://github.com/username/repo.git
# Username: attapon
# Password: <PAT_TOKEN>

2.4 การตั้งค่า .gitattributes

# ===== .gitattributes สำหรับโปรเจกต์ข้ามแพลตฟอร์ม =====

# กำหนด line ending อัตโนมัติ
* text=auto

# ไฟล์ Text: ให้ Git จัดการ line ending
*.py    text eol=lf
*.js    text eol=lf
*.ts    text eol=lf
*.jsx   text eol=lf
*.tsx   text eol=lf
*.html  text eol=lf
*.css   text eol=lf
*.md    text eol=lf
*.json  text eol=lf
*.yaml  text eol=lf
*.yml   text eol=lf
*.sh    text eol=lf

# ไฟล์ Windows Script: ใช้ CRLF
*.bat   text eol=crlf
*.cmd   text eol=crlf
*.ps1   text eol=crlf

# ไฟล์ Binary: ไม่แก้ไข line ending
*.png   binary
*.jpg   binary
*.jpeg  binary
*.gif   binary
*.ico   binary
*.pdf   binary
*.zip   binary
*.tar   binary
*.gz    binary
*.7z    binary
*.mp4   binary
*.mp3   binary

# Git LFS (Large File Storage)
*.psd   filter=lfs diff=lfs merge=lfs -text
*.ai    filter=lfs diff=lfs merge=lfs -text
*.sketch filter=lfs diff=lfs merge=lfs -text

# Export-ignore (ไม่รวมใน git archive)
.gitattributes  export-ignore
.gitignore      export-ignore
.github/        export-ignore
tests/          export-ignore

2.5 Git Aliases เพื่อเพิ่มประสิทธิภาพ

# ===== Alias ที่มีประโยชน์ =====

# แสดง log แบบสวยงาม
git config --global alias.lg \
  "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

# Status แบบย่อ
git config --global alias.st "status -sb"

# Undo last commit (เก็บไฟล์ไว้)
git config --global alias.undo "reset HEAD~1 --mixed"

# List all aliases
git config --global alias.aliases "config --get-regexp alias"

# Push current branch
git config --global alias.pushup "push -u origin HEAD"

# Delete merged branches
git config --global alias.cleanup \
  "!git branch --merged | grep -v '\\*\\|main\\|develop' | xargs -n 1 git branch -d"

2.6 การสร้าง Repository

# ===== git init: สร้าง Repository ใหม่ =====
mkdir my-project && cd my-project
git init
# Initialized empty Git repository in /path/to/my-project/.git/

# สร้างพร้อมกำหนด branch name
git init --initial-branch=main

# ===== git clone: คัดลอก Repository จาก Remote =====

# Clone ปกติ
git clone git@github.com:username/repo.git

# Clone ไปยัง Directory ชื่อที่ต้องการ
git clone git@github.com:username/repo.git my-custom-name

# Shallow Clone (เฉพาะ 1 commit ล่าสุด ใช้กับ Repo ขนาดใหญ่)
git clone --depth=1 git@github.com:username/repo.git

# Clone เฉพาะ Branch ที่ต้องการ
git clone --branch develop git@github.com:username/repo.git

# Clone พร้อม Submodules
git clone --recurse-submodules git@github.com:username/repo.git

3. วงจรการทำงานพื้นฐาน (Basic Git Workflow)

3.1 git status และการอ่านผลลัพธ์

# แสดง Status แบบเต็ม
git status

# แสดง Status แบบสั้น (-s = short, -b = branch)
git status -sb

ตัวอย่างผลลัพธ์และความหมาย:

On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:           ← ไฟล์ใน Staging Area (พร้อม Commit)
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md      ← M = Modified
        new file:   src/app.py     ← A = Added

Changes not staged for commit:     ← ไฟล์เปลี่ยนแปลงแต่ยังไม่ได้ add
  (use "git add <file>..." to update what will be committed)
        modified:   config.json    ← แก้ไขแล้วแต่ไม่ได้ stage

Untracked files:                   ← ไฟล์ใหม่ที่ Git ยังไม่รู้จัก
  (use "git add <file>..." to include in what will be committed)
        notes.txt

รหัสสถานะแบบย่อ (git status -s):

รหัส ความหมาย
M Modified, staged
M Modified, not staged
A Added (new file), staged
D Deleted, staged
D Deleted, not staged
R Renamed, staged
?? Untracked file
!! Ignored file

3.2 git add และ git commit

# ===== git add: เพิ่มไฟล์เข้า Staging Area =====

# Add ไฟล์เดียว
git add README.md

# Add ไฟล์หลายไฟล์
git add src/app.py src/utils.py

# Add ทั้ง Directory
git add src/

# Add ทุกไฟล์ (รวม Untracked ใหม่)
git add .

# Add ทุกไฟล์ที่ Git รู้จัก (ไม่รวม Untracked)
git add -u

# ===== Add แบบ Interactive Patch (-p / --patch) =====
# เลือก Hunk (ส่วนย่อย) ของการเปลี่ยนแปลงทีละส่วน
git add --patch src/app.py
# ตัวเลือก: y=yes, n=no, s=split, e=edit, q=quit, ?=help
# ===== git commit: บันทึก Snapshot =====

# Commit พร้อม message
git commit -m "feat: add user authentication module"

# Commit พร้อมเปิด Editor สำหรับ message ยาว
git commit

# Add + Commit ในขั้นตอนเดียว (เฉพาะไฟล์ที่ tracked)
git commit -am "fix: correct typo in README"

# Commit แบบ Verbose (แสดง diff ใน editor)
git commit -v

3.3 การเขียน Commit Message ที่ดี (Conventional Commits)

รูปแบบ Conventional Commits:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

ประเภท (Type) ที่ใช้บ่อย:

Type ความหมาย ตัวอย่าง
feat เพิ่ม Feature ใหม่ feat(auth): add OAuth2 login
fix แก้ไข Bug fix(api): handle null response
docs แก้ไข Documentation docs: update README installation
style แก้ไข Formatting (ไม่เปลี่ยน Logic) style: format with black
refactor Refactor โค้ด refactor(db): extract query builder
test เพิ่ม/แก้ไข Test test: add unit tests for auth
chore งาน Maintenance chore: update dependencies
perf ปรับปรุง Performance perf: cache database queries
ci แก้ไข CI/CD Config ci: add deployment workflow
build แก้ไข Build System build: migrate to webpack 5

ตัวอย่าง Commit Message ที่ดี:

feat(user): implement JWT token refresh mechanism

- Add RefreshToken model with expiry tracking
- Implement /auth/refresh endpoint
- Auto-rotate refresh tokens on use (token rotation)
- Add Redis caching for blacklisted tokens

Closes #142
BREAKING CHANGE: RefreshToken endpoint now requires Authorization header

3.4 git log และการกรอง

# ===== รูปแบบการแสดงผล =====

# Log แบบเต็ม
git log

# Log แบบย่อ (SHA + message)
git log --oneline

# Log แบบ Graph สวยงาม
git log --oneline --graph --decorate --all

# Log พร้อม Stats (จำนวนบรรทัดที่เปลี่ยน)
git log --stat

# Log พร้อม Diff ทุก Commit
git log -p

# ===== การกรอง (Filtering) =====

# กรองตาม Author
git log --author="Attapon"

# กรองตามวันที่
git log --since="2024-01-01" --until="2024-12-31"
git log --since="2 weeks ago"

# กรองตาม Message
git log --grep="feat"

# กรองตาม File
git log -- src/app.py

# ค้นหาว่า Code บรรทัดไหนถูกเพิ่ม/ลบ (Pickaxe)
git log -S "def authenticate"

# แสดงเฉพาะ N commits ล่าสุด
git log -5

# ===== Format ที่กำหนดเอง =====
git log --pretty=format:"%h | %an | %ad | %s" --date=short

ตัวอย่างผลลัพธ์ git log --oneline --graph:

* f3e4d5a (HEAD -> main, origin/main) feat: add dashboard component
*   9a8b7c3 Merge pull request #42 from feature/auth
|\
| * 2b3c4d1 feat(auth): implement JWT refresh
| * 1a2b3c4 feat(auth): add login endpoint
|/
* 8e9f0a1 fix: correct CORS headers
* 7d8e9f0 chore: update dependencies

3.5 git diff

# ===== ความแตกต่างระหว่างพื้นที่ต่างๆ =====

# Working Directory vs Staging Area (ยังไม่ได้ add)
git diff

# Staging Area vs Last Commit (สิ่งที่จะ commit)
git diff --staged
git diff --cached   # เหมือนกัน

# Working Directory vs Last Commit (ทุกการเปลี่ยนแปลง)
git diff HEAD

# เปรียบเทียบระหว่าง 2 Commits
git diff abc1234 def5678

# เปรียบเทียบระหว่าง 2 Branches
git diff main feature/auth

# ดูเฉพาะชื่อไฟล์ที่เปลี่ยน (ไม่แสดง content)
git diff --name-only HEAD~3

# สรุปสถิติการเปลี่ยนแปลง
git diff --stat HEAD~1

3.6 .gitignore: ไฟล์ที่ไม่ต้อง Track

# ===== ตัวอย่าง .gitignore สำหรับโปรเจกต์ Python/Web =====

# ===== Python =====
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
dist/
*.egg-info/
.eggs/
*.egg

# Virtual Environments
venv/
env/
.venv/
.env/

# ===== Node.js =====
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# ===== IDEs =====
.vscode/
.idea/
*.swp
*.swo
*~

# ===== OS Files =====
.DS_Store          # macOS
Thumbs.db          # Windows
desktop.ini        # Windows

# ===== Environment Variables (สำคัญมาก!) =====
.env
.env.local
.env.production
*.pem
*.key

# ===== Logs & Database =====
*.log
logs/
*.sqlite
*.db

# ===== Build Output =====
dist/
build/
.next/
.nuxt/
# ตรวจสอบว่าไฟล์ถูก ignore หรือไม่
git check-ignore -v secret.txt

# Global gitignore (ใช้กับทุก Repository บน Machine)
git config --global core.excludesfile ~/.gitignore_global

# Force add ไฟล์ที่ถูก ignore (ไม่แนะนำ)
git add -f important.env

4. การจัดการสาขาและการรวมโค้ด (Branching & Merging)

4.1 แนวคิด Branch และ HEAD Pointer

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
gitGraph
   commit id: "c1: init"
   commit id: "c2: add README"
   branch feature/login
   checkout feature/login
   commit id: "c3: add login form"
   commit id: "c4: add auth logic"
   checkout main
   commit id: "c5: fix typo"
   branch hotfix/bug-42
   checkout hotfix/bug-42
   commit id: "c6: fix null pointer"
   checkout main
   merge hotfix/bug-42 id: "Merge hotfix"
   checkout feature/login
   commit id: "c7: add tests"
   checkout main
   merge feature/login id: "Merge feature"

Branch คือ pointer เบา (lightweight pointer) ที่ชี้ไปยัง Commit ล่าสุด ขนาดเพียง 41 bytes (SHA-1 hash + newline) ทำให้การสร้าง/ลบ Branch ใน Git เร็วมาก

HEAD คือ pointer ที่บอกว่า "เราอยู่ที่ไหน" ในปัจจุบัน โดยปกติชี้ไป Branch ล่าสุด

4.2 คำสั่งจัดการ Branch

# ===== ดู Branch =====
git branch           # Local branches
git branch -r        # Remote branches
git branch -a        # All branches

# ===== สร้าง Branch =====
git branch feature/user-profile    # สร้างแต่ไม่ switch
git switch -c feature/user-profile # สร้างและ switch (แนะนำ)
git checkout -b feature/user-profile  # เหมือนกัน (เก่า)

# ===== Switch Branch =====
git switch main              # เปลี่ยนไป main
git checkout main            # เหมือนกัน (เก่า)
git switch -                 # กลับ Branch ก่อนหน้า

# ===== เปลี่ยนชื่อ Branch =====
git branch -m old-name new-name   # เปลี่ยนชื่อ Local
git push origin -u new-name       # Push branch ใหม่
git push origin --delete old-name # ลบ branch เก่าใน Remote

# ===== ลบ Branch =====
git branch -d feature/done     # ลบหลัง Merge แล้ว (safe)
git branch -D feature/abandoned # ลบโดยไม่ต้อง Merge (force)
git push origin --delete feature/done  # ลบจาก Remote

4.3 Merge แบบต่างๆ

4.3.1 Fast-forward Merge

Before:          After:
main:  A─B       main:  A─B─C─D
             →
feature: A─B─C─D    (เพียง move pointer, ไม่มี Merge commit)
# Fast-forward merge (เกิดเมื่อ main ไม่มี commit ใหม่หลังแตก branch)
git switch main
git merge feature/simple-add

# บังคับไม่ให้ Fast-forward (สร้าง Merge commit เสมอ)
git merge --no-ff feature/simple-add

4.3.2 Three-way Merge

Before:                    After:
A─B─E  (main)             A─B─E─M  (main)
   \                 →         \  /
    C─D  (feature)              C─D
# Three-way merge (เกิดเมื่อทั้งสอง branch มี commits ใหม่)
git switch main
git merge feature/user-auth
# Git จะสร้าง Merge commit อัตโนมัติ

4.4 การแก้ไข Merge Conflicts

# ===== สถานการณ์: เกิด Merge Conflict =====
git merge feature/profile
# Auto-merging src/user.py
# CONFLICT (content): Merge conflict in src/user.py
# Automatic merge failed; fix conflicts and then commit the result.

# ===== ดูไฟล์ที่มี Conflict =====
git status
# both modified: src/user.py

# ===== เปิดไฟล์และดู Conflict Markers =====
cat src/user.py

โครงสร้าง Conflict Markers:

<<<<<<< HEAD           โคดจาก Branch จจ (main)
def get_user(id):
    return db.query(User).filter_by(id=id).first()
=======                เสนแบ
def get_user(user_id):
    return User.query.get(user_id)
>>>>>>> feature/profile  โคดจาก Branch ี่ Merge
# ===== แก้ไขด้วยมือ: เลือกโค้ดที่ต้องการ =====
# หลังแก้ไข ไฟล์จะมีแค่โค้ดที่ถูกต้อง

# ===== หรือใช้ mergetool =====
git mergetool                    # เปิด tool ที่ตั้งค่าไว้
git mergetool --tool=vimdiff     # ใช้ vimdiff
git mergetool --tool=vscode      # ใช้ VS Code

# ===== หลังแก้ไขเสร็จ =====
git add src/user.py
git commit   # Git จะสร้าง merge commit message ให้อัตโนมัติ

# ===== ถ้าต้องการยกเลิก Merge =====
git merge --abort

4.5 git tag: การจัดการ Release

# ===== Lightweight Tag (เหมือน branch ที่ไม่ขยับ) =====
git tag v1.0.0

# ===== Annotated Tag (แนะนำสำหรับ Release) =====
git tag -a v1.0.0 -m "Release version 1.0.0 - Initial stable release"

# Tag Commit ที่ผ่านมา
git tag -a v0.9.0 9a8b7c3 -m "Beta release"

# ดู Tags ทั้งหมด
git tag
git tag -l "v1.*"    # กรองด้วย Pattern

# ดูข้อมูล Tag
git show v1.0.0

# Push Tags ไป Remote
git push origin v1.0.0           # Push tag เดียว
git push origin --tags           # Push ทุก tag
git push origin --follow-tags    # Push tags ที่ annotated พร้อม commit

# ลบ Tag
git tag -d v1.0.0-beta           # ลบ Local
git push origin --delete v1.0.0-beta  # ลบ Remote

5. การทำงานร่วมกับ Remote (Working with Remotes)

5.1 Remote Repository

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart TD
    subgraph CLOUD["☁️ Remote Repositories"]
        GH["GitHub\ngithub.com"]
        GL["GitLab\ngitlab.com"]
        BB["Bitbucket\nbitbucket.org"]
        SELF["Self-hosted\nGitea/Forgejo"]
    end

    subgraph DEV1["👨‍💻 Developer 1 (Attapon)"]
        L1["Local Repo\n(Full Clone)"]
        W1["Working Dir"]
    end

    subgraph DEV2["👩‍💻 Developer 2 (Somchai)"]
        L2["Local Repo\n(Full Clone)"]
        W2["Working Dir"]
    end

    GH <-->|"push / fetch"| L1
    GH <-->|"push / fetch"| L2
    L1 <-->|"checkout / commit"| W1
    L2 <-->|"checkout / commit"| W2

    style CLOUD fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style DEV1 fill:#282828,stroke:#83a598,color:#ebdbb2
    style DEV2 fill:#282828,stroke:#b8bb26,color:#ebdbb2

5.2 คำสั่งจัดการ Remote

# ===== ดู Remote =====
git remote           # แสดงชื่อ remote
git remote -v        # แสดงชื่อ + URL

# ===== เพิ่ม Remote =====
git remote add origin git@github.com:username/repo.git
git remote add upstream git@github.com:original-owner/repo.git

# ===== เปลี่ยนชื่อ Remote =====
git remote rename origin old-origin

# ===== เปลี่ยน URL =====
git remote set-url origin git@github.com:new-username/repo.git

# ===== ลบ Remote =====
git remote remove upstream

# ===== ดูข้อมูล Remote โดยละเอียด =====
git remote show origin

5.3 push, fetch, pull และความต่าง

# ===== git fetch: ดึงข้อมูลมาแต่ไม่ merge =====
git fetch origin          # ดึงทุก branch จาก origin
git fetch origin main     # ดึงเฉพาะ branch main
git fetch --all           # ดึงจากทุก remote
git fetch --prune         # ลบ remote-tracking branches ที่ถูกลบแล้ว

# ===== git pull: fetch + merge (หรือ rebase) =====
git pull                  # pull จาก upstream ที่ตั้งไว้
git pull origin main      # ระบุ remote และ branch
git pull --rebase         # ใช้ rebase แทน merge
git pull --ff-only        # เฉพาะ fast-forward (ปลอดภัยกว่า)

# ===== git push: ส่งโค้ดขึ้น Remote =====
git push origin main              # push branch main
git push -u origin feature/auth   # push + ตั้ง upstream
git push --force-with-lease       # force push อย่างปลอดภัย
git push origin --delete old-branch  # ลบ branch ใน remote

ความต่างระหว่าง fetch และ pull:

คำสั่ง สิ่งที่เกิดขึ้น ความปลอดภัย
git fetch ดาวน์โหลด commits ใหม่มาเก็บไว้ ไม่แตะ Working Directory ✅ ปลอดภัยมาก
git pull fetch + merge เข้า branch ปัจจุบัน ⚠️ อาจเกิด conflict
git pull --rebase fetch + rebase บน commits ใหม่ ✅ ประวัติสะอาดกว่า

5.4 Tracking Branch และ Upstream

# ดู Tracking configuration
git branch -vv
# * main        f3e4d5a [origin/main] feat: add dashboard
#   feature/ui  2b3c4d1 [origin/feature/ui: ahead 2] feat: button

# ตั้งค่า Upstream
git branch --set-upstream-to=origin/main main
git push -u origin feature/auth   # -u = --set-upstream

# ดู Remote-tracking branches
git branch -r
# origin/main
# origin/develop
# origin/feature/auth

5.5 Pull Request / Merge Request Workflow

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
sequenceDiagram
    participant Dev as 👨‍💻 Developer
    participant Local as 💻 Local Repo
    participant Remote as ☁️ GitHub/GitLab
    participant Reviewer as 👀 Code Reviewer
    participant CI as 🤖 CI/CD

    Dev->>Local: git switch -c feature/new-api
    Dev->>Local: [แก้โค้ด + commit หลายครั้ง]
    Dev->>Remote: git push -u origin feature/new-api
    Dev->>Remote: เปิด Pull Request
    Remote->>CI: Trigger: run tests
    CI-->>Remote: ✅ Tests Passed
    Remote->>Reviewer: แจ้งเตือน Review
    Reviewer->>Remote: Comment + Request Changes
    Dev->>Local: แก้ไขตาม feedback
    Dev->>Remote: git push (update PR)
    Reviewer->>Remote: ✅ Approve
    Remote->>Remote: Merge PR → main
    Remote->>CI: Trigger: deploy to production

5.6 Branch Protection Rules

# ตัวอย่าง GitHub Branch Protection (main branch)
# Settings → Branches → Add rule

Branch name pattern: main

✅ Require a pull request before merging
  ✅ Require approvals: 2
  ✅ Dismiss stale pull request approvals when new commits are pushed
  ✅ Require review from Code Owners

✅ Require status checks to pass before merging
  ✅ Require branches to be up to date before merging
  Status checks: [ci/tests, ci/lint, security/scan]

✅ Require conversation resolution before merging

✅ Require signed commits

✅ Include administrators

✅ Restrict who can push to matching branches
  [DevOps Team, Release Managers]

6. รูปแบบการทำงานในทีม (Git Workflows for Teams)

6.1 Git Flow

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
gitGraph
   commit id: "init" tag: "v0.1.0"
   branch develop
   checkout develop
   commit id: "setup CI"
   branch feature/login
   checkout feature/login
   commit id: "add login UI"
   commit id: "add auth API"
   checkout develop
   merge feature/login id: "merge login"
   branch feature/dashboard
   checkout feature/dashboard
   commit id: "add dashboard"
   checkout develop
   merge feature/dashboard id: "merge dashboard"
   branch release/1.0.0
   checkout release/1.0.0
   commit id: "bump version"
   commit id: "fix release bugs"
   checkout main
   merge release/1.0.0 id: "Release 1.0.0" tag: "v1.0.0"
   checkout develop
   merge release/1.0.0 id: "sync release"
   checkout main
   branch hotfix/security-patch
   checkout hotfix/security-patch
   commit id: "patch CVE-2024-001"
   checkout main
   merge hotfix/security-patch id: "Hotfix" tag: "v1.0.1"
   checkout develop
   merge hotfix/security-patch id: "sync hotfix"

ประเภท Branch ใน Git Flow:

Branch วัตถุประสงค์ Merge เข้า Merge จาก
main Production code - release, hotfix
develop Integration branch - feature, release, hotfix
feature/* พัฒนา Feature develop develop
release/* เตรียม Release main + develop develop
hotfix/* แก้ Bug ด่วนใน Production main + develop main
# ===== ใช้งาน git-flow extension =====
# ติดตั้ง: apt install git-flow / brew install git-flow

git flow init         # เริ่มต้น Git Flow ใน Repo

git flow feature start user-profile   # สร้าง feature branch
git flow feature finish user-profile  # Merge กลับ develop

git flow release start 1.2.0          # สร้าง release branch
git flow release finish 1.2.0         # Merge ไป main + develop + tag

git flow hotfix start critical-fix    # สร้าง hotfix branch
git flow hotfix finish critical-fix   # Merge ไป main + develop + tag

6.2 GitHub Flow

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart LR
    A["1️⃣ Create Branch\nจาก main"] --> B["2️⃣ Add Commits\n(พัฒนา Feature)"]
    B --> C["3️⃣ Open Pull Request\n(ขอ Review)"]
    C --> D{"4️⃣ Review\nผ่าน?"}
    D -->|"❌ แก้ไข"| B
    D -->|"✅ Approve"| E["5️⃣ Merge to main"]
    E --> F["6️⃣ Deploy\n(อัตโนมัติ)"]

    style A fill:#076678,stroke:#83a598,color:#fbf1c7
    style B fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style C fill:#d79921,stroke:#fabd2f,color:#282828
    style D fill:#3c3836,stroke:#a89984,color:#ebdbb2
    style E fill:#b16286,stroke:#d3869b,color:#fbf1c7
    style F fill:#cc241d,stroke:#fb4934,color:#fbf1c7

กฎของ GitHub Flow:

  1. ทุกอย่างใน main พร้อม Deploy เสมอ
  2. สร้าง Branch ใหม่เสมอเมื่อต้องการเปลี่ยนแปลง
  3. Push Branch ขึ้น Remote สม่ำเสมอ
  4. เปิด Pull Request เมื่อต้องการ Feedback หรือ Merge
  5. Merge เมื่อ PR ถูก Review และ CI ผ่านแล้ว
  6. Deploy ทันทีหลัง Merge

6.3 Trunk-based Development (TBD)

main (trunk) ─── A ── B ── C ── D ── E ──→
                 ↑    ↑    ↑    ↑    ↑
              short-lived branches (< 1 วัน)

หลักการ Trunk-based Development:

# ตัวอย่าง Feature Flag
import os

FEATURE_FLAGS = {
    "new_payment_flow": os.getenv("FF_NEW_PAYMENT", "false") == "true",
    "ai_recommendations": os.getenv("FF_AI_RECS", "false") == "true",
}

def process_payment(order):
    if FEATURE_FLAGS["new_payment_flow"]:
        return new_payment_processor(order)
    else:
        return legacy_payment_processor(order)

6.4 เปรียบเทียบ Workflows

เกณฑ์ Git Flow GitHub Flow Trunk-based
ความซับซ้อน สูง ต่ำ ต่ำ-กลาง
ขนาดทีม ขนาดกลาง-ใหญ่ ทุกขนาด ขนาดกลาง-ใหญ่
Release Frequency Scheduled Continuous Continuous
เหมาะกับ Software แบบ Versioned Web Apps Tech Startups/DevOps
ความยากในการ Merge สูง ต่ำ ต่ำ (merge บ่อย)
Long-lived branches
Feature Flags ไม่จำเป็น ไม่จำเป็น จำเป็น

6.5 Semantic Versioning (SemVer)

รูปแบบ: MAJOR.MINOR.PATCH เช่น 2.4.1

Version = MAJOR . MINOR . PATCH
# Conventional Commits → SemVer mapping:
# fix:     → PATCH (1.0.0 → 1.0.1)
# feat:    → MINOR (1.0.0 → 1.1.0)
# BREAKING CHANGE: → MAJOR (1.0.0 → 2.0.0)

7. เทคนิคขั้นสูง (Advanced Git Techniques)

7.1 git rebase: การจัดเรียง Commit ใหม่

7.1.1 Regular Rebase

Before rebase:             After rebase:
        feature                   feature
         ↓                          ↓
A─B─C─E (main)            A─B─C─E─D'─F' (main)
    ↘                              (reapplied)
     D─F (feature)
# ===== Rebase feature branch บน main =====
git switch feature/user-profile
git rebase main

# ถ้าเกิด Conflict:
# 1. แก้ไข conflict
# 2. git add .
# 3. git rebase --continue
# หรือยกเลิก: git rebase --abort

7.1.2 Interactive Rebase (-i)

# Rebase 5 commits ล่าสุดแบบ interactive
git rebase -i HEAD~5

# เปิด Editor:
# pick f3e4d5a feat: add login form
# pick 9a8b7c3 fix typo
# pick 2b3c4d1 fix another typo
# pick 1a2b3c4 fix yet another typo
# pick 8e9f0a1 feat: add dashboard

# คำสั่งที่ใช้บ่อย:
# pick   = ใช้ commit นี้ตามเดิม
# reword = ใช้ commit นี้แต่แก้ message
# edit   = หยุดเพื่อแก้ไข commit
# squash = รวมกับ commit ก่อนหน้า (เก็บ messages)
# fixup  = รวมกับ commit ก่อนหน้า (ทิ้ง message)
# drop   = ลบ commit นี้
# ตัวอย่าง: Squash 4 commits ล่าสุดเป็น 1
# แก้ Editor เป็น:
# pick f3e4d5a feat: add login form
# fixup 9a8b7c3 fix typo
# fixup 2b3c4d1 fix another typo
# fixup 1a2b3c4 fix yet another typo
# pick 8e9f0a1 feat: add dashboard

7.2 git cherry-pick

# นำ commit เดียวมาใช้ใน branch ปัจจุบัน
git cherry-pick abc1234

# Cherry-pick หลาย commits
git cherry-pick abc1234 def5678

# Cherry-pick range ของ commits
git cherry-pick abc1234..def5678

# Cherry-pick โดยไม่ commit ทันที (ให้ไปแก้ก่อน)
git cherry-pick --no-commit abc1234

# ===== เมื่อไรควรใช้ cherry-pick =====
# ✅ นำ hotfix จาก main ไปใส่ใน release branch
# ✅ นำ feature เล็กๆ ข้าม branch
# ✅ กู้คืน commit ที่ถูก revert โดยไม่ต้องการ
#
# ❌ ไม่ควรใช้แทน merge/rebase เมื่อทำงานกับ feature ทั้งหมด
# ❌ หลีกเลี่ยงการ cherry-pick บน shared branch

7.3 git stash: พักงานชั่วคราว

# ===== บันทึก Stash =====
git stash                           # stash ทุกอย่าง
git stash push -m "WIP: auth fixes" # stash พร้อม message
git stash --include-untracked       # รวม untracked files
git stash --all                     # รวม ignored files ด้วย

# ===== ดู Stash List =====
git stash list
# stash@{0}: On main: WIP: auth fixes
# stash@{1}: WIP on feature/ui: 9a8b7c3 add button

# ===== นำ Stash กลับมา =====
git stash pop                  # เอา stash@{0} มา + ลบออกจาก list
git stash apply stash@{1}      # เอา stash@{1} มา แต่ไม่ลบ
git stash pop --index          # restore staging area ด้วย

# ===== ดูเนื้อหา Stash =====
git stash show stash@{0}       # summary
git stash show -p stash@{0}    # full diff

# ===== ลบ Stash =====
git stash drop stash@{0}       # ลบ stash นี้
git stash clear                # ลบทั้งหมด

# ===== สร้าง Branch จาก Stash =====
git stash branch feature/new-idea stash@{0}

7.4 git commit --amend

# ===== แก้ไข Commit ล่าสุด =====

# แก้ Commit Message อย่างเดียว
git commit --amend -m "feat: add user authentication with JWT"

# เพิ่มไฟล์ที่ลืมไว้ใน Commit ล่าสุด
git add forgotten-file.py
git commit --amend --no-edit   # ไม่เปลี่ยน message

# ⚠️ อย่า amend commit ที่ push ขึ้น shared branch แล้ว!
# ถ้าจำเป็นต้อง push: git push --force-with-lease
จำนวนขั้นตอนสูงสุด = log 2 ( n )

โดยที่ n คือจำนวน Commits ระหว่าง good และ bad commit หากมี 1024 commits ใช้เพียง 10 ขั้นตอน

# ===== เริ่ม Bisect =====
git bisect start

# บอก Git ว่า Commit ปัจจุบัน (HEAD) มี Bug
git bisect bad

# บอก Git ว่า Commit นี้ยังดีอยู่ (ก่อนที่ Bug จะเกิด)
git bisect good v1.2.0

# Git จะ checkout ไปยัง Commit กลาง
# ทดสอบ → แจ้งผล:
git bisect good   # ถ้า Bug ยังไม่ปรากฏ
git bisect bad    # ถ้า Bug ปรากฏ

# ทำซ้ำจนกว่า Git จะบอก commit ที่ทำให้เกิด Bug

# ===== Automated Bisect (ใช้ Script) =====
git bisect start HEAD v1.2.0
git bisect run python test_login.py   # script return 0=good, nonzero=bad

# ===== จบ Bisect =====
git bisect reset   # กลับสู่ HEAD เดิม

7.6 git worktree: ทำงานหลาย Branch พร้อมกัน

# สร้าง Working Tree ใหม่สำหรับ Branch อื่น
git worktree add ../hotfix-branch hotfix/critical-fix

# ดู Worktrees ทั้งหมด
git worktree list

# ลบ Worktree
git worktree remove ../hotfix-branch

# ===== ประโยชน์ =====
# - รีวิว PR ใน directory แยก โดยไม่ต้อง stash งานปัจจุบัน
# - Fix hotfix ใน window แยก ขณะที่ยังพัฒนา feature อยู่
# - Build/Test หลาย branch พร้อมกัน

8. การย้อนกลับและกู้คืนข้อมูล (Undoing Changes & Recovery)

8.1 ภาพรวมคำสั่ง Undo

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart TD
    Q["ต้องการ Undo อะไร?"]

    Q --> A{"ไฟล์ใน\nWorking Dir"}
    Q --> B{"ไฟล์ใน\nStaging Area"}
    Q --> C{"Commit\nล่าสุด"}
    Q --> D{"หลาย Commits\n(Private branch)"}
    Q --> E{"Commits บน\nShared branch"}

    A --> A1["git restore <file>\ngit checkout -- <file>"]
    B --> B1["git restore --staged <file>\ngit reset HEAD <file>"]
    C --> C1["git commit --amend"]
    D --> D1["git reset --hard HEAD~N\n(ลบ commits ทิ้ง)"]
    E --> E1["git revert HEAD\n(สร้าง commit กลับ)"]

    style Q fill:#d79921,stroke:#fabd2f,color:#282828
    style A1 fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style B1 fill:#427b58,stroke:#8ec07c,color:#fbf1c7
    style C1 fill:#076678,stroke:#83a598,color:#fbf1c7
    style D1 fill:#cc241d,stroke:#fb4934,color:#fbf1c7
    style E1 fill:#b16286,stroke:#d3869b,color:#fbf1c7

8.2 git restore

# ===== ยกเลิกการแก้ไขไฟล์ใน Working Directory =====
git restore README.md                # คืนค่าไฟล์จาก Staging
git restore .                        # คืนทุกไฟล์
git restore --source=HEAD~2 app.py   # คืนเวอร์ชันจาก 2 commits ที่แล้ว

# ===== ยกเลิกการ Stage ไฟล์ =====
git restore --staged README.md       # เอาออกจาก Staging Area
git restore --staged .               # เอาทุกไฟล์ออกจาก Staging

# ===== ยกเลิกทั้ง Stage และ Working Dir =====
git restore --staged --worktree README.md

8.3 git reset

# HEAD~1 = 1 commit ก่อน HEAD
# HEAD~3 = 3 commits ก่อน HEAD
# abc1234 = Commit hash ที่ต้องการ

# ===== --soft: ย้าย HEAD แต่เก็บไฟล์ไว้ใน Staging =====
git reset --soft HEAD~1
# → Commit หายไป แต่การเปลี่ยนแปลงยังอยู่ใน Staging (พร้อม Commit ใหม่)

# ===== --mixed: ย้าย HEAD และล้าง Staging (default) =====
git reset HEAD~1
git reset --mixed HEAD~1
# → Commit หายไป การเปลี่ยนแปลงกลับมาอยู่ใน Working Directory

# ===== --hard: ย้าย HEAD, ล้าง Staging, ล้าง Working Directory =====
git reset --hard HEAD~1
# ⚠️ อันตราย! การเปลี่ยนแปลงหายไปหมด ไม่สามารถกู้คืนได้ง่าย

# Reset ไปยัง Commit ที่ระบุ
git reset --hard abc1234

# ===== ตัวอย่างการใช้งาน =====
# Squash 3 commits สุดท้ายเป็น 1:
git reset --soft HEAD~3
git commit -m "feat: complete user authentication system"

8.4 git revert

# สร้าง Commit ใหม่ที่กลับค่าการเปลี่ยนแปลงของ Commit ที่ระบุ
# ✅ ปลอดภัยสำหรับ Shared/Public branch เพราะไม่เขียนประวัติใหม่

# Revert commit ล่าสุด
git revert HEAD

# Revert commit เฉพาะ
git revert abc1234

# Revert หลาย commits (สร้างทีละ 1 commit)
git revert HEAD~3..HEAD

# Revert แบบ No-commit (จัดกลุ่มหลาย revert เป็น 1 commit)
git revert --no-commit HEAD~3..HEAD
git commit -m "revert: rollback last 3 commits due to breaking change"

# Revert merge commit (ต้องระบุ parent)
git revert -m 1 abc1234  # -m 1 = ใช้ parent แรก (mainline)

8.5 git reflog: กู้คืน Commit ที่หายไป

# ===== reflog คือ log ของทุกการเคลื่อนไหว HEAD =====
git reflog
# HEAD@{0}: reset: moving to HEAD~3
# HEAD@{1}: commit: feat: add payment module
# HEAD@{2}: commit: feat: add cart feature
# HEAD@{3}: commit: feat: add product listing

# ===== กู้คืน Commit ที่ถูก reset --hard ไป =====
# 1. หา SHA ของ commit ที่ต้องการ
git reflog | grep "feat: add payment"

# 2. สร้าง branch จาก commit นั้น
git branch recovery/payment abc1234

# หรือ reset กลับไปยัง commit นั้น
git reset --hard HEAD@{2}

# ===== กู้คืน Branch ที่ถูกลบ =====
git reflog | grep "feature/deleted-branch"
git checkout -b feature/deleted-branch abc1234

8.6 ตารางเปรียบเทียบคำสั่ง Undo

สถานการณ์ คำสั่ง ปลอดภัยใน Shared Branch หมายเหตุ
ยกเลิกแก้ไขใน Working Dir git restore <file> การเปลี่ยนแปลงหายถาวร
เอาไฟล์ออกจาก Staging git restore --staged <file> ไม่กระทบ Working Dir
แก้ Commit Message ล่าสุด git commit --amend ห้ามทำบน pushed commit
ลบ Commit ล่าสุด (เก็บไฟล์) git reset --soft HEAD~1 ใช้เฉพาะ Local
ลบ Commit ล่าสุด (ทิ้งไฟล์) git reset --hard HEAD~1 อันตราย!
กลับค่า Commit (Public) git revert <hash> สร้าง commit ใหม่
กู้คืน Commit ที่หายไป git reflog + git reset ⚠️ ใช้ภายใน 30 วัน

9. Automation และ Integration (Git Hooks & CI/CD)

9.1 Git Hooks

Git Hooks คือสคริปต์ที่ Git รันอัตโนมัติเมื่อเกิด Event บางอย่าง อยู่ที่ .git/hooks/

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart LR
    subgraph CLIENT["💻 Client-side Hooks"]
        direction TB
        H1["pre-commit\n(ก่อน Commit)\nLint, Tests, Format"]
        H2["prepare-commit-msg\n(สร้าง Message Template)"]
        H3["commit-msg\n(ตรวจสอบ Message Format)"]
        H4["post-commit\n(หลัง Commit)\nNotifications"]
        H5["pre-push\n(ก่อน Push)\nRun Tests"]
        H1 --> H2 --> H3 --> H4
    end

    subgraph SERVER["🖥️ Server-side Hooks"]
        direction TB
        S1["pre-receive\n(ก่อนรับ Push)"]
        S2["update\n(ต่อ Branch)"]
        S3["post-receive\n(หลังรับ Push)\nDeploy, Notify"]
        S1 --> S2 --> S3
    end

    CLIENT -->|"git push"| SERVER

    style CLIENT fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style SERVER fill:#282828,stroke:#83a598,color:#ebdbb2
#!/bin/bash
# .git/hooks/pre-commit (chmod +x)
# ===== ตรวจสอบ Code Style ก่อน Commit =====

echo "🔍 Running pre-commit checks..."

# 1. ตรวจ Python syntax
if git diff --cached --name-only | grep -q "\.py$"; then
    echo "  → Checking Python syntax..."
    git diff --cached --name-only | grep "\.py$" | xargs python -m py_compile
    if [ $? -ne 0 ]; then
        echo "❌ Python syntax error found!"
        exit 1
    fi
fi

# 2. ตรวจ trailing whitespace
if git diff --cached | grep -q "^+.*[[:space:]]$"; then
    echo "❌ Trailing whitespace found!"
    git diff --cached | grep -n "^+.*[[:space:]]$"
    exit 1
fi

echo "✅ Pre-commit checks passed!"
exit 0
#!/bin/bash
# .git/hooks/commit-msg (chmod +x)
# ===== ตรวจสอบ Conventional Commit format =====

COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build)(\(.+\))?: .{1,72}"

if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
    echo "❌ Commit message does not follow Conventional Commits format!"
    echo ""
    echo "Expected format: <type>(<scope>): <description>"
    echo "Example: feat(auth): add JWT token validation"
    echo ""
    echo "Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build"
    exit 1
fi

echo "✅ Commit message format OK"
exit 0

9.2 Husky + lint-staged (Node.js Projects)

# ===== ติดตั้ง =====
npm install --save-dev husky lint-staged

# เปิดใช้งาน Husky
npx husky init
// package.json
{
  "scripts": {
    "prepare": "husky"
  },
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{css,scss}": [
      "stylelint --fix",
      "prettier --write"
    ],
    "*.py": [
      "black",
      "flake8"
    ]
  }
}
# .husky/pre-commit
#!/bin/sh
npx lint-staged

# .husky/commit-msg
#!/bin/sh
npx --no -- commitlint --edit $1
// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'test', 'chore', 'perf', 'ci', 'build', 'revert'
    ]],
    'subject-max-length': [2, 'always', 72]
  }
}

9.3 GitHub Actions: CI/CD Workflow

# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

env:
  PYTHON_VERSION: "3.11"
  NODE_VERSION: "20"

jobs:
  # ===== Job 1: Code Quality =====
  lint:
    name: 🔍 Lint & Format Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: Install dependencies
        run: |
          pip install black flake8 mypy
          pip install -r requirements.txt

      - name: Run Black (formatter)
        run: black --check .

      - name: Run Flake8 (linter)
        run: flake8 . --max-line-length=88

      - name: Run MyPy (type checker)
        run: mypy src/

  # ===== Job 2: Tests =====
  test:
    name: 🧪 Run Tests
    runs-on: ubuntu-latest
    needs: lint
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12"]
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: pip install -r requirements.txt -r requirements-dev.txt

      - name: Run tests with coverage
        run: |
          pytest --cov=src --cov-report=xml --cov-fail-under=80

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  # ===== Job 3: Security Scan =====
  security:
    name: 🔒 Security Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Bandit (Python security linter)
        run: |
          pip install bandit
          bandit -r src/ -f json -o bandit-report.json

  # ===== Job 4: Deploy (เฉพาะ push ไป main) =====
  deploy:
    name: 🚀 Deploy to Production
    runs-on: ubuntu-latest
    needs: [lint, test, security]
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to server
        run: |
          echo "Deploying version ${{ github.sha }}"
          # คำสั่ง deploy จริง

9.4 GPG Signing Commits

# ===== สร้าง GPG Key =====
gpg --full-generate-key
# เลือก: RSA and RSA (default), 4096 bits, 0 (ไม่หมดอายุ)
# กรอก Name, Email (ต้องตรงกับ git config)

# ดู Key ID
gpg --list-secret-keys --keyid-format=long
# sec   rsa4096/ABCDEF1234567890 2024-01-01 [SC]

# Export Public Key สำหรับ GitHub
gpg --armor --export ABCDEF1234567890

# ตั้งค่า Git ให้ใช้ GPG Key นี้
git config --global user.signingkey ABCDEF1234567890
git config --global commit.gpgsign true
git config --global tag.gpgsign true

# Sign commit ด้วยตนเอง
git commit -S -m "feat: signed commit"

# ตรวจสอบ signature
git log --show-signature -1

10. หัวข้อพิเศษสำหรับโปรเจกต์ขนาดใหญ่ (Advanced Topics for Large Projects)

10.1 git submodule vs git subtree

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart TD
    subgraph MAIN["📦 Main Repository (my-app)"]
        MC["src/ — Application Code"]
        SM["lib/utils → .gitmodules\n(pointer to commit SHA)"]
        ST["vendor/ui → copied code\n(embedded in repo)"]
    end

    subgraph SUB["🔗 Submodule"]
        SR["utils-repo\n(แยก Repo แยก URL)"]
    end

    subgraph TREE["🌲 Subtree"]
        TR["ui-library\n(merged history)"]
    end

    SM -->|"git submodule update"| SR
    ST -.->|"git subtree pull"| TR

    style MAIN fill:#282828,stroke:#fabd2f,color:#ebdbb2
    style SUB fill:#282828,stroke:#cc241d,color:#ebdbb2
    style TREE fill:#282828,stroke:#b8bb26,color:#ebdbb2

Submodule:

# ===== เพิ่ม Submodule =====
git submodule add git@github.com:team/utils.git lib/utils
git submodule add --branch stable git@github.com:team/ui.git lib/ui

# ===== Clone Repo ที่มี Submodule =====
git clone --recurse-submodules git@github.com:username/my-app.git
# หรือ (ถ้า clone ปกติแล้วลืม)
git submodule init
git submodule update

# ===== อัปเดต Submodule เป็นเวอร์ชันล่าสุด =====
git submodule update --remote lib/utils
git submodule update --remote --merge  # merge การเปลี่ยนแปลง

# ===== ดู Status ของ Submodules =====
git submodule status

Subtree:

# ===== เพิ่ม Subtree =====
git remote add ui-lib git@github.com:team/ui-library.git
git subtree add --prefix=vendor/ui ui-lib main --squash

# ===== ดึง Update จาก Upstream =====
git subtree pull --prefix=vendor/ui ui-lib main --squash

# ===== Push การเปลี่ยนแปลงกลับ Upstream =====
git subtree push --prefix=vendor/ui ui-lib feature/fix-button
เกณฑ์ Submodule Subtree
ประวัติ แยกจาก Main Repo รวมใน Main Repo
ความซับซ้อน สูง ต่ำกว่า
Clone ต้องใช้ --recurse-submodules ปกติ
Contributor ต้องรู้เรื่อง Submodule ไม่จำเป็น
Contribute กลับ ง่าย ยากกว่า
เหมาะกับ Dependency แยก Repo Vendor code

10.2 git lfs (Large File Storage)

# ===== ติดตั้ง Git LFS =====
# Ubuntu: sudo apt install git-lfs
# macOS:  brew install git-lfs
# Windows: winget install GitHub.GitLFS

git lfs install   # เปิดใช้งานใน Git

# ===== Track ไฟล์ขนาดใหญ่ =====
git lfs track "*.psd"        # Photoshop files
git lfs track "*.ai"         # Illustrator files
git lfs track "*.mp4"        # Video files
git lfs track "models/*.bin" # ML Model files
git lfs track "*.parquet"    # Data files

# การ track จะสร้าง .gitattributes
git add .gitattributes
git commit -m "chore: add LFS tracking for large files"

# ===== ดู LFS Status =====
git lfs status
git lfs ls-files   # ดูไฟล์ที่ track ด้วย LFS

# ===== ดู LFS Statistics =====
git lfs env

# ===== Migration: ย้ายไฟล์ที่มีอยู่เข้า LFS =====
git lfs migrate import --include="*.psd,*.ai" --everything

10.3 Shallow Clone และ Sparse Checkout

# ===== Shallow Clone: ดึงแค่ประวัติล่าสุด =====
git clone --depth=1 git@github.com:large-org/monorepo.git
git clone --depth=50 git@github.com:large-org/monorepo.git   # 50 commits

# Deepen ภายหลังถ้าต้องการ
git fetch --unshallow

# ===== Sparse Checkout: ดึงเฉพาะส่วนที่ต้องการ (Monorepo) =====
git clone --filter=blob:none --sparse git@github.com:large-org/monorepo.git
cd monorepo

# กำหนด Directory ที่ต้องการ
git sparse-checkout set apps/frontend packages/ui libs/auth

# ดู Sparse Checkout Config
git sparse-checkout list

# เพิ่ม Pattern
git sparse-checkout add packages/shared

# ยกเลิก Sparse Checkout (ดึงทุกอย่าง)
git sparse-checkout disable

10.4 การ Optimize Repository

# ===== git gc (Garbage Collection) =====
# Git รัน gc อัตโนมัติ แต่สามารถรันเองได้

git gc                    # Garbage collection ปกติ
git gc --aggressive       # Aggressive (ช้าแต่ compress ดีกว่า)
git gc --prune=now        # ลบ unreachable objects ทันที

# ===== git prune =====
git prune                 # ลบ Objects ที่ไม่มีใครอ้างถึง
git prune --expire=now    # ลบทันที (ไม่รอ Grace period)

# ===== ดูขนาด Repository =====
git count-objects -vH
# count: 0
# size: 0 bytes
# in-pack: 1234
# packs: 1
# size-pack: 45.23 MiB

# ===== ค้นหาไฟล์ขนาดใหญ่ใน History =====
git rev-list --objects --all |
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
  awk '/^blob/ {print substr($0,6)}' |
  sort --numeric-sort --key=2 --reverse |
  head -20

# ===== ลบไฟล์ขนาดใหญ่ออกจาก History (BFG) =====
# ใช้ BFG Repo-Cleaner (เร็วกว่า git filter-branch)
java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive

11. บทสรุปและแหล่งเรียนรู้ (Conclusion & Further Resources)

11.1 Cheat Sheet: คำสั่งจัดกลุ่มตามบริบท

11.1.1 Setup & Config

git config --global user.name "Name"
git config --global user.email "email@example.com"
git config --global init.defaultBranch main
git config --global alias.lg "log --oneline --graph --all"
git init                    # สร้าง Local Repo
git clone <url>             # Clone Remote Repo

11.1.2 Daily Workflow

git status -sb              # ดูสถานะ
git add .                   # Stage ทุกอย่าง
git add -p                  # Stage แบบ Interactive
git commit -m "type: msg"   # Commit
git commit --amend          # แก้ Commit ล่าสุด
git push                    # Push ขึ้น Remote
git pull --rebase           # Pull + Rebase

11.1.3 Branch Management

git switch -c feature/x     # สร้าง + Switch branch
git switch main             # Switch branch
git branch -d feature/x    # ลบ branch (after merge)
git merge --no-ff feature/x # Merge พร้อม Merge commit
git rebase main             # Rebase บน main
git rebase -i HEAD~5        # Interactive rebase

11.1.4 Investigation

git log --oneline --graph --all   # ดู History แบบ Graph
git diff HEAD                     # ทุกการเปลี่ยนแปลง
git diff --staged                 # สิ่งที่จะ Commit
git blame README.md               # ดูว่าใครแก้บรรทัดไหน
git bisect start                  # เริ่มค้นหา Bug
git reflog                        # ดูทุกการเคลื่อนไหว

11.1.5 Undo & Recovery

git restore <file>          # ยกเลิกแก้ไขใน Working Dir
git restore --staged <file> # เอาออกจาก Staging
git reset --soft HEAD~1     # Undo commit (เก็บไฟล์)
git reset --hard HEAD~1     # Undo commit (ลบไฟล์) ⚠️
git revert HEAD             # สร้าง Revert commit
git stash push -m "WIP"     # พักงานชั่วคราว
git stash pop               # ดึงงานที่พักกลับมา

11.2 Best Practices

11.2.1 Atomic Commits (Commit เดี่ยว)

หลักการ: แต่ละ Commit ควรทำสิ่งเดียวที่สมบูรณ์ในตัวเอง

❌ ไม่ดี:
- "fix lots of bugs and add new features and update docs"

✅ ดี:
- "fix(auth): resolve JWT expiry race condition"
- "feat(user): add profile picture upload"
- "docs: update API authentication guide"

11.2.2 Branch Naming Convention

feature/<issue-id>-<short-description>
fix/<issue-id>-<short-description>
hotfix/<version>-<short-description>
release/<version>
chore/<short-description>
docs/<short-description>

ตัวอย่าง:
feature/142-user-profile-picture
fix/201-null-pointer-in-auth
hotfix/1.2.1-security-patch
release/2.0.0

11.2.3 .gitignore Checklist

✅ ไฟล์ที่ต้องอยู่ใน .gitignore เสมอ:
- Secrets (.env, *.pem, *.key, credentials.json)
- Dependencies (node_modules/, venv/, vendor/)
- Build outputs (dist/, build/, *.pyc)
- IDE settings (.idea/, .vscode/ สำหรับ team projects)
- OS files (.DS_Store, Thumbs.db)
- Log files (*.log, logs/)
- Local config (*.local, *.override)

11.3 GUI Clients เปรียบเทียบ

Client Platform ฟรี/จ่าย เหมาะกับ
GitKraken Win/Mac/Linux Freemium Team collaboration
Fork Win/Mac จ่าย Power users
Sourcetree Win/Mac ฟรี Beginners
Tower Win/Mac จ่าย Professional
GitHub Desktop Win/Mac ฟรี GitHub users
VS Code (built-in) All ฟรี Developers
IntelliJ/PyCharm All Freemium JetBrains users
Lazygit All ฟรี Terminal enthusiasts

11.4 Timeline: วิวัฒนาการ Git

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#504945', 'lineColor': '#a89984', 'background': '#282828', 'mainBkg': '#3c3836', 'fontFamily': 'monospace'}}}%%
flowchart TB
    subgraph E1["📅 1972–2000: Before Git"]
        T1["1972 — SCCS\nBell Labs"]
        T2["1982 — RCS\nWalter Tichy"]
        T3["1986 — CVS\nConcurrent Versions System"]
        T4["2000 — SVN\nApache Subversion\n(ใช้กันแพร่หลาย)"]
        T1 --> T2 --> T3 --> T4
    end

    subgraph E2["📅 2005: The Birth of Git"]
        T5["เมษายน 2005\nLinus Torvalds สร้าง Git\n(ในสัปดาห์เดียว!)"]
        T6["มิถุนายน 2005\nLinux Kernel ย้ายมาใช้ Git"]
        T7["ธันวาคม 2005\nGit v1.0 Release"]
        T5 --> T6 --> T7
    end

    subgraph E3["📅 2008–2015: Ecosystem Growth"]
        T8["2008 — GitHub เปิดตัว"]
        T9["2011 — GitLab เปิดตัว"]
        T10["2012 — Bitbucket รองรับ Git"]
        T11["2013 — GitHub ยอดผู้ใช้ 3M"]
        T8 --> T9 --> T10 --> T11
    end

    subgraph E4["📅 2018–ปัจจุบัน: Enterprise & Scale"]
        T12["2018 — Microsoft ซื้อ GitHub\n($7.5B)"]
        T13["2020 — Default branch\nเปลี่ยนเป็น 'main'"]
        T14["2022 — Git v2.39\nSparse Checkout ปรับปรุง"]
        T15["2024 — Git 100M+ Users"]
        T12 --> T13 --> T14 --> T15
    end

    E1 --> E2 --> E3 --> E4

    style E1 fill:#3c3836,stroke:#a89984,color:#ebdbb2
    style E2 fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
    style E3 fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style E4 fill:#3c3836,stroke:#b8bb26,color:#ebdbb2

11.5 แหล่งเรียนรู้แนะนำ

📚 หนังสือ:

🌐 Interactive Learning:

📖 Reference:

🛠️ เครื่องมือเพิ่มเติม: