Máy thời gian cho code của bạn: mọi thay đổi đều được lưu, nên bạn có thể quay lại, làm việc song song và cùng ship với mọi người.
← / → để chuyển slide · chuyển EN/VI bên dưới
Không có kiểm soát phiên bản, code của bạn nằm trên một ổ đĩa, file nọ file kia. Sửa gì đó rồi cầu nguyện.
index.html, index_v2.html, index_final.html, index_final_REAL.html — lúc 2 giờ sáng bạn chẳng biết file nào là thật.
Ghi đè, máy sập, một lần AI sửa nhầm — và không có 'undo' cho cả một dự án.
Code hồi thứ Ba tuần trước trông thế nào? Vì sao nó hỏng sau lần sửa đó? Không cách nào biết được.
Hai người sửa cùng một file trên một laptop? Chúc may mắn khi phải quyết ai thắng.
Một ý tưởng: git giữ toàn bộ lịch sử dự án trên máy bạn — và có thể đồng bộ lịch sử đó với một bản sao trên internet (GitHub).
Mỗi lệnh git đều di chuyển thứ gì đó giữa bốn căn phòng: working tree → staging area → commits → con trỏ branch.
Đó là toàn bộ bảng từ vựng. Phần còn lại đều là chi tiết.
Các file thật trên ổ đĩa, do bạn và AI sửa. 'Hiện tại', nhưng chưa được lưu vào lịch sử.
Danh sách chính xác thay đổi nào sẽ vào commit kế tiếp. Bạn chọn; git không đoán.
Mỗi commit = một tấm ảnh chụp cả dự án + một dòng ghi chú. Các tấm ảnh xếp chồng thành lịch sử.
Không phải bản sao code — chỉ là con trỏ nói 'bản chụp mới nhất tính tới đây = cái này'.
Một sơ đồ cần nhớ: bạn sửa ở working tree, chọn thay đổi vào staging, và commit biến khay thành tấm ảnh mới.
Một mã ngắn, một dòng ghi chú, và một tấm ảnh chụp được đóng băng của dự án. git log cho bạn xem album.
git log --oneline
a1b2c3d fix: handle empty search results
d4e5f6a feat: add user profile page
0f9e8d7 first commit
Mới nhất ở trên cùng. Mỗi dòng = một tấm ảnh bạn luôn có thể quay lại.
Cả hai câu trả lời cùng một từ: kiểm soát. Bạn quyết định chính xác cái gì được lưu, và khi nào.
Bạn có thể chọn 1 trong 5 file đã sửa. Commit chứa đúng những gì bạn bỏ vào khay — không thừa, không thiếu.
Cách dùng kinh điển: chọn file sửa code, nhưng không chọn file .env chứa bí mật của bạn.
Commit là điểm lưu mà bạn tạo ra có chủ đích. Không auto-save, không sự cố — lịch sử là chuỗi những quyết định.
Commit nhỏ và thường xuyên = lịch sử hoàn tác chi tiết.
90% một ngày dùng git là vòng lặp ba lệnh này. Học nó đến thành phản xạ.
Kiểm tra, chọn, lưu. Lặp lại.
Liệt kê file đã sửa và file mới: 'bạn đã sửa X, và Y là file mới'. Lệnh đầu tiên gõ mỗi khi bạn không chắc.
git add app.py bỏ trạng thái hiện tại của file đó vào staging. git add . = mọi thứ đã đổi.
git commit -m "lời nhắn" biến khay thành tấm ảnh mới trong lịch sử. Lời nhắn là viết cho bạn ở tương lai.
Nó cho bạn biết chính xác bạn đang ở đâu: gì đã sửa, gì đã chọn, gì hoàn toàn mới.
Hai lệnh và một tấm ảnh đã tồn tại. Dòng ghi chú là phần duy nhất bạn tự viết.
Commit nhỏ, commit thường xuyên. Commit là điểm lưu, không phải tượng đài.
Bạn sẽ đọc những dòng này sau vài tháng — hoặc một đồng đội. Hãy viết cho người đọc đó.
Sửa lỗi đăng nhập = một commit. Icon mới = commit khác. Trộn vào nhau là không thể hoàn tác được.
"fix: xử lý form rỗng" — không phải "mình đã sửa cái gì đó với form hay là". Như tiêu đề, không phải nhật ký.
Diff đã cho thấy CÁI GÌ đổi. Dòng ghi chú là để giải thích VÌ SAO — 'vì API giờ trả về null'.
Nhờ AI soạn dòng ghi chú từ thay đổi của bạn — nhưng chỉ giữ đúng một dòng bạn sẵn sàng bảo vệ.
Lịch sử mới là mấu chốt. git có thể cho bạn xem bất kỳ trạng thái quá khứ nào — và đưa bạn quay về đó.
log = danh sách, diff = so sánh, show = xem kỹ một tấm ảnh.
| Lệnh | Nó trả lời | Khi nào dùng |
|---|---|---|
| git log | Chuyện gì đã xảy ra, theo thứ tự nào? | Luôn luôn — bản đồ lịch sử của bạn |
| git diff | Cái gì đổi, từng dòng một? | Trước khi commit, hay 'mình có hỏng gì không?' |
| git show a1b2c3d | Commit ĐÓ cụ thể đã đổi gì? | Khi một commit gây ra vấn đề |
--oneline = mỗi commit một dòng. Thói quen: liếc bản đồ trước khi sửa bất cứ thứ gì.
Dòng bắt đầu bằng + là thêm, dòng có - là bỏ. Cách nhanh nhất để trả lời 'mình có hỏng gì không?'.
git diff
--- a/app.py
+++ b/app.py
-price = 100
+price = 99 # black friday!
Diff là sự thật: đúng những gì sẽ vào commit kế tiếp.
Tự hỏi: mình muốn quay lại xa tới đâu? Working tree → staging → lịch sử. Mỗi cấp một lệnh hoàn tác.
'Mình phá hỏng file này, trả lại bản đã commit gần nhất.' git restore app.py. Các commit không hề hấn gì.
'Mình chọn nhầm file vào khay.' Lấy nó ra khỏi khay. File trên ổ đĩa không đổi.
'Commit đó sai rồi.' Đưa con trỏ branch lùi một bước. Công việc vẫn cứu được — đừng hoảng.
Cứu nguy phổ biến nhất: một file bị sửa hỏng (thường do AI), phần còn lại ổn.
Branch là con trỏ, không phải bản sao. Đó là lý do tạo branch tức thì, còn chuyển branch thì miễn phí.
Branch 'main' trỏ tới tấm ảnh mới nhất. Mỗi commit mới, con trỏ lại trượt lên trước. Chỉ vậy thôi.
Tạo branch không sao chép gì cả — chỉ ghim một cái tên vào một commit. Mili-giây, chi phí bằng không.
Commit trên 'main' thì 'main' trượt tới tấm ảnh mới. Lịch sử là một chuỗi; branch là nhãn gắn ở cuối chuỗi.
Mười branch có thể trỏ cùng một commit — hoặc khác nhau. Chúng chia sẻ lịch sử như cây gia phả.
Dù bạn không bao giờ tạo branch, 'main' (hay 'master') vẫn tồn tại. Commit của bạn đi tới nơi con trỏ đang đứng.
Bạn tách ra từ C2, thêm C3 trên branch feature, rồi merge về — main hấp thụ công việc của bạn.
Bốn lệnh: cắt branch, làm việc, về lại main, merge. Đó là toàn bộ vũ điệu.
Branch là cách làm việc song song không còn là cuộc chiến.
Đang refactor dở dang? Sang một branch. 'main' vẫn ổn định cho mọi người khác.
Thử ý tưởng rủi ro trên branch. Thất bại? Xóa branch — lịch sử nguyên vẹn.
Quy ước của team: đặt tên theo tính năng (feature/login, fix/broken-nav). Xong, merge, hết.
Mười người, mười branch, không còn 'ai ghi đè file của mình?'. GitHub biến mỗi branch thành Pull Request để review.
Dự án thật sống trên một repo từ xa — thường là GitHub. Laptop của bạn chỉ là một trong nhiều bản sao.
Mỗi lần clone, git đặt tên remote mặc định là 'origin' — repo mà bạn lấy về.
Nhanh, riêng tư, offline. Bạn commit ở đây thoải mái — không ai để ý cả.
Bản trên GitHub mà đồng đội, server và lần triển khai cùng thống nhất.
git push origin main = 'gửi branch main của tôi tới repo tôi đặt tên là origin'. Bạn có thể có nhiều remote.
Bạn commit ở local, đồng đội push lên remote — hai bản lệch nhau. Đồng bộ là thói quen hằng ngày, không phải sự kiện lớn.
clone = 'lấy một bản sao, nối với origin'. Sau đó, vòng lặp chỉ là pull vào, push ra.
Hai chiều: phía pull (nhận) và phía push (gửi). fetch là cái lặng lẽ; pull = fetch + áp dụng.
| Lệnh | Nó làm gì | Nói dễ hiểu |
|---|---|---|
| git clone <url> | Tải toàn bộ repo (code + lịch sử) và ghi nhớ nguồn của nó | Đầu mọi dự án: 'đưa tôi một bản sao' |
| git fetch | Tải commit mới từ origin — không đổi gì trên máy bạn | 'Cho tôi xem bên kia có gì mới' |
| git pull | fetch + merge vào branch hiện tại | 'Mang đồ mới vào code của tôi' |
| git push | Tải commit của bạn lên origin | 'Công bố việc của tôi — ai cũng thấy' |
.gitignore liệt kê các mẫu bỏ qua. git status thậm chí không nhắc tới các file này — chúng ở lại local.
# secrets — never, ever commit these
.env
*.db
# generated stuff — easy to rebuild
__pycache__/
node_modules/
*.log
dist/
Quy tắc: nếu nó tạo lại được, hoặc là bí mật — hãy ignore.
Một khi bí mật vào lịch sử, nó thành công khai — lịch sử không quên, và kẻ tấn công cũng vậy.
API key, mật khẩu, token. File .env là nguồn rò rỉ số 1. Ai cũng có thể đọc lịch sử repo của bạn.
Database có dữ liệu người dùng thật, về bản chất là riêng tư. Commit bản mẫu hoặc schema, không phải dữ liệu.
Cache bytecode của Python. Nó tự tạo lại; trong git nó chỉ là rác.
Vài trăm MB thư viện đã cài. npm install tự dựng lại từ package.json.
Mọi dự án thật đều sống trong git. Repo là nguồn sự thật duy nhất, mọi thứ khác đều dựng từ đó.
Nhớ những lệnh này là bạn làm việc được với mọi dự án. Phần còn lại, AI và tài liệu lo.
| Lệnh | Việc |
|---|---|
| git status | Tôi ở đâu? Gì đã đổi? |
| git add / git commit | Chọn và lưu một tấm ảnh |
| git log / git diff / git show | Đọc lịch sử |
| git restore | Hoàn tác một file (hoặc một lần chọn) |
| git switch (-c) / git branch | Chuyển giữa các dòng công việc song song |
| git merge | Gộp branch về main |
| git clone / git pull / git push | Lấy bản sao, giữ mới, công bố việc |
Git là máy thời gian có nút chia sẻ.
Mọi dự án bạn chạm tới trong khóa học này đều sống trong git. status → add → commit → push. Đó là toàn bộ vòng lặp của một shipper.