Git là gì?
Xem thửVấn đề cần giải quyết
Bạn đang ngồi trên máy bay, không có Wi-Fi, và vừa sửa xong hai lỗi. Với nhiều công cụ cũ, bạn phải đợi có mạng mới lưu được lịch sử. Với Git, bạn commit ngay trên máy bay. Điều gì khiến Git làm được như vậy, và khi nào mạng mới thực sự cần?
Sau bài này, bạn có thể
- Giải thích Git là hệ thống quản lý phiên bản phân tán và hệ quả của việc đó.
- Phân biệt thao tác chạy cục bộ với thao tác cần kết nối.
- Mô tả cách Git lưu snapshot thay vì lưu phần khác biệt.
Tiên quyết: bài Version control là gì và SCM.
Git là gì
Git là hệ thống quản lý phiên bản phân tán (DVCS) phổ biến nhất hiện nay, do Linus Torvalds, tác giả của nhân Linux, tạo ra năm 2005. Git là mã nguồn mở và vẫn được phát triển tích cực.
Khác với CVS hay Subversion chỉ có một nơi giữ lịch sử, với Git mỗi bản sao làm việc cũng là một kho đầy đủ, chứa toàn bộ lịch sử thay đổi.
Thử và quan sát: cục bộ và qua mạng
Hãy dự đoán: bạn commit hai lần khi không có mạng. Các commit có thành công không, và kho từ xa có thấy chúng không? Bấm Bước tiếp để kiểm chứng, rồi dùng nút biến thể để xem điều gì xảy ra khi push lúc mất mạng.
Đang tải Animation…
Bảng bước (bản đọc tĩnh của mô phỏng)
| Bước | Lệnh | Điều xảy ra |
|---|---|---|
| 1 | git commit -m "Sửa lỗi đăng nhập" | Commit ghi vào kho cục bộ nên không cần mạng. Kho từ xa chưa biết gì. |
| 2 | git commit -m "Thêm test cho đăng nhập" | Commit thứ hai cũng thành công. Kho cục bộ đi trước kho từ xa hai commit. |
| 3 | git log --oneline | Xem lịch sử cũng chạy cục bộ, đọc thẳng từ kho trên máy. |
| 4 | git push origin main | Có mạng trở lại. Push gửi hai commit lên kho từ xa; origin/main và main từ xa cùng tiến tới C4. |
Biến thể: Push khi mất mạng
| Bước | Lệnh | Điều xảy ra |
|---|---|---|
| 1 | git commit -m "Sửa lỗi đăng nhập" | Commit cục bộ vẫn thành công dù không có mạng. |
| 2 | git commit -m "Thêm test cho đăng nhập" | Lịch sử cục bộ tiếp tục dài ra. |
| 3 | git push origin main | Push cần kết nối nên thất bại. Không commit nào bị mất: chúng vẫn nằm an toàn trong kho cục bộ. |
| 4 | git status | Git cho biết nhánh của bạn đang đi trước origin/main hai commit, đợi lần push thành công. |
Giải đáp. Commit, log, branch chỉ làm việc với kho trên máy bạn nên không cần mạng. Kho từ xa chỉ thấy các commit sau khi bạn push. Nhãn origin/main nằm trong kho cục bộ và phản ánh lần gần nhất bạn đồng bộ, nên khi push thất bại nó đứng yên và Git báo nhánh của bạn đi trước hai commit.
Ba trụ cột thiết kế của Git
1. Hiệu năng. Commit, tạo nhánh, merge, so sánh đều nhanh. Git quan tâm tới nội dung tệp hơn tên tệp, dùng nén và delta encoding để lưu hiệu quả. Vì phân tán nên hầu hết thao tác diễn ra cục bộ.
2. Bảo mật. Mọi đối tượng trong kho (nội dung tệp, thư mục, commit, tag) được bảo vệ bằng hàm băm mật mã: SHA-1, và đang chuyển dần sang SHA-256. Nhờ vậy lịch sử không thể bị sửa âm thầm mà không bị phát hiện.
3. Linh hoạt. Git hỗ trợ nhiều luồng làm việc phi tuyến, hiệu quả cho cả dự án nhỏ và lớn, và tương thích nhiều giao thức, công cụ.
Git lưu ảnh chụp, không lưu phần khác biệt
Nhiều hệ thống cũ lưu bản gốc cộng các thay đổi. Git nghĩ về dữ liệu như một chuỗi snapshot của toàn bộ dự án. Mỗi lần commit, Git ghi lại trạng thái các tệp và một tham chiếu tới snapshot đó. Tệp nào không đổi, Git chỉ trỏ tới bản đã lưu.
Cách đọc hình. Hàng trên là cách lưu khác biệt: để dựng bản 4 phải áp dụng lần lượt ba thay đổi lên bản gốc. Hàng dưới là cách của Git: snapshot 2 nhìn như đầy đủ dự án, nhưng chỉ a.txt có nội dung mới; b.txt và c.txt là liên kết tới bản đã lưu ở snapshot 1, nên không tốn gấp đôi dung lượng.
Dễ nhầm: commit không phải một bản vá. Dù có thể xem phần khác biệt giữa hai commit bằng git diff, thứ được lưu thật sự là snapshot.
Bạn có thể xem chuỗi snapshot dưới dạng đồ thị:
git log --oneline --graph
Hiểu lầm thường gặp
- "Git cần mạng để hoạt động." Chỉ push, fetch và pull cần mạng. Mọi thao tác ghi và đọc lịch sử đều cục bộ.
- "Git lưu các thay đổi giữa hai bản." Git lưu snapshot; việc tính khác biệt xảy ra khi bạn so sánh.
- "Hash chỉ là mã số ngẫu nhiên." Hash được tính từ nội dung, nên đổi nội dung là đổi hash. Đó là cơ sở để phát hiện lịch sử bị sửa.
Tự kiểm tra
- Lệnh nào trong chuỗi
commit,log,push,branchcần mạng? - Giải thích vì sao snapshot 2 trong hình không tốn gấp đôi dung lượng.
- Nếu push thất bại vì mất mạng, commit của bạn còn không? Dấu hiệu nào cho biết điều đó?
Đáp án gợi ý. (1) Chỉ push. (2) Các tệp không đổi chỉ là liên kết tới bản đã lưu. (3) Còn, vì commit nằm trong kho cục bộ; git status báo nhánh đi trước origin/main.
Điều cần nhớ
- Git là phân tán: mỗi bản clone là một kho đầy đủ.
- Ghi lịch sử là việc cục bộ, chia sẻ lịch sử mới cần mạng.
- Git lưu snapshot và dùng lại các tệp không đổi.
- Hash bảo vệ tính toàn vẹn của lịch sử.
- Bài sau: vì sao cả tổ chức nên chọn Git.
Nguồn tham khảo
Pro Git, chương 1.3 "What is Git?" (git-scm.com/book).