Git là gì? Git là một hệ thống quản lý phiên bản phân tán (Distributed Version Control System - DVCS) được thiết kế để theo dõi lịch sử thay đổi của mã nguồn. Khi bạn làm việc với Git, mọi chỉnh sửa đối với tệp tin đều được ghi lại, cho phép bạn khôi phục hoặc quay lại bất kỳ phiên bản nào của dự án tại một thời điểm cụ thể.
Khác với các hệ thống cũ, Git là một hệ thống phân tán hoàn toàn. Điều này nghĩa là mọi lập trình viên khi sao chép (clone) mã nguồn đều sở hữu một bản sao đầy đủ của toàn bộ kho lưu trữ, bao gồm cả lịch sử thay đổi và các nhánh. Bạn không cần kết nối mạng thường xuyên để thực hiện các thao tác quản lý phiên bản cơ bản.
Git cung cấp cho bạn cái nhìn minh bạch về lịch sử dự án: thay đổi nào đã thực hiện, ai là người thực hiện và lý do tại sao. Khi nhiều người cùng đóng góp vào một cơ sở mã duy nhất, Git là công cụ thiết yếu để giữ cho mã nguồn toàn vẹn.

Git là gì?
Về mặt kỹ thuật, Git là một hệ thống quản lý phiên bản phân tán (DVCS). Khác với các hệ thống lưu trữ theo tệp thông thường, Git tự động tính mã kiểm tra cho mọi dữ liệu trước khi lưu. Cơ chế này dùng mã băm SHA-1, một chuỗi gồm 40 ký tự thập lục phân (hexadecimal), được tính dựa trên cả nội dung tệp tin và cấu trúc thư mục (trees). Nhờ đó bạn không thể thay đổi bất kỳ nội dung nào mà Git không biết, và việc thất thoát hay hỏng hóc dữ liệu trong quá trình truyền tải bị phát hiện ngay.
Một đặc điểm quan trọng khác của Git là tính cục bộ. Hầu hết các thao tác chỉ cần tệp tin và tài nguyên trên máy tính của bạn, không cần kết nối mạng hay truy cập máy chủ trung tâm. Khi bạn duyệt lịch sử dự án hoặc so sánh các phiên bản, Git đọc dữ liệu trực tiếp từ cơ sở dữ liệu cục bộ trên ổ cứng. Chính cơ chế này giúp Git chạy rất nhanh: nó loại bỏ rào cản mạng vốn có của các hệ thống quản lý phiên bản thế hệ trước.
Thay vì xem Git như một công cụ quản lý phiên bản truyền thống, hãy hiểu nó là một hệ thống tệp nhỏ với các công cụ mạnh mẽ xây dựng bên trên. Git lưu mọi thứ trong cơ sở dữ liệu của nó dựa trên giá trị băm nội dung thay vì tên tệp. Cách tiếp cận này biến mỗi bản sao trên máy lập trình viên thành một máy chủ dự phòng đầy đủ, chứa toàn bộ metadata và lịch sử của dự án.
Trước khi có Git, lập trình viên quản lý code thế nào?
Ban đầu, phương pháp phổ biến nhất là quản lý phiên bản cục bộ (Local VCS). Cách làm thủ công thường thấy là sao chép các tệp tin vào một thư mục khác, đôi khi đính kèm nhãn thời gian. Cách này rất dễ gây nhầm lẫn. Để giải quyết, các hệ thống như RCS (Revision Control System) đã ra đời, hoạt động bằng cách lưu các bộ bản vá (patch sets) — tức phần khác biệt giữa các phiên bản tệp — trong một định dạng đặc biệt trên đĩa để tái tạo nội dung tệp tại bất kỳ thời điểm nào.

Khi nhu cầu cộng tác tăng lên, hệ thống quản lý phiên bản tập trung (Centralized Version Control System - CVCS) xuất hiện. Các hệ thống như CVS, Subversion (SVN) và Perforce dùng một máy chủ trung tâm duy nhất chứa toàn bộ tệp tin. Các máy khách sẽ "check out" tệp tin từ máy chủ này để làm việc. Mô hình này giúp quản trị viên kiểm soát quyền truy cập chi tiết và mọi người đều biết đồng nghiệp đang làm gì.
Nhưng mô hình CVCS tồn tại rủi ro tập trung (single point of failure). Nếu máy chủ trung tâm gặp sự cố hoặc ổ cứng chứa cơ sở dữ liệu bị hỏng mà không có bản sao lưu đúng cách, bạn mất hoàn toàn lịch sử thay đổi của dự án. Khi đó, thứ duy nhất còn lại chỉ là những snapshot đơn lẻ mà các thành viên đang có trên máy cá nhân. Git loại bỏ rủi ro này bằng cách yêu cầu mỗi máy khách lưu một bản sao đầy đủ của toàn bộ kho lưu trữ.
Vì sao Git ra đời?
Sự hình thành của Git gắn liền với sự kiện cộng đồng phát triển nhân Linux mất quyền truy cập vào công cụ BitKeeper năm 2005. Trước đó, BitKeeper được dùng miễn phí cho các dự án mở, nhưng mâu thuẫn về giấy phép giữa Andrew Tridgell và Larry McVoy — người đứng sau BitKeeper — đã dẫn đến việc thu hồi quyền truy cập này. Cộng đồng Linux cần một hệ thống mới đủ mạnh cho quy mô của dự án nhưng phải đảm bảo tính mở và phân tán.
Linus Torvalds quyết định tự viết một hệ thống mới và phác thảo ý tưởng từ tháng 4 năm 2005. Mục tiêu của ông rất rõ: hiệu năng xử lý cao, hỗ trợ mô hình phân tán hoàn toàn và có cơ chế chống hỏng hóc dữ liệu. Ông hoàn thiện phiên bản đầu tiên chỉ trong khoảng 10 ngày, đủ để Git tự quản lý chính mã nguồn của mình.
Triết lý thiết kế của Linus tập trung vào tốc độ và sự đơn giản ở tầng lõi. Ông đặt ra yêu cầu cụ thể: áp dụng một loạt bản vá trong khoảng nửa phút, kể cả khi loạt đó có 50 đến 100 bản vá. Đây là bài toán mà các hệ thống tập trung như CVS hay SVN thời bấy giờ thường xuyên bế tắc về thời gian xử lý. Ông xây dựng Git bằng tư duy của một kỹ sư hệ thống tệp, ưu tiên tính ổn định và khả năng xử lý các tập dữ liệu lớn.
Git lưu dữ liệu theo snapshot, không phải theo diff
Khác biệt cốt lõi giữa Git và các hệ thống khác nằm ở cách tư duy về dữ liệu. Các hệ thống cũ thường lưu thông tin dưới dạng "delta", nghĩa là ghi lại tệp gốc và danh sách các thay đổi (diff) qua từng phiên bản. Ngược lại, Git coi dữ liệu là một chuỗi các snapshot (ảnh chụp). Mỗi khi bạn commit, Git chụp lại toàn bộ hệ thống tệp tại thời điểm đó và lưu tham chiếu đến ảnh chụp này.

Mô hình đối tượng của Git gồm ba thành phần chính:
- Blobs: Lưu nội dung của tệp tin.
- Trees: Lưu cấu trúc thư mục và liên kết tên tệp với các Blobs hoặc Trees con.
- Commits: Chứa thông tin về snapshot, trỏ tới một Root Tree và các commit cha để hình thành lịch sử.
Để tối ưu dung lượng, Git dùng cơ chế lưu trữ có chọn lọc. Nếu một tệp tin không thay đổi giữa hai lần commit, Git không sao chép lại tệp đó mà chỉ tạo một liên kết đến tệp cũ đã tồn tại. Nhờ vậy, chuyển đổi giữa các phiên bản diễn ra rất nhanh: Git chỉ cần xử lý các con trỏ và những tệp thay đổi thực sự.
Khi bạn yêu cầu xem thay đổi giữa hai phiên bản, Git tính toán diff một cách động từ các snapshot. Hệ thống duyệt theo chiều sâu (depth-first search) trên các cây con (subtrees) bằng cách so sánh mã băm của chúng. Nếu mã băm của một thư mục không đổi, Git bỏ qua toàn bộ nhánh đó và chỉ tập trung vào các nhánh có khác biệt. Đó là lý do việc tính diff vẫn hiệu quả ngay cả với dự án hàng triệu dòng mã.
Ba trạng thái của một tệp trong Git
Để dùng Git hiệu quả, bạn cần nắm vững ba trạng thái chính của một tệp tin:
- Modified (đã sửa đổi): Tệp đã thay đổi so với phiên bản hiện tại trong cơ sở dữ liệu nhưng chưa được đánh dấu để đưa vào lần lưu trữ tiếp theo.
- Staged (đã đưa vào vùng chờ): Bạn đã đánh dấu một tệp đã sửa đổi để đưa nó vào snapshot trong lần commit kế tiếp.
- Committed (đã commit): Dữ liệu đã được lưu an toàn vào cơ sở dữ liệu cục bộ.
Tương ứng với ba trạng thái này là ba khu vực quản lý:
- Working Tree: Bản sao của một phiên bản dự án được trích xuất từ cơ sở dữ liệu và đặt lên đĩa cứng để bạn sửa đổi.
- Staging Area (Index): Thực chất là một tệp nằm trong thư mục Git (
.git/index) chứa thông tin về những gì sẽ có trong lần commit tới. Nó đóng vai trò như bản nháp cho snapshot sắp tới. - Git Directory (
.git): Nơi lưu toàn bộ metadata và cơ sở dữ liệu đối tượng của dự án. Đây là phần được sao chép khi bạn chạy lệnh clone.

Quy trình làm việc chuẩn là bạn sửa tệp trong Working Tree, đưa các thay đổi vào Staging Area, sau đó commit để ghi snapshot vĩnh viễn vào Git Directory.
Vì sao nên dùng Git?
Lợi thế lớn nhất của Git là tốc độ xử lý. Vì hầu hết thao tác diễn ra cục bộ, bạn có thể xem lịch sử, so sánh phiên bản hoặc tạo nhánh mới gần như tức thì mà không phải chờ phản hồi từ máy chủ qua mạng. Khả năng làm việc ngoại tuyến cho phép bạn commit và quản lý nhánh ngay cả khi không có kết nối internet, sau đó đồng bộ khi có mạng trở lại.
Cơ chế quản lý nhánh (branching) trong Git rất nhẹ. Một nhánh thực chất chỉ là một con trỏ di động trỏ đến một commit cụ thể. Điều này cho phép bạn thử nghiệm tính năng mới trên các nhánh riêng biệt mà không gây rủi ro cho mã nguồn chính. Việc chuyển đổi giữa các nhánh diễn ra nhanh vì Git chỉ cập nhật những tệp có khác biệt giữa các snapshot.
Tính an toàn của Git đến từ cơ chế SHA-1. Mọi đối tượng trong Git đều được định danh bằng mã băm dựa trên nội dung, nên Git phát hiện ngay bất kỳ hỏng hóc dữ liệu hoặc thay đổi trái phép nào xảy ra trong quá trình lưu trữ hoặc truyền tải mã nguồn giữa các máy tính.
Git khác GitHub như thế nào?
Bạn cần phân biệt: Git là phần mềm quản lý phiên bản mã nguồn, còn GitHub là dịch vụ lưu trữ trực tuyến các kho lưu trữ Git. Git chạy cục bộ trên máy tính của bạn, trong khi GitHub cung cấp một không gian trên đám mây để bạn lưu và chia sẻ các dự án Git đó với cộng đồng.

GitHub bổ sung các lớp tính năng cộng tác bên ngoài lõi của Git, gồm Issues (quản lý lỗi và tính năng), Pull Requests (đề xuất thay đổi), Code Review (thẩm định mã) và GitHub Marketplace. Những công cụ này giúp quy trình phát triển phần mềm trực quan hơn và hỗ trợ thảo luận nhóm hiệu quả hơn so với việc chỉ dùng Git thuần túy.
Mô hình cộng tác trên GitHub cũng giúp việc đóng góp vào mã nguồn mở thuận tiện hơn. Thông qua tính năng fork và pull request, lập trình viên có thể đề xuất thay đổi cho các dự án mà họ không có quyền ghi trực tiếp. GitHub đã chuẩn hóa quy trình này, tạo ra một hệ sinh thái giúp lập trình viên khắp nơi phối hợp làm việc.
Git được dùng thế nào trong một nhóm?
Quy trình GitHub flow là tiêu chuẩn phổ biến trong các nhóm làm việc, gồm sáu bước:
- Tạo nhánh (branch): Tạo nhánh mới từ nhánh chính. Bạn nên đặt tên nhánh mang tính mô tả (ví dụ
fix-login-error) để các cộng sự nắm được mục đích công việc mà không cần mở mã nguồn. - Thực hiện thay đổi: Chỉnh sửa mã và commit.
- Tạo Pull Request (PR): Gửi yêu cầu để nhóm thẩm định thay đổi của bạn.
- Thảo luận và xử lý phản hồi: Cập nhật mã nguồn dựa trên góp ý của người thẩm định.
- Hợp nhất (merge): Sau khi được chấp thuận, mã được gộp vào nhánh chính.
- Xóa nhánh: Loại bỏ nhánh đã hợp nhất để giữ kho lưu trữ gọn gàng.

Trong môi trường chuyên nghiệp, mô hình Shared Repository thường đi kèm tính năng Protected Branches (nhánh được bảo vệ) để ngăn việc ghi đè trực tiếp vào các nhánh quan trọng như main. Ngược lại, mô hình Fork & Pull thường áp dụng cho các dự án mã nguồn mở, để kiểm soát chặt các đóng góp từ bên ngoài thông qua quy trình xét duyệt Pull Request.
Nên bắt đầu với Git từ đâu?
Để bắt đầu, bạn nên làm quen với các lệnh cơ bản trên giao diện dòng lệnh (CLI):
git init: Khởi tạo kho lưu trữ mới.git clone: Sao chép dự án từ xa về máy cục bộ.git add: Đưa tệp vào vùng chờ (Staging Area).git commit: Lưu snapshot vào lịch sử.git status: Kiểm tra trạng thái các tệp tin.git push/git pull: Đồng bộ dữ liệu với kho lưu trữ từ xa.
Ví dụ về quy trình khởi tạo và commit đầu tiên:
git init my-project
cd my-project
touch README.md
git add README.md
git commit -m "khởi tạo dự án"Hãy ưu tiên dòng lệnh khi mới bắt đầu. Hiểu rõ cách Git di chuyển dữ liệu giữa Working Tree, Index và Git Directory qua dòng lệnh sẽ giúp bạn xử lý các tình huống xung đột mã nguồn phức tạp tốt hơn nhiều so với việc chỉ dựa vào công cụ có giao diện đồ họa.
Tài liệu tham khảo
- Git - About Version Control
- Git - What is Git?
- Git Turns 20: A Q&A with Linus Torvalds — The GitHub Blog
- Why Use Version Control? — Tower Git Ebook
- Commits are snapshots, not diffs — The GitHub Blog
- About Git — GitHub Docs
- GitHub flow — GitHub Docs
- How to undo (almost) anything with Git — The GitHub Blog