Git (phần mềm)

**Git** () là một hệ thống phần mềm quản lý phiên bản phân tán, có khả năng quản lý các phiên bản của mã nguồn hoặc dữ liệu. Nó thường được các lập trình viên sử dụng để quản lý mã nguồn khi phát triển phần mềm theo nhóm.

Các mục tiêu thiết kế của Git bao gồm: tốc độ, tính toàn vẹn dữ liệu và hỗ trợ các quy trình làm việc phân tán, phi tuyến tính với hàng nghìn nhánh song song chạy trên nhiều máy tính khác nhau.

Giống như hầu hết các hệ thống quản lý phiên bản phân tán khác, và khác với đa số hệ thống theo mô hình khách – chủ (client–server), Git lưu trữ một bản sao cục bộ của toàn bộ kho lưu trữ (repository, thường gọi tắt là "repo"), bao gồm cả lịch sử và khả năng theo dõi phiên bản, độc lập với kết nối mạng hay máy chủ trung tâm. Mỗi kho lưu trữ được lưu trên máy tính trong một thư mục chuẩn với các tệp ẩn bổ sung để cung cấp khả năng quản lý phiên bản. Git cung cấp các tính năng để đồng bộ thay đổi giữa các kho lưu trữ có chung lịch sử; đối với cộng tác bất đồng bộ, điều này mở rộng tới các kho trên những máy từ xa. Mặc dù tất cả các kho lưu trữ (có cùng lịch sử) về mặt lý thuyết là ngang hàng, các lập trình viên thường sử dụng một máy chủ trung tâm để lưu một bản tích hợp.

Git là phần mềm tự do nguồn mở được phân phối theo giấy phép GPL-2.0-only.

Git ban đầu được Linus Torvalds tạo ra để quản lý phiên bản trong quá trình phát triển Linux kernel. Nhãn hiệu "Git" được đăng ký bởi Software Freedom Conservancy.

Ngày nay, Git là hệ thống quản lý phiên bản được sử dụng phổ biến nhất bởi các lập trình viên. Đây là hệ thống quản lý phiên bản phân tán phổ biến nhất, với gần 95% lập trình viên cho biết đây là hệ thống quản lý phiên bản chính mà họ sử dụng tính đến năm 2022. Git là công cụ quản lý mã nguồn được dùng rộng rãi nhất trong giới lập trình viên chuyên nghiệp. Nhiều dịch vụ kho Git được cung cấp, bao gồm GitHub, SourceForge, Bitbucket và GitLab.

## Lịch sử
Torvalds bắt đầu phát triển Git vào tháng 4 năm 2005 sau khi giấy phép miễn phí của BitKeeper – hệ thống quản lý mã nguồn (SCM) độc quyền được dùng cho phát triển nhân Linux từ năm 2002 – bị thu hồi đối với dự án Linux. Chủ sở hữu bản quyền BitKeeper là Larry McVoy cho rằng Andrew Tridgell đã tạo ra SourcePuller bằng cách đảo ngược các giao thức của BitKeeper. Sự kiện này cũng thúc đẩy sự ra đời của Mercurial, một hệ thống quản lý phiên bản khác.

Torvalds muốn có một hệ thống phân tán có thể sử dụng theo cách giống BitKeeper, nhưng không hệ thống miễn phí nào hiện có đáp ứng được nhu cầu của ông. Ông dẫn ví dụ một hệ thống quản lý mã nguồn cần tới 30 giây để áp dụng một bản vá và cập nhật toàn bộ siêu dữ liệu liên quan, và nhận xét rằng điều này không thể mở rộng cho nhu cầu phát triển nhân Linux, nơi việc đồng bộ với các người bảo trì khác có thể đòi hỏi thực hiện 250 thao tác như vậy cùng lúc. Về tiêu chí thiết kế, ông đặt yêu cầu việc áp dụng một bản vá không được mất quá ba giây, và bổ sung ba mục tiêu nữa:
* Lấy Concurrent Versions System (CVS) làm ví dụ *không nên* làm theo; nếu phân vân, hãy đưa ra quyết định ngược lại hoàn toàn.
* Hỗ trợ một quy trình làm việc phân tán, giống BitKeeper.
* Bao gồm các cơ chế bảo vệ rất mạnh chống lại sự hỏng hóc dữ liệu, dù là vô ý hay cố ý.

Những tiêu chí này đã loại bỏ mọi hệ thống quản lý phiên bản đang được dùng vào thời điểm đó, nên ngay sau khi nhân Linux 2.6.12-rc2 được phát hành, Torvalds bắt tay vào việc viết hệ thống riêng của mình.

Việc phát triển Git bắt đầu vào ngày 3 tháng 4 năm 2005. Torvalds công bố dự án ngày 6 tháng 4 và ngày hôm sau đã dùng chính Git để quản lý và lưu trữ mã nguồn của chính nó. Lần gộp (*merge*) nhiều nhánh đầu tiên diễn ra ngày 18 tháng 4. Torvalds đã đạt được các mục tiêu về hiệu năng; ngày 29 tháng 4, phiên bản Git còn sơ khai được benchmark với tốc độ ghi các bản vá vào cây mã nguồn nhân Linux là 6,7 bản vá mỗi giây. Vào ngày 16 tháng 6, Git đã quản lý được bản phát hành nhân 2.6.12.

Ngày 26 tháng 7 năm 2005, Torvalds chuyển việc bảo trì dự án cho Junio Hamano, một trong những người đóng góp chính. Hamano chịu trách nhiệm phát hành phiên bản 1.0 vào ngày 21 tháng 12 năm 2005.

### Tên gọi
Torvalds từng nói đùa một cách châm biếm về cái tên *git* (tiếng lóng Anh–Anh, chỉ một người khó ưa hoặc ngớ ngẩn): "I'm an egotistical bastard, and I name all my projects after myself. First ‘Linux’, now ‘git’." ("Tôi là một thằng tự cao tự đại, và tôi đặt tên mọi dự án của mình theo tên tôi. Trước là ‘Linux’, giờ là ‘git’.") Trang hướng dẫn của chính Git mô tả đây là "trình theo dõi nội dung ngu ngốc" ("the stupid content tracker").

Tệp read-me trong mã nguồn giải thích thêm:

Trong mã nguồn của Git, chương trình còn được gọi là "the information manager from hell" (trình quản lý thông tin đến từ địa ngục).

## Đặc trưng

### Thiết kế
Thiết kế của Git là một sự tổng hợp giữa kinh nghiệm của Torvalds với Linux trong việc duy trì một dự án phát triển phân tán lớn, hiểu biết sâu sắc của ông về hiệu năng hệ thống tệp thu được từ chính dự án đó, và nhu cầu cấp bách phải tạo ra một hệ thống hoạt động được trong thời gian ngắn. Những yếu tố này dẫn tới các lựa chọn cài đặt sau:
; Hỗ trợ mạnh cho phát triển phi tuyến tính: Git hỗ trợ việc tạo nhánh (*branching*) và gộp nhánh (*merging*) rất nhanh, và cung cấp các công cụ riêng để trực quan hóa và điều hướng lịch sử phát triển phi tuyến. Trong Git, một giả định cốt lõi là một thay đổi sẽ được gộp (*merge*) nhiều lần hơn là được viết ra, khi nó được chuyển qua lại giữa nhiều người đánh giá khác nhau. Trong Git, nhánh rất nhẹ: một nhánh chỉ là một tham chiếu (*reference*) trỏ tới một commit.
; Phát triển phân tán: Cũng giống như Darcs, BitKeeper, Mercurial, Bazaar, và Monotone, Git cung cấp cho mỗi lập trình viên một bản sao cục bộ của toàn bộ lịch sử phát triển; các thay đổi được sao chép từ kho này sang kho khác. Những thay đổi này được nhập vào như các nhánh phát triển bổ sung và có thể được gộp lại theo cách giống như một nhánh được phát triển cục bộ.
; Tương thích với các hệ thống và giao thức hiện có: Các kho Git có thể được công bố qua Hypertext Transfer Protocol Secure (HTTPS), Hypertext Transfer Protocol (HTTP), File Transfer Protocol (FTP), hoặc giao thức Git chạy trên socket thuần hoặc trên Secure Shell (ssh). Git cũng có một chế độ giả lập máy chủ CVS, cho phép sử dụng các client CVS và plugin môi trường phát triển hiện có để truy cập các kho Git. Các kho Subversion có thể được sử dụng trực tiếp thông qua git-svn.
; Xử lý hiệu quả các dự án lớn: orvalds mô tả Git là "rất nhanh và có khả năng mở rộng tốt", và các bài kiểm tra hiệu năng do Mozilla thực hiện cho thấy Git nhanh hơn khoảng một bậc độ lớn so với Mercurial và GNU Bazaar trong việc phân biệt các kho lớn; việc nạp lịch sử phiên bản từ một kho lưu trữ cục bộ có thể nhanh hơn tới một trăm lần so với lấy từ máy chủ từ xa.
; Xác thực lịch sử bằng mật mã: Lịch sử trong Git được lưu trữ theo cách mà ID của một phiên bản cụ thể (một *commit* theo thuật ngữ Git) phụ thuộc vào toàn bộ lịch sử phát triển dẫn tới commit đó. Khi đã được công bố, không thể thay đổi các phiên bản cũ mà không bị phát hiện. Cấu trúc này tương tự như một cây Merkle, nhưng có thêm dữ liệu tại các nút và lá. (Mercurial và Monotone cũng có đặc điểm này.)
; Thiết kế dựa trên bộ công cụ: Git được thiết kế như một tập hợp các chương trình viết bằng C cùng với một số shell script đóng vai trò "wrapper" bao quanh các chương trình đó. Mặc dù phần lớn các script này sau đó đã được viết lại bằng C để tăng tốc độ và khả năng di chuyển, thiết kế theo kiểu bộ công cụ vẫn được giữ lại, và việc xâu chuỗi các thành phần lại với nhau rất dễ dàng
; Chiến lược gộp có thể thay thế: Là một phần của thiết kế dạng toolkit, Git có một mô hình được định nghĩa rõ ràng cho một trạng thái gộp chưa hoàn tất, và có nhiều thuật toán khác nhau để hoàn tất việc gộp đó, cuối cùng nếu không xử lý tự động được sẽ thông báo cho người dùng rằng cần chỉnh sửa thủ công.
; Rác tích tụ cho đến khi được gom dọn: Việc hủy bỏ thao tác hoặc quay lại các thay đổi sẽ để lại những đối tượng "bị treo" (*dangling objects*) không còn hữu ích trong cơ sở dữ liệu. Về tổng thể, chúng chỉ chiếm một phần nhỏ trong lịch sử ngày càng lớn của các đối tượng cần giữ lại. Git sẽ tự động thực hiện các các bãi rác khi đủ nhiều đối tượng "rời rạc" (loose objects) được tạo ra trong kho. Người dùng cũng có thể gọi việc thu gom rác một cách tường minh bằng lệnh `git gc`.
; Đóng gói đối tượng định kỳ: Git lưu mỗi đối tượng mới được tạo như một tệp riêng. Mặc dù mỗi tệp được nén riêng lẻ, điều này vẫn chiếm nhiều không gian và không hiệu quả. Vấn đề được giải quyết bằng cách sử dụng các *pack* – gom rất nhiều đối tượng lại, nén delta lẫn nhau trong một tệp (hoặc một luồng byte trên mạng) gọi là *packfile*. Các pack được nén dựa trên heuristics rằng những tệp cùng tên thường giống nhau, nhưng không phụ thuộc vào điều này để đảm bảo tính đúng đắn. Một tệp chỉ mục (index) tương ứng được tạo cho mỗi packfile, ghi lại vị trí (offset) của từng đối tượng trong packfile. Các đối tượng mới được tạo (gắn với lịch sử mới) vẫn được lưu ở dạng tách rời, và cần đóng gói lại định kỳ để duy trì hiệu quả về dung lượng. Quá trình đóng gói kho có thể rất tốn tài nguyên tính toán. Bằng cách cho phép đối tượng tồn tại ban đầu ở dạng "lỏng" (loose) nhưng tạo ra nhanh chóng, Git cho phép hoãn thao tác pack tốn kém sang lúc khác, khi thời gian không còn quá quan trọng, ví dụ cuối ngày làm việc. Git thực hiện repack định kỳ tự động, nhưng cũng có thể repack thủ công bằng lệnh `git gc` command. Để đảm bảo toàn vẹn dữ liệu, cả packfile và index của nó đều chứa một checksum SHA-1, và tên tệp của packfile cũng chứa một checksum SHA-1. Để kiểm tra tính toàn vẹn của một kho, dùng lệnh `git fsck`.

:Một đặc tính khác của Git là nó chụp snapshot cây thư mục các tệp. Các hệ thống theo dõi phiên bản sớm nhất như SCCS (Source Code Control System) và RCS (Revision Control System) làm việc trên từng tệp riêng lẻ và nhấn mạnh việc tiết kiệm không gian bằng interleaved deltas (SCCS) hoặc mã hóa delta (RCS) giữa các phiên bản (thường rất giống nhau). Các hệ thống sau này vẫn giữ khái niệm "một tệp có một danh tính xuyên suốt nhiều phiên bản". Tuy nhiên, Torvalds đã bác bỏ khái niệm này.Do đó, Git không ghi nhận rõ ràng quan hệ giữa các phiên bản tệp ở bất kỳ mức độ nào bên dưới cây mã nguồn.

#### Hạn chế
Những quan hệ phiên bản ngầm này dẫn tới một số hệ quả đáng kể:
* Việc xem lịch sử thay đổi của một tệp tốn chi phí hơn một chút so với xem lịch sử của cả dự án. Để có lịch sử các thay đổi ảnh hưởng tới một tệp, Git phải duyệt toàn bộ lịch sử toàn cục rồi kiểm tra xem mỗi thay đổi có sửa tệp đó hay không. Tuy nhiên, cách duyệt lịch sử này cho phép Git tạo ra, với hiệu quả tương đương, một lịch sử duy nhất cho bất kỳ tập tệp nào. Ví dụ, một thư mục con của cây mã nguồn cộng với một tệp header dùng chung toàn cục là một trường hợp rất phổ biến.
* Việc đổi tên được xử lý một cách ngầm chứ không ghi rõ ràng. Một phàn nàn thường gặp với CVS là nó sử dụng tên tệp để nhận diện lịch sử phiên bản; do đó, việc di chuyển hoặc đổi tên tệp không thể thực hiện được mà không: hoặc là cắt đứt lịch sử, hoặc là "đổi tên lịch sử", từ đó làm lịch sử không còn chính xác. Hầu hết các hệ thống quản lý phiên bản sau CVS giải quyết vấn đề này bằng cách gán cho mỗi tệp một tên định danh dài hạn (tương tự số inode) sống sót qua việc đổi tên. Git không lưu lại loại định danh này, và điều đó được coi là một ưu điểm. Các tệp mã nguồn đôi khi bị tách nhỏ, gộp lại, hoặc đơn giản là đổi tên, và nếu ghi nhận chúng chỉ như một lần đổi tên thì sẽ "đóng băng" một mô tả không chính xác về những gì thực sự đã xảy ra trong lịch sử (vốn là bất biến). Git giải quyết vấn đề bằng cách phát hiện đổi tên khi duyệt lịch sử snapshot, chứ không ghi nhận lúc tạo snapshot. (Tóm laị, với một tệp trong phiên bản *N*, thì tệp cùng tên trong phiên bản *N*&nbsp;−&nbsp;1 là tổ tiên mặc định của nó. Tuy nhiên, nếu không có tệp cùng tên trong *N*&nbsp;−&nbsp;1, Git sẽ tìm một tệp chỉ tồn tại trong *N*&nbsp;−&nbsp;1 và rất giống với tệp mới.) Cơ chế này đòi hỏi tốn CPU hơn mỗi khi xem lịch sử, và có nhiều tùy chọn để tinh chỉnh heuristics. Cơ chế này không phải lúc nào cũng chính xác; đôi khi một tệp được đổi tên đồng thời với việc chỉnh sửa trong cùng một commit sẽ bị hiểu nhầm là xóa tệp cũ và tạo tệp mới. Lập trình viên có thể "lách" hạn chế này bằng cách commit thao tác đổi tên và phần thay đổi nội dung thành hai commit riêng.

## Các bản triển khai

Git (bản triển khai chính viết bằng C) chủ yếu được phát triển trên Linux, mặc dù nó cũng hỗ trợ hầu hết các hệ điều hành lớn khác, bao gồm các hệ điều hành BDS (DragonFly BSD, FreeBSD, NetBSD, và OpenBSD), Solaris, macOS, và Windows.

Bản port đầu tên của Git lên Windows chủ yếu dựa trên một framework] mô phỏng Linux, dùng để chạy bản Git dành cho Linux. Khi cài Git trên Windows, hệ thống sẽ tạo một thư mục trong Program Files với tên gần giống, chứa bản port Mingw-w64 của GNU Compiler Collection, Perl 5, MSYS2 (bản fork của Cygwin – một môi trường mô phỏng kiểu Unix trên Windows) và nhiều bản port hoặc lớp mô phỏng khác của các tiện ích và thư viện Linux cho Windows. Hiện nay, các bản dựng Git "native" cho Windows được phân phối dưới dạng bộ cài 32-bit và 64-bit. Trang web chính thức của Git hiện vẫn duy trì một bản Git dành cho Windows, tiếp tục sử dụng môi trường MSYS2.

*JGit* là một bản triển khai Git dưới dạng thư viện phần mềm thuần Java, được thiết kế để nhúng vào bất kỳ ứng dụng Java nào. JGit được sử dụng trong công cụ review mã Gerrit, và trong EGit – một client Git dành cho môi trường phát triển Eclipse.

*Go-git* là một bản triển khai Git mã nguồn mở, viết hoàn toàn bằng Go. Hiện nó đang được dùng làm nền cho các dự án như cung cấp giao diện SQL cho các kho mã Git và cung cấp khả năng mã hóa cho Git.

*Dulwich* là một bản triển khai Git viết hoàn toàn bằng Python, hỗ trợ CPython 3.6 trở lên và PyPy.

*Llibgit2* là một bản triển khai Git dưới dạng thư viện phần mềm ANSI C không có phụ thuộc nào khác, có thể biên dịch trên nhiều nền tảng, bao gồm Windows, Linux, macOS và BSD. Thư viện này có binding cho nhiều ngôn ngữ lập trình, bao gồm Ruby, Python, và Haskell.

*JS-Git* là một bản triển khai JavaScript của một tập con chức năng của Git.

*Game of Trees* là một bản triển khai Git mã nguồn mở dành cho dự án OpenBSD.

git9 là một bản triển khai Git độc lập cho hệ điều hành Plan 9, sử dụng các lớp trừu tượng gốc của hệ thống này.
## Lịch sử phát triển

## Phần mềm hỗ trợ

Có nhiều website và phần mềm cho phép lưu trữ (miễn phí và có phí) Git.

* BerliOS
* GitHub
* GitLab
* Gitorious
* Sourceforge
* GNU Savannah
* GitEnterprise

## Tham khảo

## Nguồn
*

## Liên kết ngoài

* 
* Git Magic – một quyển sách về Git đã được dịch ra tiếng Việt.
*  Git Community Book – nơi có thể tìm thấy các tài liệu hướng dẫn