11 · Git Labs
13 bài thực hành theo cấp độ. Các lab ưu tiên local-first để bạn có thể luyện Git thật sự thay vì chỉ đọc lý thuyết.
mkdir -p ~/git-labs && cd ~/git-labs.Init → Add → Commit
Mục tiêu: Hiểu ba vùng Working Tree / Index / HEAD.
rm -rf lab01 && mkdir lab01 && cd lab01
git init -b main
printf "# Git Lab
" > README.md
git status
git diff
git add README.md
git diff --staged
git commit -m "docs: add README"
git log --onelineKiểm tra kết quả
git status
# expected: working tree clean.gitignore và tracked file
Mục tiêu: Phân biệt ignore với untrack.
cd ~/git-labs
rm -rf lab02 && mkdir lab02 && cd lab02
git init -b main
printf "SECRET=demo
" > .env
git add .env && git commit -m "chore: accidentally track env"
printf ".env
" > .gitignore
git status
# .env vẫn tracked!
git rm --cached .env
git add .gitignore
git commit -m "chore: stop tracking env"Kiểm tra kết quả
git status --ignored
# .env phải hiện ignored, không trackedBranch + Fast-forward + Merge commit
Mục tiêu: Nhìn commit graph và phân biệt hai kiểu merge.
cd ~/git-labs
rm -rf lab03 && mkdir lab03 && cd lab03
git init -b main
echo base > app.txt
git add . && git commit -m "init"
git switch -c feature/a
echo feature-a >> app.txt
git commit -am "feat: A"
git switch main
git merge feature/a
git switch -c feature/b
echo feature-b > b.txt
git add . && git commit -m "feat: B"
git switch main
echo main-change > main.txt
git add . && git commit -m "chore: main change"
git merge --no-ff feature/b -m "merge feature/b"
git log --oneline --graph --decorate --allKiểm tra kết quả
git log --graph --oneline --all
# tìm một fast-forward và một merge commitTạo và resolve merge conflict
Mục tiêu: Tự tay tạo conflict, đọc markers và resolve.
cd ~/git-labs
rm -rf lab04 && mkdir lab04 && cd lab04
git init -b main
echo "MODE=base" > config.env
git add . && git commit -m "init config"
git switch -c feature/config
echo "MODE=staging" > config.env
git commit -am "feat: staging mode"
git switch main
echo "MODE=production" > config.env
git commit -am "chore: production mode"
git merge feature/config
# conflict expected
cat config.env
# sửa file thành giá trị bạn quyết định
echo "MODE=production" > config.env
git add config.env
git commit -m "merge: resolve config mode"Kiểm tra kết quả
git status
git log --graph --oneline --allCollaboration local: bare remote + 2 developer
Mục tiêu: Luyện fetch, push rejection và integrate mà không cần GitHub.
cd ~/git-labs
rm -rf lab05 && mkdir lab05 && cd lab05
git init --bare central.git
git clone central.git developer-a
git clone central.git developer-b
cd developer-a
git switch -c main
echo "A init" > shared.txt
git add . && git commit -m "init by A"
git push -u origin main
cd ../developer-b
git fetch origin
git switch -c main --track origin/main
echo "B change" >> shared.txt
git commit -am "feat: change by B"
git push
cd ../developer-a
echo "A second" >> shared.txt
git commit -am "feat: second change by A"
git push
# expected rejection because B pushed first
git fetch origin
git log --oneline --graph --decorate --all
# integrate theo cách bạn chọn:
git rebase origin/main
# resolve nếu có conflict
git pushKiểm tra kết quả
git log --oneline --graph --decorate --all
# local main và origin/main phải cùng tip sau pushStash WIP
Mục tiêu: Tạm cất thay đổi tracked + untracked và phục hồi.
cd ~/git-labs
rm -rf lab06 && mkdir lab06 && cd lab06
git init -b main
echo base > app.txt
git add . && git commit -m init
echo wip >> app.txt
echo new > temp.txt
git stash push -u -m "WIP demo"
git status
git stash list
git stash show -p stash@{0}
git stash popKiểm tra kết quả
git status
# app.txt modified + temp.txt untracked phải quay lạiReset soft/mixed/hard vs Revert
Mục tiêu: Quan sát chính xác mỗi mode tác động lên HEAD/Index/Working Tree.
cd ~/git-labs
rm -rf lab07 && mkdir lab07 && cd lab07
git init -b main
echo 1 > number.txt
git add . && git commit -m one
echo 2 > number.txt
git commit -am two
git reset --soft HEAD~1
git status
# commit lại
git commit -m two
git reset HEAD~1
git status
git add . && git commit -m two
# tạo commit 3 rồi revert
echo 3 > number.txt
git commit -am three
git revert HEAD --no-edit
git log --onelineKiểm tra kết quả
cat number.txt
git log --oneline
# commit "three" vẫn tồn tại, sau nó có revert commitRecovery bằng reflog
Mục tiêu: Cố tình reset --hard rồi khôi phục commit.
cd ~/git-labs
rm -rf lab08 && mkdir lab08 && cd lab08
git init -b main
for n in 1 2 3; do echo $n > value.txt; git add .; git commit -m "value $n"; done
git log --oneline
git reset --hard HEAD~2
git log --oneline
git reflog
# lấy SHA của commit value 3 rồi:
git switch -c recovery <SHA_VALUE_3>Kiểm tra kết quả
cat value.txt
# expected: 3
git log --oneline --all --graph<SHA_VALUE_3> bằng SHA thật từ reflog.Interactive rebase: squash/fixup/reword
Mục tiêu: Làm sạch history feature branch.
cd ~/git-labs
rm -rf lab09 && mkdir lab09 && cd lab09
git init -b main
echo base > app.txt; git add .; git commit -m init
echo feature >> app.txt; git commit -am "feat: add feature"
echo typo >> app.txt; git commit -am "fix typo"
echo debug >> app.txt; git commit -am "debug temporary"
git log --oneline
# chạy editor interactive:
git rebase -i HEAD~3
# thử: pick commit feat, fixup typo, reword debug (hoặc drop nếu muốn)
git log --onelineKiểm tra kết quả
git log --oneline
# history mới phải phản ánh action bạn đã chọnCherry-pick hotfix
Mục tiêu: Lấy một commit độc lập sang release branch.
cd ~/git-labs
rm -rf lab10 && mkdir lab10 && cd lab10
git init -b main
echo base > app.txt; git add .; git commit -m init
git branch release
git switch -c hotfix
echo fix >> app.txt
git commit -am "fix: urgent patch"
FIX_SHA=$(git rev-parse HEAD)
git switch release
git cherry-pick "$FIX_SHA"
git log --oneline --all --graphKiểm tra kết quả
cat app.txt
# release phải chứa fixBisect tìm commit gây bug
Mục tiêu: Dùng binary search thay vì check từng commit.
cd ~/git-labs
rm -rf lab11 && mkdir lab11 && cd lab11
git init -b main
for n in 1 2 3 4 5 6 7 8; do echo $n > value.txt; git add .; git commit -m "value $n"; done
# giả sử value >= 6 là bad
git bisect start
git bisect bad HEAD
git bisect good HEAD~7
# tại mỗi commit Git chọn:
cat value.txt
# nếu value >= 6: git bisect bad; ngược lại git bisect good
# lặp tới khi tìm first bad
git bisect resetKiểm tra kết quả
git status
# quay lại branch ban đầu sau resetWorktree: feature + hotfix song song
Mục tiêu: Làm nhiều branch đồng thời không stash/switch liên tục.
cd ~/git-labs
rm -rf lab12-main lab12-hotfix
mkdir lab12-main && cd lab12-main
git init -b main
echo base > app.txt; git add .; git commit -m init
git worktree add ../lab12-hotfix -b hotfix main
git worktree list
cd ../lab12-hotfix
echo fix >> app.txt
git commit -am "fix: from worktree"
cd ../lab12-main
git log --oneline --all --graph
git worktree remove ../lab12-hotfixKiểm tra kết quả
git worktree list
# linked hotfix worktree đã được removeInspect Git objects
Mục tiêu: Nhìn trực tiếp commit/tree/blob objects.
cd ~/git-labs/lab01
git cat-file -t HEAD
git cat-file -p HEAD
git cat-file -p HEAD^{tree}
git ls-tree -r HEAD
git rev-parse HEAD
git rev-parse --show-toplevelKiểm tra kết quả
# xác định object type của HEAD, tree và blob README.md