Git là gì? Tại sao nó lại là công cụ mà mọi lập trình viên chuyên nghiệp đều cần thành thạo? Bài viết này sẽ trả lời cho những câu hỏi đó.
Bài toán quản lý phiên bản (version control)
Quản lý phiên bản (version control) là gì? tại sao chúng ta nên quan tâm đến nó? Để hiểu được vấn đề này, chúng ta nhắc lại một ví dụ sau:
Giả sử, bạn là một lập trình viên và công việc hàng ngày của bạn là lập trình. Tuy nhiên, có một vấn đề mà bạn chắc chắn sẽ hay gặp phải đó là mã nguồn mà các bạn viết ra lần đầu, lần thứ 2, … và thậm chí lần thứ n cũng khó có thể đúng và hoàn hảo ngay lập tức. Điều này đúng cả cho những lập trình viên mới vào nghề và cả với những chuyên gia gạo cội nhất.
Vậy, thông thường nếu là bạn thì bạn sẽ quản lý, lưu trữ các phiên bản này như thế nào?
Xóa chúng đi và làm hoàn toàn mới?
Nếu bạn làm như vậy, thì bạn sẽ gặp rắc rối khá lớn với các dự án lớn. Bởi rất nhiều khi, phiên bản sửa đổi lại tệ hơn cả phiên bản gốc và bạn cần phải quay lại để sử dụng những gì bạn đã viết cũ trước đây ! Vậy để đảm bảo việc đưa mã nguồn về trạng thái trước khi chỉnh sửa thì chúng ta sẽ làm như thế nào?
Cách đơn giản nhất là lưu nó lại thành một file khác, và tiếp tục làm dưới file mới này?
Tuy nhiên, nếu không có quy ước đặt tên hợp lý, sẽ có rất nhiều vấn đề xảy ra.
Rõ ràng, bạn sẽ rất khó để tìm kiếm được file nào mà bạn muốn. Thật sự là như vậy, với riêng bản thân mình tôi đã bị rất nhiều trường hợp phải tìm file mình cần giữa một loạt các file có tên là “_final”, thậm chí “_final_final”… mà cũng chẳng biết file nào thực sự là cuối cùng. Bạn có thể thêm các ngày tháng vào tên của file ví dụ như trên hình. Tuy nhiên, việc tự mình sao chép file mỗi lần chỉnh sửa thì sẽ rất vất vả, và cũng dễ xảy ra nhầm lẫn. Hoặc thậm chí ngay cả khi chẳng có nhầm lẫn thì bạn cũng rất khó tìm lại sau một thời gian không động đến nó nữa. Bạn chẳng thể biết file ngày 22/4 hay file ngày 24/4 là file mình cần. Bởi bạn chẳng nhớ nổi file đó đã sửa gì và sửa đến đâu, có gì khác so với các file cũ. Rất khó khăn phải không ạ?
Chưa kể, khi chúng ta đặt tên một cách vô trật tự thì không biết chúng ta sẽ phân biệt chúng kiểu gì. Thêm vào đó, với các dự án lớn, chúng ta cũng thường phải làm việc nhóm và yêu cầu chia sẻ các file trong nhóm thì vấn đề càng trở lên phức tạp hơn như các vấn đề về đồng bộ khi có nhiều người cùng chỉnh sửa cùng lúc. Khi đó sẽ xảy ra trường hợp xóa mất nội dung thay đổi của người đã chỉnh sửa trước đó.
Để giải quyết những vấn đề này chúng ta sử dụng các hệ thống quản lý phiên bản (VCS). Và một điển hình hay gặp nhất của nó là Git.
Hệ thống quản lý phiên bản là gì?
Hệ thống quản lý phiên bản nói một cách đơn giản là một hệ thống lưu trữ các thay đổi của một tập tin (file) hoặc tập hợp các tập tin theo thời gian và cho phép người dùng có thể quay lại một phiên bản xác định nào đó khi cần thiết.
Như định nghĩa trên có thể thấy, hệ thống quản lý phiên bản không chỉ đơn thuần giúp chúng ta quản lý mã nguồn của phần mềm như chúng ta vẫn hay gặp như Git, Github,…mà nó còn có thể được sử dụng để quản lý lưu trữ bất cứ định dạng tệp tin nào.
Bạn có thể sử dụng hệ thống quản lý phiên bản (Version Control System – VCS) để lưu trữ tất cả các phiên bản của một bức ảnh trong trường hợp bạn là một nhà thiết kế đồ họa, hoặc sử dụng nó để lưu trữ các bản layout của website trong trường hợp bạn làm thiết kế web. Nói chung VCS là một công cụ hữu ích và cần thiết đối với mọi người.
VCS giúp bạn trong việc khôi phục lại phiên bản cũ của các file, khôi phục lại phiên bản cũ của toàn bộ dự án, xem lại các thay đổi đã được thực hiện theo thời gian, xem ai là người thực hiện thay đổi cuối cùng, xem xét sự cố có thể xảy ra khi nào, ai là người đã gây ra sự cố đó…
Thậm chí khi bạn lỡ tay làm rối tung mọi thứ hoặc vô tính xóa mất các file đi, bạn cũng có thể khôi phục lại trạng thái của chúng một cách dễ dàng, nhanh chóng và không hề tốn quá nhiều công sức.
Hệ thống quản lý phiên bản tập trung và hệ thống quản lý phiên bản phân tán
Hệ thống quản lý phiên bản tập trung (Centralized Version Control Systems – CVCS) là một hệ thống lưu trữ các thay đổi tại một máy chủ trung tâm và các máy khách phải truy cập và tiến hành commit các thay đổi vào kho lưu trữ (repository) trung tâm này. Các hệ thống này, ví dụ như Subversion, TFVC, Perforce và Clearcase… bao gồm một máy chủ có chứa tất cả các tập tin đã được “phiên bản hoá” (versioned), và danh sách các máy khách có quyền thay đổi các tập tin này trên máy chủ trung tâm đó. Nếu một thay đổi được thực hiện, nó sẽ tiếp cận và đồng bộ trên máy chủ trung tâm và mọi nhà phát triển phía máy khách đều có thể thực hiện các commit thay đổi, điều đó cũng có nghĩa rằng họ có thể đưa các mã nguồn lỗi vào kho lưu trữ này. Điều này thật không ổn khi chỉ một người đưa mã nguồn lỗi lên hệ thống thì toàn bộ những người tham gia sẽ bị ảnh hưởng và làm việc trên mã nguồn lỗi này. Hơn nữa do chỉ có một kho lưu trữ “đúng” duy nhất, vì vậy việc làm việc ngoại tuyến mà không có mạng là một vấn đề. Để hoàn thành các hoạt động cơ bản như thêm lịch sử xem hoặc commit mã nguồn mới, người dùng cần phải tiến hành truy cập vào kho lưu trữ. Mô hình này được sử dụng khá phổ biến và được coi là mô hình tiêu chuẩn cho các hệ thống quản lý phiên bản trước đây.
Do những hạn chế của các hệ thống quản lý phiên bản tập trung, Các hệ thống quản lý phiên bản phân tán – Distributed Version Control Systems (DVCS) như Git, Mercurial, Bazaar hay Darcs đã ra đời. Trong các hệ thống này các máy khách không chỉ “check out” (sao chép về máy cục bộ) các phiên bản mới nhất của các tập tin mà chúng còn sao chép (mirror) toàn bộ kho chứa (repository) và làm việc cục bộ trên chính kho chứa sao chép này, sau đó sẽ tiến hành commit các thay đổi lên hệ thống chung. Chính vì vậy nếu như một máy khách nào trong hệ thống bị lỗi, thì kho chứa từ một máy khách bất kỳ khác nào cũng có thể dùng để sao chép ngược trở lại máy chủ để khôi phục lại toàn bộ hệ thống. Mỗi lần checkout của máy khách là một lần tạo bản sao đầy đủ của tất cả dữ liệu.
Trong mô hình phân tán, mọi nhà phát triển đều có bản sao kho lưu trữ của riêng mình mà không cần làm việc qua một máy chủ trung tâm. Với cách tiếp cận này, các nhà phát triển có thể làm việc ngoại tuyến – có thể commit, phân nhánh, hợp nhất các nhánh, xem lịch sử, hoặc bất cứ thao tác gì cần thiết khi đã có toàn bộ kho lưu trữ cục bộ. Chỉ cần truy cập Internet khi muốn đồng bộ hóa dữ liệu với các thành viên khác trong nhóm.
Các hệ thống quản lý phiên bản phân tán này xử lý rất tốt việc quản lý nhiều kho chứa từ xa, vì vậy bạn có thể cộng tác với nhiều nhóm các nhà phát triển khác nhau theo những cách khác nhau trong cùng một dự án. Điều này cho phép bạn cài đặt nhiều loại “tiến trình công việc” (workflow) không thể thực hiện được với các hệ thống tập trung.
Git là gì?
Git là một hệ thống quản lý phiên bản phân tán để theo dõi các thay đổi trong mã nguồn trong quá trình phát triển phần mềm. Nó được thiết kế với mục tiêu chính là để hỗ trợ sự phối hợp công việc giữa các lập trình viên, tuy nhiên nó cũng có thể được sử dụng để theo dõi các thay đổi trong các hệ thống tệp tin bất kỳ nói chung.
Git được Linus Torvalds tạo ra vào năm 2005, vốn được phát triển nhằm tạo thuận lợi cho việc quản lý mã nguồn trong quá trình phát triển nhân của Linux. Và sau này nó cũng được mở rộng sang các môi trường khác như Windows hay MacOS với nhiều mục đích khác nhau, tuy nhiên mục tiêu tính vẫn là được sử dụng để quản lý mã nguồn trong quá trình phát triển phần mềm. Giống như hầu hết các hệ thống kiểm soát phiên bản phân tán khác, mọi thư mục Git trên mỗi máy tính là một kho lưu trữ ghi lại đầy đủ nội dung và lịch sử thay đổi cùng với khả năng theo dõi phiên bản mà không cần duy trì kết nối mạng liên tục. Git là phần mềm miễn phí và nguồn mở được phân phối theo các điều khoản của Giấy phép Công cộng GNU phiên bản 2.
Trên Git, các lịch sử cập nhật sẽ lưu trạng thái của file khi có nhu cầu. Vì thế, chúng ta có thể khôi phục lại trạng thái của một file đã chỉnh sửa về trạng thái cũ hoặc có thể xem xét được sự khác biệt qua các lần chỉnh sửa.
Khi định ghi đè (overwrite) lên file mới nhất đã chỉnh sửa của người khác bằng file đã chỉnh sửa dựa trên file cũ, thì khi đăng (upload) lên server sẽ hiện ra cảnh cáo. Điều này giúp tránh được các lỗi xung đột do việc ghi đè lên nội dung chỉnh sửa của người khác mà không hề hay biết.
Git ra đời như thế nào?
Sự hình thành của Git gắn liền với quá trình phát triển của nhân Linux. Ban đầu, trong phần lớn thời gian cập nhật bảo trì của nhân Linux (1991-2002), các thay đổi trên mã nguồn của nó được truyền đi dưới dạng các bản vá và các tập tin lưu trữ.Tuy nhiên, do sự mở rộng của cộng đồng và sự phức tạp trong dự án phát triển, nó yêu cầu phải sử dụng một hệ thống quản lý phiên bản phân tán. Năm 2002, dự án nhân Linux bắt đầu sử dụng một hệ thống quản lý phiên bản phân tán có tên là BitKeeper. Ban đầu, do sự hợp tác giữa cộng đồng phát triển và công ty phát triển BitKeeper, các nhà phát triển được sử dụng nó một cách miễn phí. Tuy nhiên, do một số lí do, đến năm 2005, sự hợp tác này không được duy trì nữa, và các nhà phát triển bắt đầu phải trả phí. Chính điều này đã thúc đẩy cộng đồng phát triển Linux (chính xác hơn là Linus Torvalds, người sáng lập ra Linux) phát triển công cụ của riêng dựa trên những chức năng cơ bản của BitKeeper.
Kể từ khi ra đời năm 2005, Git đã tiến hoá và phát triển toàn diện để dễ dàng sử dụng hơn, và hoạt động vô cùng hiệu quả với các dự án lớn.
Sự khác biệt giữa các hệ thống quản lý phiên bản khác và Git là gì?
Nếu các bạn đã có một số kiến thức về các hệ thống quản lý phiên bản khác, như Subversion hay Perforce thì khi sang Git, bạn sẽ khá bối rối. Mặc dù giao diện và một số thao tác cơ bản trên Git khá giống các VCS khác, tuy nhiên nó có quan điểm về thông tin và cách thức lưu trữ thông tin khá khác biệt.
Vậy sự khác biệt giữa các VCS khác và Git là gì?
Phần lớn các hệ thống VCS khác lưu trữ thông tin dưới dạng danh sách các tập tin được thay đổi. Chúng coi thông tin được lưu trữ như một tập hợp các tập tin và các thay đổi được thực hiện trên mỗi tập tin theo thời gian.

Cách thức lưu trữ dữ liệu của các VCS khác
Git không xử lý dữ liệu theo cách này. Git coi dữ liệu giống như một tập hợp các “ảnh” (snapshot) của một hệ thống tập tin nhỏ. Mỗi lần bạn “commit”, hoặc lưu lại trạng thái hiện tại của dự án trong Git sẽ đồng nghĩa với việc snapshot lại nội dung của tất cả các tập tin tại thời điểm đó và tạo ra một tham chiếu tới “ảnh” đó. Nếu như tập tin không có sự thay đổi nào, Git sẽ không lưu trữ tập tin đó lại một lần nữa mà chỉ tạo một liên kết tới tập tin gốc đã tồn tại trước đó.

Cách thức lưu trữ dữ liệu của Git
Đây là sự khác biệt lớn nhất giữa Git và hầu hết các VCS khác. Điều này làm cho Git không chỉ là một hệ thống quản lý phiên bản đơn giản, mà nó hoạt động gần giống như một hệ thống quản lý tập tin thu nhỏ với các tính năng, công cụ vô cùng mạnh mẽ. Nó tạo ra một số lợi ích trong việc Phân nhánh trong Git.
Cách thức hoạt động của Git là gì?
Phần lớn các thao tác/hoạt động trong Git chỉ cần yêu cầu các tập tin hay tài nguyên cục bộ. Git không yêu cầu bất cứ thông tin hay tài nguyên từ máy tính nào khác trong mạng. Toàn bộ dự án hoàn toàn nằm trên ổ cứng của bạn, do đó các thao tác được thực hiện gần như ngay lập tức mà không hề có độ trễ như trên các hệ thống quản lý phiên bản tập trung.
Khi bạn muốn xem lịch sử của dự án, Git không cần phải lấy thông tin đó từ một máy chủ khác để hiển thị, mà đơn giản nó được đọc trực tiếp từ chính cơ sở dữ liệu cục bộ của bạn. Và do đó thao tác này được thực hiện gần như ngay lập tức. Nếu như bạn muốn so sánh sự thay đổi giữa phiên bản hiện tại của một tập tin với phiên bản của một tháng trước, Git có thể tìm kiếm tập tin cũ đó trên máy cục bộ rồi sau đó so sánh sự khác biệt cho bạn. Thay vì việc phải truy vấn từ xa hoặc “kéo về” (pull) phiên bản cũ của tập tin đó từ máy chủ trung tâm rồi mới thực hiện so sánh cục bộ.
Do đó, bạn có thể làm hầu hết mọi việc mà không cần đến kết nối Internet hay VPN. Bạn có thể vừa di chuyển vừa làm việc, làm việc ở nhà, hay đi du lịch ở đâu đó, việc commit diễn ra bình thường cho tới khi có kết nối Internet để đồng bộ hoá. Trong rất nhiều hệ thống khác, việc này gần như là không thể hoặc rất khó khăn. Ví dụ trong Perforce hay Subversion, bạn gần như không thể làm gì nếu như không kết nối được tới máy chủ; bạn có thể sửa tập tin nhưng bạn không thể commit các thay đổi đó vào cơ sở dữ liệu (vì cơ sở dữ liệu của bạn không được kết nối). Đây có thể không phải là điều gì đó lớn lao đối với Git. Nó còn có nhiều chức năng hay ho hơn nhiều.
Git đảm bảo tính toàn vẹn của tệp tin
Cơ chế đảm bảo tính toàn vẹn trong git là gì?
Git “băm” mọi dữ liệu trước khi lưu trữ và tiến hành tham chiếu tới dữ liệu thông qua các mã băm này. Điều này làm cho là việc thay đổi nội dung của một tập tin hay một thư mục mà Git không biết tới là điều không thể. Chức năng này là cốt lõi trong Git và về mặt lý thuyết có thể đảm bảo tính toàn vẹn cho các tệp tin lưu trữ. Mọi sự mất mát hay lỗi trên dữ liệu đều sẽ bị Git phát hiện được.
Thuật toán băm được sử dụng trong Git là SHA-1. Thuật toán băm này biến một nội dung dữ liệu có kích thước bất kỳ thành một chuỗi có độ dài 40 ký tự Hexa (0-9 và A – F). Một mã băm SHA-1 có định dạng như sau:
1 |
[crayon-607bfea37ef3c918092683 inline="true" ]24b9da6552252987aa493b52f8696cd6d3b00373 |
[/crayon]
Mã băm này được tính toán dựa trên nội dung của tập tin hoặc cấu trúc thư mục trong Git.
Bạn sẽ thấy các mã băm được sử dụng ở mọi nơi trong Git. Thực tế, Git không lưu trữ và xử lý trực tiếp tên tệp mà sử dụng các mã băm của tệp để đưa vào lưu trữ trong một cơ sở dữ liệu có thể truy vấn được.
Khi bạn thực hiện các hành động trong Git, phần lớn tất cả hành động đó đều được thêm vào cơ sở dữ liệu của Git. Rất khó để yêu cầu hệ thống thực hiện một hành động nào đó mà không thể khôi phục lại được (chẳng hạn như việc xoá dữ liệu). Giống như trong các VCS khác, bạn có thể xóa hoặc làm rối tung dữ liệu mà bạn chưa commit; nhưng khi bạn đã commit thì rất khó để xóa các dữ liệu đó đi, đặc biệt là nếu bạn thường xuyên đẩy (push) cơ sở dữ liệu sang một kho chứa khác.
Điều này khiến việc sử dụng Git trở nên “an toàn” bởi vì chúng ta có thể thử nghiệm, “nghịch ngợm” mà không lo sợ sẽ phá hỏng mọi thứ.
Ba trạng thái cơ bản của Git là gì?
Git xử lý và lưu trữ các tệp dưới 3 trạng thái cơ bản đó là: committed, modified, và staged. Đây là yếu tố quan trọng nhất mà bạn cần nhớ để có thể hiểu được những phần tiếp theo một cách trôi chảy.
- Committed là trạng thái khi dữ liệu đã được lưu trữ một cách an toàn trong cơ sở dữ liệu.
- Modified là trạng thái tệp tin đã bị thay đổi nhưng chưa được commit vào cơ sở dữ liệu.
- Và staged là trạng thái đã đánh dấu sẽ commit phiên bản hiện tại của một tập tin đã chỉnh sửa trong lần commit sắp tới.
Dựa trên 3 trạng thái này Git tạo ra ba khu vực riêng biệt: thư mục Git, thư mục làm việc, và khu vực tổ chức (staging area).
Thư mục Git là nơi Git lưu trữ các “siêu dữ liệu” (metadata) và cơ sở dữ liệu cho dự án. Đây là phần quan trọng nhất của Git, nó là phần được sao lưu về khi bạn tạo một bản sao (clone) của một kho chứa từ một máy tính khác.
Thư mục làm việc là bản sao một phiên bản của dự án. Những tập tin này được kéo về (pulled) từ cơ sở dữ liệu được nén lại trong thư mục Git và lưu trên ổ cứng cho bạn sử dụng hoặc chỉnh sửa.
Khu vực tổ chức là một tập tin đơn giản được chứa trong thư mục Git, nó chứa thông tin về những gì sẽ được commit trong lần commit sắp tới. Khu vực này cũng thường được gọi là khu vực “chỉ mục” (index).
Git tuân theo tiến trình làm việc cơ bản như sau:
- Đầu tiên bạn thay đổi các tập tin trong thư mục làm việc.
- Sau đó bạn tổ chức các tập tin, tạo mới snapshot của các tập tin đó vào khu vực tổ chức.
- Cuối cùng là commit, snapshot của các tập tin trong khu vực tổ chức sẽ được lưu trữ vĩnh viễn vào thư mục Git.
Nếu một phiên bản nào đó của một tập tin nằm trong thư mục Git, nó được coi là đã commit. Nếu như nó đã được sửa và thêm vào khu vực tổ chức, nghĩa là nó đã được staged. Và nếu nó được thay đổi từ khi checkout nhưng chưa được staged, nó được coi là đã thay đổi.
Trong bài viết này chúng ta đã biết Git là gì, và một số khái niệm cơ bản trong Git, cách thức Git lưu trữ và kiểm soát các trạng thái. Trong các bài viết tiếp theo chúng ta sẽ tìm hiểu chi tiết hơn cách thức sử dụng Git và làm rõ những ưu điểm của Git là gì.
Hãy theo dõi chuyên mục và để lại bình luận bên dưới nhé!