Trước khi đi sâu vào Git, chúng ta cần hiểu rõ khái niệm kiểm soát phiên bản.
Kiểm soát Phiên bản
Kiểm soát phiên bản (Revision control) là một kỹ thuật trong kỹ thuật phần mềm dùng để quản lý lịch sử thay đổi của các tệp, thư mục hoặc dự án trong quá trình phát triển. Nó giúp dễ dàng xem lại lịch sử thay đổi, sao lưu và khôi phục các phiên bản trước đó.
- Hỗ trợ phát triển cộng tác đa người dùng trên nhiều khu vực địa lý.
- Theo dõi và ghi lại lịch sử của một hoặc nhiều tệp.
- Tổ chức và bảo vệ mã nguồn cũng như tài liệu.
- Thống kê khối lượng công việc.
- Phát triển song song, nâng cao hiệu quả làm việc.
- Theo dõi toàn bộ quá trình phát triển phần mềm.
- Giảm tải cho nhà phát triển, tiết kiệm thời gian và giảm thiểu lỗi do con người.
Nói một cách đơn giản, đó là công nghệ dùng để quản lý các dự án phát triển cộng tác.
Nếu không có kiểm soát phiên bản hoặc quy trình quản lý không đúng đắn, việc phát triển phần mềm sẽ gặp nhiều vấn đề như tính nhất quán của mã nguồn, sự dư thừa dữ liệu, tính giao dịch, tính đồng thời, bảo mật mã nguồn và tích hợp dự án.
Các công cụ kiểm soát phiên bản phổ biến
Các công cụ kiểm soát phiên bản phổ biến bao gồm:
- Git
- SVN (Subversion)
- CVS (Concurrent Versions System)
- VSS (Microsoft Visual SourceSafe)
- TFS (Team Foundation Server)
- Visual Studio Online
Phân loại Kiểm soát Phiên bản
1. Kiểm soát Phiên bản Cục bộ (Local Version Control)
Lưu trữ mọi thay đổi của tệp, cho phép tạo các "ảnh chụp nhanh" (snapshot) hoặc ghi lại các tệp vá lỗi. Phù hợp cho cá nhân, ví dụ: RCS.
2. Kiểm soát Phiên bản Tập trung (Centralized Version Control) - Đại diện: SVN
Tất cả dữ liệu phiên bản được lưu trữ trên máy chủ. Các nhà phát triển cộng tác đồng bộ hóa hoặc tải lên các thay đổi của họ từ máy chủ. Khi không kết nối mạng, người dùng không thể xem lịch sử phiên bản, chuyển đổi giữa các phiên bản để kiểm tra hoặc làm việc trên các nhánh khác nhau. Hơn nữa, việc lưu trữ tất cả dữ liệu trên một máy chủ duy nhất có rủi ro cao bị hỏng, dẫn đến mất toàn bộ dữ liệu (mặc dù có thể sao lưu định kỳ). Ví dụ tiêu biểu: SVN, CVS, VSS.
3. Kiểm soát Phiên bản Phân tán (Distributed Version Control) - Git
Toàn bộ kho lưu trữ thông tin phiên bản được đồng bộ hóa về máy cục bộ của mỗi người dùng. Điều này cho phép xem toàn bộ lịch sử phiên bản cục bộ, commit ngay cả khi ngoại tuyến và chỉ cần push lên máy chủ hoặc gửi cho người dùng khác khi có kết nối mạng. Vì mỗi người dùng đều giữ bản sao đầy đủ của dữ liệu, chỉ cần một thiết bị của người dùng không gặp sự cố là có thể khôi phục toàn bộ dữ liệu. Tuy nhiên, điều này cũng làm tăng dung lượng lưu trữ cục bộ.
Không có tình trạng không làm việc được do hỏng máy chủ hoặc các vấn đề về mạng!
Điểm khác biệt chính giữa Git và SVN
SVN là hệ thống kiểm soát phiên bản tập trung, kho lưu trữ được đặt tại máy chủ trung tâm. Khi làm việc, bạn cần lấy phiên bản mới nhất từ máy chủ, thực hiện công việc và đẩy những thay đổi đã hoàn thành lên máy chủ. Hệ thống này yêu cầu kết nối mạng để hoạt động và đòi hỏi băng thông cao.
Git là hệ thống kiểm soát phiên bản phân tán, không có máy chủ trung tâm. Mỗi máy tính của mỗi người dùng là một kho lưu trữ đầy đủ. Bạn có thể làm việc mà không cần kết nối mạng vì tất cả các phiên bản đều nằm trên máy tính của bạn. Phương pháp cộng tác là: khi bạn sửa đổi tệp A trên máy tính của mình, và người khác cũng sửa đổi tệp A trên máy tính của họ, bạn chỉ cần đẩy các thay đổi của mình cho nhau và có thể xem được sửa đổi của đối phương. Git cho phép xem trực tiếp những mã nguồn và tệp nào đã được cập nhật!
Git là hệ thống kiểm soát phiên bản phân tán tiên tiến nhất thế giới hiện nay.
Lịch sử của Git
Giống như nhiều điều vĩ đại khác trong cuộc sống, Git ra đời trong một thời kỳ đầy biến động và đổi mới. Dự án mã nguồn mở nhân Linux có vô số người đóng góp. Phần lớn công việc bảo trì nhân Linux trước đây đều tốn thời gian cho việc gửi các bản vá và lưu trữ các tệp lưu trữ (từ năm 1991-2002). Đến năm 2002, toàn bộ nhóm dự án bắt đầu sử dụng hệ thống kiểm soát phiên bản phân tán độc quyền BitKeeper để quản lý và bảo trì mã nguồn.
Trong cộng đồng Linux có rất nhiều "lão làng"! Họ đã nghiên cứu và bẻ khóa BitKeeper!
Đến năm 2005, mối quan hệ hợp tác giữa công ty thương mại phát triển BitKeeper và cộng đồng mã nguồn mở nhân Linux kết thúc. Họ đã thu hồi quyền sử dụng BitKeeper miễn phí của cộng đồng Linux. Điều này buộc cộng đồng mã nguồn mở Linux (đặc biệt là Linus Torvalds, người tạo ra Linux) phải phát triển hệ thống phiên bản của riêng mình dựa trên kinh nghiệm học được khi sử dụng BitKeeper (chỉ trong khoảng 2 tuần!). Đó chính là Git sau này!
Git là hệ thống kiểm soát phiên bản phân tán tiên tiến nhất thế giới.
Git là miễn phí, mã nguồn mở, ban đầu được phát triển để hỗ trợ việc phát triển nhân Linux, thay thế cho BitKeeper!
Cha đẻ của Linux và Git là Linus Torvalds (sinh năm 1969 tại Phần Lan).
Cấu hình Môi trường Git
Truy cập trang chủ Git, tải phiên bản Git tương ứng với hệ điều hành của bạn.
Nếu tải chậm, bạn có thể tìm kiếm các bản mirror!
Để tải nhanh hơn trang chủ, bạn có thể sử dụng bản mirror của Taobao: http://npm.taobao.org/mirrors/git-for-windows/
Gỡ cài đặt
Thực hiện gỡ cài đặt trực tiếp và sau đó dọn dẹp biến môi trường.
Tải xuống phiên bản tương ứng và cài đặt! Quá trình cài đặt thường chỉ cần nhấn "Next" liên tục.
Khởi động Git
Sau khi cài đặt thành công, bạn sẽ thấy mục Git trong menu Start. Có 3 chương trình: Git Bash, Git CMD và Git GUI. Bạn cũng có thể thấy các chương trình tương ứng bằng cách nhấp chuột phải vào bất kỳ thư mục nào.
- Git Bash: Giao diện dòng lệnh theo phong cách Unix/Linux, được sử dụng và khuyến nghị nhiều nhất.
- Git CMD: Giao diện dòng lệnh theo phong cách Windows.
- Git GUI: Giao diện đồ họa của Git, không khuyến khích cho người mới bắt đầu. Nên làm quen với các lệnh thông dụng trước.
Học các Lệnh Linux Cơ bản
cd: Thay đổi thư mục.cd ..: Quay lại thư mục trước đó.cdđơn giản sẽ vào thư mục mặc định.pwd: Hiển thị đường dẫn thư mục hiện tại.ls(hoặcll): Liệt kê tất cả các tệp trong thư mục hiện tại.ll(hai lần 'l') hiển thị chi tiết hơn.touch: Tạo một tệp mới. Ví dụ:touch index.jssẽ tạo tệpindex.jstrong thư mục hiện tại.rm: Xóa một tệp. Ví dụ:rm index.jssẽ xóa tệpindex.js.mkdir: Tạo một thư mục mới (tạo một thư mục).rm -r: Xóa một thư mục. Ví dụ:rm -r srcsẽ xóa thư mụcsrc.mv: Di chuyển tệp. Ví dụ:mv index.html srcsẽ di chuyển tệpindex.htmlđến thư mụcsrc. Cả tệp và thư mục đích phải nằm trong cùng một thư mục.reset: Khởi tạo lại Terminal / Xóa màn hình.clear: Xóa màn hình.history: Xem lịch sử các lệnh đã sử dụng.help: Xem trợ giúp.exit: Thoát.#: Biểu thị chú thích.
Cấu hình Git
Tất cả các tệp cấu hình đều được lưu trữ cục bộ.
Xem cấu hình: git config -l
Xem cấu hình ở các cấp độ khác nhau:
# Xem cấu hình hệ thống
git config --system --list
# Xem cấu hình người dùng hiện tại (global)
git config --global --list
Các tệp cấu hình liên quan đến Git:
Git\etc\gitconfig: Tệpgitconfigtrong thư mục cài đặt Git --system (cấp hệ thống).C:\Users\Lenovo\.gitconfig: Chỉ áp dụng cho người dùng đã đăng nhập --global (toàn cục).
Bạn có thể chỉnh sửa trực tiếp các tệp này, hoặc thiết lập thông qua lệnh sẽ được phản ánh vào đây.
Thiết lập Tên người dùng và Email (Định danh người dùng, bắt buộc)
Sau khi cài đặt Git, việc đầu tiên bạn cần làm là thiết lập tên người dùng và địa chỉ email. Điều này rất quan trọng vì mỗi lần Git commit sẽ sử dụng thông tin này và nó sẽ được nhúng vĩnh viễn vào commit của bạn:
git config --global user.name "ten_cua_ban" # Tên
git config --global user.email "email_cua_ban@example.com" # Email
Bạn chỉ cần thực hiện thiết lập này một lần. Nếu bạn thêm tùy chọn --global, Git sẽ luôn sử dụng thông tin này cho mọi thao tác bạn thực hiện trên hệ thống. Nếu bạn muốn sử dụng tên hoặc email khác cho một dự án cụ thể, bạn có thể chạy lệnh này trong thư mục dự án đó mà không cần tùy chọn --global. Nói tóm lại, --global là cấu hình toàn cục, không có nó là cấu hình riêng cho từng dự án.
Lý thuyết Cơ bản về Git (Cốt lõi)
Khu vực làm việc
Có ba khu vực làm việc cục bộ trong Git: Thư mục làm việc (Working Directory), Khu vực tạm (Stage/Index) và Kho lưu trữ (Repository hoặc Git Directory). Nếu thêm kho lưu trữ từ xa (Remote Directory), chúng ta có thể chia thành bốn khu vực làm việc.
Mối quan hệ chuyển đổi giữa các tệp trong bốn khu vực này như sau:
- Workspace: Khu vực làm việc, nơi bạn lưu trữ mã nguồn dự án của mình.
- Index / Stage: Khu vực tạm, dùng để lưu trữ tạm thời các thay đổi của bạn. Về cơ bản, nó chỉ là một tệp lưu trữ danh sách các tệp sẽ được commit.
- Repository: Kho lưu trữ (hoặc kho lưu trữ cục bộ), nơi lưu trữ an toàn dữ liệu. Nó chứa tất cả các phiên bản bạn đã commit. HEAD trỏ đến phiên bản mới nhất được đưa vào kho lưu trữ.
- Remote: Kho lưu trữ từ xa, máy chủ lưu trữ mã nguồn. Bạn có thể coi nó đơn giản là một máy tính trong nhóm dự án của bạn dùng để trao đổi dữ liệu từ xa.
Ba khu vực cục bộ chính xác hơn là phiên bản mà HEAD trỏ tới trong kho lưu trữ Git:
- Directory: Một thư mục được quản lý bởi Git, tức là một kho lưu trữ, bao gồm không gian làm việc và không gian quản lý của Git.
- WorkSpace: Các thư mục và tệp cần được kiểm soát phiên bản bởi Git. Các thư mục và tệp này tạo thành không gian làm việc.
- .git: Thư mục chứa thông tin quản lý của Git, được tạo tự động khi khởi tạo kho lưu trữ.
- Index/Stage: Khu vực tạm, hoặc khu vực chờ commit, nơi bạn có thể đặt tất cả các thay đổi trước khi commit vào kho lưu trữ.
- Local Repo: Kho lưu trữ cục bộ, một kho lưu trữ phiên bản được lưu trữ cục bộ. HEAD trỏ đến nhánh phát triển (branch) hiện tại.
- Stash: Ẩn, là một ngăn xếp lưu trạng thái làm việc, dùng để lưu/khôi phục trạng thái tạm thời trong Workspace.
Quy trình làm việc
Quy trình làm việc thông thường của Git như sau:
- Thêm/sửa đổi tệp trong thư mục làm việc.
- Đưa các tệp cần quản lý phiên bản vào khu vực tạm.
- Commit các tệp từ khu vực tạm vào kho lưu trữ Git.
Do đó, tệp được Git quản lý có ba trạng thái: đã sửa đổi (modified), đã tạm (staged), đã commit (committed).
Thiết lập Dự án Git
Tạo Thư mục làm việc và các Lệnh thường dùng
Thư mục làm việc (WorkSpace) thường là thư mục bạn muốn Git quản lý. Nó có thể là thư mục dự án của bạn hoặc một thư mục trống. Nên tránh tên có tiếng Việt. Trong sử dụng hàng ngày, bạn chỉ cần nhớ 6 lệnh sau:

Thiết lập Kho lưu trữ Cục bộ
Có hai cách để tạo kho lưu trữ cục bộ: tạo kho lưu trữ hoàn toàn mới hoặc clone từ kho lưu trữ từ xa.
1. Tạo kho lưu trữ hoàn toàn mới, thực hiện trong thư mục gốc của dự án bạn muốn Git quản lý:
# Tạo một kho mã Git mới trong thư mục hiện tại
$ git init
2. Sau khi thực hiện, bạn sẽ thấy một thư mục .git mới xuất hiện trong thư mục dự án. Tất cả thông tin về phiên bản đều nằm trong thư mục này.
Clone Kho lưu trữ từ xa
1. Một cách khác là clone kho lưu trữ từ xa. Vì nó sẽ tạo một bản sao gương hoàn chỉnh của kho lưu trữ từ máy chủ từ xa về máy cục bộ!
# Clone một dự án và toàn bộ lịch sử mã nguồn (thông tin phiên bản)
$ git clone [url] https://gitee.com/kuangstudy/openclass.git
2. Hãy thử clone một dự án thử nghiệm từ Gitee hoặc Github!
Thao tác Tệp Git
4 trạng thái của Tệp
Kiểm soát phiên bản là kiểm soát phiên bản của tệp. Để thực hiện các thao tác như sửa đổi, commit tệp, trước tiên bạn cần biết trạng thái hiện tại của tệp, nếu không bạn có thể commit nhầm tệp bạn không muốn hoặc không commit được tệp bạn muốn.
- Untracked: Chưa được theo dõi. Tệp này có trong thư mục nhưng chưa được thêm vào kho Git, không tham gia vào kiểm soát phiên bản. Trạng thái sẽ chuyển thành Staged sau khi thực hiện
git add. - Unmodify: Tệp đã được đưa vào kho, chưa sửa đổi. Nội dung của tệp trong kho lưu trữ và trong thư mục hoàn toàn giống nhau. Loại tệp này có hai hướng đi: nếu bị sửa đổi, nó sẽ trở thành Modified. Nếu bị xóa khỏi kho bằng
git rm, nó sẽ trở thành tệp Untracked. - Modified: Tệp đã bị sửa đổi, chỉ đơn thuần là sửa đổi mà chưa thực hiện thao tác nào khác. Tệp này cũng có hai hướng đi: có thể được đưa vào khu vực tạm staged bằng cách thực hiện
git add. Nếu sử dụnggit checkout, nó sẽ bỏ qua các thay đổi và quay lại trạng thái unmodify. Lệnhgit checkoutnày sẽ lấy tệp từ kho lưu trữ và ghi đè lên các thay đổi hiện tại! - Staged: Trạng thái tạm. Thực hiện
git commitsẽ đồng bộ hóa các thay đổi vào kho lưu trữ. Lúc này, tệp trong kho và tệp cục bộ sẽ lại giống nhau, trạng thái tệp là Unmodify. Thực hiệngit reset HEAD filenameđể hủy tạm, trạng thái tệp sẽ là Modified.
Xem Trạng thái Tệp
Như đã nói ở trên, tệp có 4 trạng thái. Bạn có thể xem trạng thái của tệp bằng lệnh sau:
# Xem trạng thái của một tệp cụ thể
git status [tên_tệp]
# Xem trạng thái của tất cả các tệp
git status
# git add . Thêm tất cả các tệp vào khu vực tạm
# git commit -m "Nội dung thông báo" Commit nội dung từ khu vực tạm vào kho lưu trữ cục bộ -m Thông tin commit
Bỏ qua Tệp (Ignore Files)
Đôi khi, chúng ta không muốn đưa một số tệp vào kiểm soát phiên bản, ví dụ: tệp cơ sở dữ liệu, tệp tạm thời, tệp thiết kế, v.v. Hãy tạo một tệp .gitignore trong thư mục chính. Tệp này có các quy tắc sau:
- Các dòng trống hoặc bắt đầu bằng dấu thăng (
#) trong tệp sẽ bị bỏ qua. - Có thể sử dụng ký tự đại diện của Linux. Ví dụ: dấu sao (
*) đại diện cho nhiều ký tự tùy ý, dấu hỏi (?) đại diện cho một ký tự, dấu ngoặc vuông ([abc]) đại diện cho một dải ký tự tùy chọn, dấu ngoặc nhọn ({string1,string2,.…}) đại diện cho các chuỗi tùy chọn, v.v. - Nếu tên bắt đầu bằng dấu chấm than (
!), nó biểu thị quy tắc ngoại lệ và sẽ không bị bỏ qua. - Nếu tên bắt đầu bằng dấu phân cách đường dẫn (
/), nó biểu thị tệp cần bỏ qua nằm trong thư mục này, các tệp trong thư mục con sẽ không bị bỏ qua. - Nếu tên kết thúc bằng dấu phân cách đường dẫn (
/), nó biểu thị cần bỏ qua thư mục con có tên đó trong thư mục này, chứ không phải tệp (mặc định bỏ qua cả tệp và thư mục).
# Đây là chú thích
*.txt # Bỏ qua tất cả các tệp có đuôi .txt
!lib.txt # Ngoại trừ tệp lib.txt
/temp # Chỉ bỏ qua tệp TODO trong thư mục gốc của dự án, không bao gồm thư mục temp ở các cấp khác
build/ # Bỏ qua tất cả các tệp trong thư mục build/
doc/*.txt # Sẽ bỏ qua doc/notes.txt nhưng không bao gồm doc.server/arch.txt
Sử dụng Gitee
GitHub có tường lửa và khá chậm. Ở Việt Nam, chúng ta thường sử dụng Gitee. Đôi khi công ty sẽ tự xây dựng máy chủ GitLab.
- Đăng ký và đăng nhập Gitee, hoàn thiện thông tin cá nhân.
- Thiết lập khóa SSH công khai cho máy cục bộ để đăng nhập không cần mật khẩu! (Đăng nhập không cần mật khẩu là bước khá quan trọng. Gitee là kho lưu trữ từ xa, chúng ta làm việc trên kho lưu trữ cục bộ).
# Vào thư mục C:\Users\Administrator\.ssh
# Tạo khóa công khai
ssh-keygen
3. Thêm thông tin khóa công khai (public key) vào tài khoản Gitee của bạn!
4. Sử dụng Gitee để tạo kho lưu trữ của riêng bạn!
Giấy phép: Có được phép sao chép tùy ý không? Mã nguồn mở nhưng không được sử dụng thương mại, không được sao chép, v.v. tùy thuộc vào giới hạn!
Clone về máy cục bộ.
Tích hợp Git trong IDEA
1. Tạo dự án, ràng buộc Git
- Chỉ cần sao chép thư mục Git của kho lưu trữ từ xa vào dự án của bạn!
- Lưu ý quan sát những thay đổi trong IDEA.
2. Sửa đổi tệp, sử dụng IDEA để thao tác Git
- Thêm vào khu vực tạm.
- Commit.
- Push lên kho lưu trữ từ xa.
3. Kiểm tra Commit
Đây là các thao tác của một người dùng.
Nhánh (Branch) trong GIT
Nhánh trong Git tương đối khó hiểu. Nhánh giống như vũ trụ song song trong phim khoa học viễn tưởng. Nếu hai vũ trụ song song không ảnh hưởng lẫn nhau thì sẽ không có vấn đề gì với sự phát triển hiện tại. Tuy nhiên, khi hai vũ trụ song song hợp nhất tại một thời điểm, chúng ta sẽ cần xử lý một số vấn đề!
Các lệnh thường dùng trong nhánh Git:
# Liệt kê tất cả các nhánh cục bộ
git branch
# Liệt kê tất cả các nhánh từ xa
git branch -r
# Tạo một nhánh mới, nhưng vẫn ở lại nhánh hiện tại
git branch [tên_nhánh]
# Tạo một nhánh mới và chuyển sang nhánh đó
git checkout -b [nhánh]
# Hợp nhất nhánh được chỉ định vào nhánh hiện tại
$ git merge [nhánh]
# Xóa nhánh
$ git branch -d [tên_nhánh]
# Xóa nhánh từ xa
$ git push origin --delete [tên_nhánh]
$ git branch -dr [remote/branch]
Nếu nhiều nhánh thực thi song song, sẽ dẫn đến việc mã nguồn của chúng ta không xung đột, tức là tồn tại nhiều phiên bản cùng lúc!
web-api - A
web-admin - B sẽ gọi A
web-app - C sẽ gọi mã của B và A
Nếu xảy ra xung đột, chúng ta cần thảo luận để giải quyết!
Nếu cùng một tệp bị sửa đổi trong quá trình hợp nhất các nhánh, nó sẽ gây ra xung đột. Cách giải quyết là chúng ta có thể sửa đổi tệp xung đột và commit lại! Chọn giữ mã của họ hay mã của bạn!
Nhánh master chính nên rất ổn định, dùng để phát hành phiên bản mới. Thông thường không được phép làm việc trực tiếp trên đó. Công việc thường được thực hiện trên nhánh dev mới tạo. Sau khi hoàn thành công việc, ví dụ: chuẩn bị phát hành, hoặc mã trong nhánh dev đã ổn định, nó có thể được hợp nhất vào nhánh chính master.