Git (01): Tổng quan

1         Tổng quan

1.1       Hệ thống quản lý phiên bản


Định nghĩa về quản lý phiên bản

Phiên bản (version) là các bản khác nhau của một hoặc nhiều tập tin, thư mục hay cả dự án (từ đây gọi chung là tập tin để tiện trình bày). Trong quá trình làm việc, nội dung của tập tin luôn thay đổi, vì vậy nhu cầu xem lại hoặc khôi phục lại trạng thái của tập tin tại một thời điểm nào đó trong quá khứ rất cần thiết. Hệ thống quản lý phiên bản (Version Control System – VCS) sẽ giúp làm được điều này. 

Hệ thống quản lý phiên bản bao gồm phần mềm và cách thức làm việc đi kèm với nó.

Một vài chức năng chính của hệ thống quản lý phiên bản:

– Khôi phục lại trạng thái của một tập tin ở các thời điểm khác nhau trong quá khứ

– Biết được ai đã thực hiện các thay đổi trên tập tin, và đã thay đổi những gì

– Dễ dàng khôi phục lại các nội dung hoặc tập tin bị xóa  

– Dễ dàng so sánh những thay đổi của tập tin theo các mốc thời gian

Dựa trên cách tổ chức và hoạt động, các hệ thống quản lý phiên bản được chia thành ba loại, gồm: hệ thống cục bộ, hệ thống tập trung và hệ thống phân tán.

Hệ thống quản lý phiên bản cục bộ

Đây là cách làm thủ công, đơn giản, không nhất thiết phải dùng tới phần mềm. Nó đơn giản chỉ là việc người dùng tự lưu trữ các tập tin ở các thời điểm khác nhau trong quá trình làm việc thành các tên khác nhau. Để tiện theo dõi, người dùng có thể đặt tên tập tin bao gồm thời gian, cộng với một vài từ khóa nhận diện. Ví dụ: logo_2020_02_20_xanh.gif, logo_2020_02_21_do.gif.

Với hệ thống này, người dùng rất khó để quản lý khi số lượng tập tin nhiều, liên tục thay đổi theo thời gian. Để hỗ trợ, các lập trình viên đã tạo ra các công cụ giúp quản lý các thay đổi, dùng cơ sở dữ liệu cục bộ để lưu trữ và quản lý các thay đổi.

Công cụ phổ biến được dùng để quản lý phiên bản cục bộ là RCS. Tìm hiểu thêm về RCS tại đây: https://www.gnu.org/software/rcs/

Hệ thống quản lý phiên bản cục bộ có thể lưu mỗi phiên bản trong một thư mục, sử dụng cơ sở dữ liệu để quản lý thông tin các thư mục. Tuy nhiên, hệ thống này không hỗ trợ làm việc trên môi trường cộng tác nhiều người. Xem hình minh họa [2],




Hệ thống quản lý phiên bản tập trung

Với hệ thống quản lý phiên bản cục bộ, các thành viên trong nhóm rất khó chia sẻ và cộng tác trong quá trình làm việc. Hệ thống quản lý phiên bản tập trung sẽ giải quyết được vấn đề này.


Hệ thống quản lý phiên bản tập trung (Centralized Version Control Systems – CVCS) gồm máy chủ chứa các phiên bản của tập tin và danh sách các máy khách được phép thay đổi các tập tin trên máy chủ. Các máy khách sẽ lấy các phiên bản của tập tin từ máy chủ về, thực hiện các thay đổi trên tập tin và cập nhật lại các thay đổi về máy chủ.
Xem hình minh họa,



Một số hệ thống quản lý phiên bản tập trung: CVS, Subversion (SVN), Perforce.

Hạn chế của hệ thống quản lý phiên bản tập trung là nếu máy chủ bị trục trặc sẽ dẫn tới gián đoạn việc cập nhật phiên bản của các thành viên, hoặc bị mất toàn bộ các phiên bản của tập tin trên server.

Hệ thống quản lý phiên bản phân tán

Hệ thống quản lý phiên bản phân tán giúp khắc phục hạn chế của hệ thống quản lý phiên bản tập trung.

Với hệ thống quản lý phiên bản phân tán, các máy client không chỉ chép phiên bản mới nhất của các tập tin từ server về, mà nó còn chép toàn bộ cả kho chứa (repository, repo), trong đó bao gồm cả lịch sử các phiên bản. Do vậy, nếu máy chủ gặp trục trặc thì vẫn có thể lấy bất kì kho chứa tại các máy client để khôi phục lại toàn bộ kho chứa cho máy server. Ví dụ các hệ thống quản lý phiên bản phân tán: Git, Mercurial, Bazaar, Darcs.


Xem hình minh họa,


Ngoài ra, hệ thống này cũng cho phép một máy client có thể liên kết với nhiều kho chứa ở xa cùng lúc, do vậy bạn có thể cùng lúc cộng tác với nhiều nhóm làm việc khác nhau.  

1.2       Lịch sử sơ lược về Git


Từ năm 2002, Linux sử dụng một hệ thống quản lý phiên bản phân tán (Distributed Version Control System - DVCS) có tên là BitKeeper

Năm 2005 hợp đồng với BitKeeper chấm dứt, cộng đồng Linux không tiếp tục sử dụng BitKeeper nữa mà tự xây dựng một DVCS mới, dựa trên các đặc điểm học được từ hệ thống BitKeeper.
DVCS mới cần đáp ứng được các yêu cầu sau:

– Xử lý nhanh

– Thiết kế đơn giản

– Hỗ trợ tốt cho "phát triển phi tuyến tính" (non-linear development), cho phép quản lý hàng ngàn nhánh song song

– Phân tán toàn diện

– Có khả năng xử lý các dự án phức tạp, với tốc độ cao và khối lượng dữ liệu lớn (giống như nhân Linux)


Trong năm 2005 Git đã ra đời, đáp ứng được các yêu cầu đặt ra và nhanh chóng được sử dụng rộng rãi.

1.3        Nguyên tắc làm việc của Git


Để sử dụng Git hiệu quả, cần biết và hiểu một số nguyên tắc làm việc của nó.

“Chụp ảnh”

Một cách rất tự nhiên, khi bạn cần lưu trữ các phiên bản khác nhau của mỗi tập tin bạn sẽ làm như thế nào? Như trong phần “quản lý phiên bản cục bộ” đã đề cập: khi một tập tin có thay đổi và cần lưu thành một phiên bản khác, bạn sẽ lưu nó thành một tập tin mới với tên mới. Nghĩa là tập tin mới có thay đổi delta nào đó so với tập tin ban đầu. Để tối ưu việc lưu trữ, thực tế chỉ cần lưu tập tin gốc, cộng thêm thông tin của mỗi lần thay đổi (delta). Khi đó, thông tin một phiên bản của dự án sẽ gồm các tập tin gốc, cùng với các thay đổi của từng tập tin. Đây chính là cách tiếp cận của đa số các hệ thống quản lý phiên bản, như: CVS, Subversion (SVN), Perforce, Bazaar.


Xem hình minh họa,




Với Git thì khác, để lưu lại một phiên bản của dự án, Git sẽ chụp ảnh (snapshot) toàn bộ các tập tin của dự án. Tập tin nào có thay đổi thì “chụp” (tạo ra một ảnh mới cho tập tin), tập tin nào không thay đổi thì không “chụp”, mà chỉ tạo một liên kết, trỏ về phiên bản trước của nó.

Xem hình minh họa,



Có thể thấy, dữ liệu của Git gồm một loạt các “ảnh chụp” của hệ thống tập tin đơn giản (miniature filesystem). Mỗi “ảnh chụp” là một phiên bản của dự án, tương đương với một “commit” trong hệ thống Git.

Phần lớn các thao tác với Git được thực hiện trên máy cục bộ

Khi làm việc với Git, hầu hết các thông tin và tài nguyên đều có sẵn trên máy cục bộ, do vậy bạn không phải kết nối tới server ở xa.

Ví dụ, nếu bạn muốn xem lại thông tin hoặc nội dung các phiên bản trước của dự án, thì bạn chỉ việc xem trong cơ sở dữ liệu của Git tại máy cục bộ. Hoặc nếu bạn muốn lưu lại phiên bản hiện thời của dự án (commit), bạn cũng thực hiện trên máy cục bộ. Chỉ khi nào bạn muốn chia sẻ phiên bản mới cho thành viên khác thì mới cần tới mạng để tải phiên bản mới lên server (push).

Git đảm bảo tính toàn vẹn

Mọi thứ trong Git (ví dụ tập tin) đều được tạo mã kiểm tra (checksum) trước khi lưu vào cơ sở dữ liệu Git. Git tạo ra mã kiểm tra bằng cách chạy một thuật toán (SHA-1) dựa vào nội dung của tập tin.
Kết quả của thuật toán SHA-1 sẽ tạo ra một số hexa, tạm gọi là mã SHA-1, có chiều dài 40 kí số. Ví dụ, một mã SHA-1: 24b9da6552252987aa493b52f8696cd6d3b00373

Git dùng mã SHA-1 của tập tin để đặt tên mới cho nó và thao tác với tên mới này chứ không không quan tâm đến tên thật của tập tin.

Giả sử bằng cách nào đó, nội dung của một tập tin bị thay đổi, khi Git mở tập tin, nó sẽ tính lại mã SHA-1, so với mã SHA-1 đã được lưu trước đây, nếu hai mã này không khớp, Git sẽ phát hiện ra là nội dung của tập tin đã bị thay đổi.

Như vậy không thể có tình trạng nội dung của tập tin bị thay đổi mà Git không biết, cơ chế này đảm bảo dữ liệu do Git quản lý luôn có tính toàn vẹn.

Git chỉ “thêm” dữ liệu

Trong quá trình làm việc với Git, hầu như mọi thao tác đều được Git ghi vào cơ sở dữ liệu. Bạn có thể bị mất hoặc bị xáo trộn thông tin nếu chưa lưu phiên bản (commit), nếu bạn đã lưu phiên bản thì rất khó bị mất dữ liệu, đặc biệt nếu bạn thường xuyên đẩy cơ sở dữ liệu Git lên server (push) hoặc tới kho chứa khác.

Cách làm việc theo kiểu luôn “thêm” dữ liệu (không xóa) tạo ra cảm giác yên tâm cho người sử dụng.

Ba trạng thái quan trọng của tập tin

Khi một tập tin (thư mục) đã được Git quản lý, nó có thể ở các trạng thái sau: modified, staged, committed.

– modified: tập tin đã bị thay đổi (nội dung hoặc tên), nhưng chưa lưu phiên bản (commit) vào cơ sở dữ liệu Git trên máy cục bộ (hay .git directory, repository, repo)

– staged: tập tin đã bị thay đổi, đã được đánh dấu là sẽ lưu phiên bản vào cơ sở dữ liệu Git trên máy cục bộ

– committed: là tập tin đã bị thay đổi, đã được đánh dấu và đã được lưu phiên bản trong cơ sở dữ liệu Git trên máy cục bộ

Ba trạng thái trên tạo ra ba vùng làm việc của một dự án đã được Git quản lý (thư mục đã được nhúng Git vào bên trong): gồm working tree (hay working directory), staging area và .git directory.

– working directory: thư mục làm việc hiện thời, là bản sao một phiên bản của dự án, nó được lấy ra từ cơ sở dữ liệu Git (.git directory). Đây là thư mục làm việc của lập trình viên, thao tác trên nó như một thư mục bình thường.

– staging area: khu vực tổ chức, là một tập tin (index) nằm trong thư mục .git, chứa thông tin về những gì sẽ được lưu phiên bản (commit) trong lần tới.

– .git directory: thư mục .git, là nơi Git lưu trữ “siêu dữ kiện” (metadata), và cơ sở dữ liệu của Git (không phải cơ sở dữ liệu của ứng dụng đang được phát triển). Đây là phần quan trọng nhất của Git, nó là thành phần được sao lưu (copy) về khi bạn nhân bản một kho chứa từ máy khác (clone).


Xem hình minh họa,



Về cơ bản, tiến trình công việc (workflow) khi thao tác với Git gồm:

– Bạn thao tác (tạo mới, thêm dữ liệu, sửa, xóa) với tập tin/thư mục trong working directory

– Đưa vào staging area các tập tin/thư mục mà bạn muốn lưu trữ vào .git directory (những thứ sẽ được lưu phiên bản, sẽ được commit)

– Tạo phiên bản cho các nội dung đã có trong staging area, cụ thể là thực hiện lệnh commit. Các tập tin/thư mục đã được đánh dấu trong staging area sẽ được lưu trữ an toàn vào .git directory

Một tập tin nằm trong .git directory được xem là đã được committed. Nếu tập tin đã bị thay đổi và đã được đưa vào staging area được xem là staged. Và nếu một tập tin đã bị thay đổi tính từ thời điểm được sinh ra từ .git directory (check out) và chưa đưa vào staging area thì được xem là modified.


Đọc thêm “The biggest misconception about Git”: https://medium.com/@gohberg/the-biggest-misconception-about-git-b2f87d97ed52

1.4       Dùng Git ở chế độ dòng lệnh


Tại sao nên học/dùng Git ở chế độ dòng lệnh (command line)?

Để sử dụng Git có rất nhiều cách, có thể chỉ cần dùng chương trình dòng lệnh hoặc có thể dùng các chương trình có giao diện đồ họa (GUI).

Tuy nhiên, chỉ có chương trình dòng lệnh mới có thể chạy tất cả các lệnh của Git, ngược lại các chương trình đồ họa chỉ bao gồm các lệnh phổ biến của Git.

Một người biết sử dụng Git ở chế độ dòng lệnh rất dễ dàng sử dụng Git ở chế độ đồ họa, điều ngược lại không phải khi nào cũng đúng.

Giao diện GUI thì có nhiều loại, tùy sở thích, mỗi người dùng sẽ cài những phần mềm GUI khác nhau, muốn sử dụng được phải có thời gian làm quen. Tuy nhiên, giao diện dòng lệnh chỉ có một kiểu và máy nào cũng có, rất dễ sử dụng.

Một số chương trình dòng lệnh: Terminal của macOS, Command Prompt hoặc PowerShell của Windows, hoặc Git bash của Git.

Một số chương trình GUI: Github Desktop, SourceTree, GitKraken, SmartGit, Git Cola, GitForce, Giggle, Magit, Egit, Gitg[1].

-----
[2] https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control
-----------
Cập nhật [25/02/2020]
-----------
Xem thêm: Git (02): Cài đặt và cấu hình Git
-----
Bạn muốn tự học HTML bài bản? Xem thêm