Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Git Checkout, một lệnh quan trọng với nhiều chức năng trong Git như chuyển đổi nhánh, chuyển đổi tag, hoàn tác,… cùng các lệnh Git thay thế cho một vài trường hợp.

Đọc bài viết này để hiểu rõ hơn về:

  • Git checkout là gì?
  • Các trường hợp sử dụng Git checkout
  • Các lỗi thường gặp khi sử dụng Git checkout

Git là gì?

Git là một hệ thống quản lý phiên bản phân tán mạnh mẽ, giúp hỗ trợ quản lý mã nguồn một cách hiệu quả. Git lần đầu được ra mắt vào năm 2005 bởi Linus Torvalds. Git thường được sử dụng kết hợp với các dịch vụ lưu trữ mã nguồn từ xa như Github, Gitlab hay Bitbucket để hỗ trợ cộng tác từ xa, nâng cao chất lượng làm việc nhóm trong dự án.

Git đóng một vai trò quan trọng trong xuyên suốt quá trình làm việc của các lập trình viên, những chức năng nổi bật của Git phải kể đến:

  • Theo dõi lịch sử thay đổi của mã nguồn
  • Hợp nhất thay đổi từ nhiều nguồn
  • Lưu trữ và chia sẻ mã nguồn
  • So sánh sự thay đổi trong phiên bản

Đọc thêm các bài viết tổng quan về Git:

Git Checkout là gì?

Git branch là một sự thay đổi đáng kể của Git so với quy trình làm việc truyền thống của Subversion (SVN). Việc có những nhánh riêng giúp dễ dàng thử nghiệm những ý tưởng mới mà không sợ làm hỏng chức năng hiện có và cho phép làm việc trên nhiều tính năng không liên quan cùng một lúc. Ngoài ra, các nhánh còn hỗ trợ nhiều quy trình làm việc cộng tác.

Lệnh git checkout cho phép bạn di chuyển giữa các branch (nhánh) trong Git. Khi bạn checkout một nhánh, các tập tin trong thư mục làm việc sẽ được cập nhật để khớp với phiên bản được lưu trữ trong nhánh đó và Git sẽ ghi lại tất cả các commit mới trên nhánh đó. Hãy xem nó như là một cách để chọn dòng phát triển mà bạn đang làm việc.

Ngoài tính năng chính là chuyển đổi trạng thái làm việc giữa các nhánh, Git Checkout còn được sử dụng trong một số trường hợp khác như sau.

Các trường hợp sử dụng Git Checkout kèm ví dụ chi tiết

Chuyển đổi nhánh nội bộ và nhánh từ xa

Sử dụng Git Checkout để chuyển đổi trạng thái làm việc từ nhánh này sang nhánh khác, bạn sử dụng cú pháp sau:

git checkout <tên nhánh>

Điều này sẽ đưa HEAD (*) đến commit của cùng của nhánh được chuyển đến.

(*) HEAD là tham chiếu đặc biệt trỏ đến commit hiện tại, nó thể hiện trạng thái tập tin đang được làm việc.

Trường hợp muốn chuyển sang một nhánh từ kho lưu trữ từ xa, bạn có thể thực hiện theo các bước sau:

Lấy nội dung của nhánh trên kho lưu trữ từ xa

git fetch --all

Sau đó, sử dụng git checkout đến nhánh từ xa như một nhánh cục bộ

git checkout <nhánh remote>

Ví dụ, bạn đang làm việc trên nhánh develop, bây giờ bạn muốn chuyển sang nhánh main, hãy thực hiện lệnh sau:

git checkout main

Kể từ phiên bản 2.23, Git đã bổ sung thêm lệnh switch để tách biệt chức năng chuyển đổi nhánh với git checkout:

git switch <tên nhánh>

Tạo và chuyển sang nhánh mới

Thông thường khi cần tạo một nhánh mới, chúng ta có thể sử dụng lệnh git branch, và sử dụng git checkout khi muốn chuyển sang làm việc ở nhánh đó.

Ở trường hợp này, chúng ta có thể sử dụng tùy chọn -b với git checkout để thực hiện đồng thời hai công việc này:

git checkout -b <tên nhánh>

Ví dụ để tạo và chuyển sang làm việc trên nhánh feat/user, ta sử dụng cú pháp sau:

git checkout -b feat/user

Chuyển sang các tag

Tag trong git là một cách để đánh dấu các vị trí cụ thể trong lịch sử commit. Nó thường được sử dụng để lưu lại các phiên bản quan trọng trong mã nguồn như phiên bản Release. Để chuyển đổi sang trạng thái của các tags, ta có thể sử dụng git checkout tương tự như khi sử dụng với các nhánh.

git checkout <tên tag>

Ví dụ, trong mã nguồn đang có các tags như v1.0, v1.1, v2.0. Để chuyển đến trạng thái của tag v1.0, ta sử dụng cú pháp sau:

git checkout v1.0

Hoàn tác các thay đổi trên tập tin

Trong quá trình làm việc trên tập tin, bạn có thể hoàn tác các thay đổi chưa được commit trên tập tin bằng cách sử dụng lệnh git checkout. Điều này nghĩa là khôi phục trạng thái của tập tin về trạng thái của commit cuối cùng.

git checkout -- <tên tập tin>

Ví dụ, để hoàn tác các thay đổi trên tập tin index.html

git checkout -- index.html

Ngoài ra, để hoàn tác nhiều tập tin, ta sử dụng cú pháp sau:

git checkout -- <tên tập tin 1> <tên tập tin 2>

Hoặc để hoàn tác trạng thái của toàn bộ tập tin trong thư mục làm việc hiện tại:

git checkout -- .

Kể từ phiên bản 2.23, Git đã bổ sung lệnh git restore để thay thế chức năng hoàn tác thay đổi này của Git. Bạn có thể sử dụng git restore để khôi phục tập tin về trạng thái trước khi thay đổi bằng cú pháp

git restore <tên tập tin>

Hoặc toàn bộ tập tin trong thư mục hiện tại:

git restore .

Detached HEAD (xem lại nội dung của một snapshot)

Detached HEAD là trường hợp HEAD không trỏ vào một nhánh cụ thể mà trỏ trực tiếp đến một commit. Điều này sẽ làm tách biệt trạng thái làm việc khỏi các nhánh, giúp bạn có thể thử nghiệm, xem lại mã nguồn, hoặc kiểm tra các thay đổi mà không làm ảnh hưởng đến nhánh nào cả.

git checkout <commit-hash>

Ví dụ, trong nhánh develop đang có 3 commit với thông tin mã định hash như sau:

git checkout - itviec blog

Để chuyển trạng thái làm việc sang commit có tên “init”, ta sử dụng cú pháp sau:

git checkout 9b1a833f0a4238f49e5775ed583ba7c55ed38832

Khôi phục hành động khi kết hợp với git reflog

Git reflog là một lệnh cực kì mạnh mẽ và hữu dụng trong Git. Khi sử dụng Git reflog, ta có thể xem lại danh sách các hoạt động đã diễn ra trong mã nguồn như thêm commit mới, xóa nhánh, tạo nhánh, xóa commit,…

git checkout - itviec blog

Kết quả từ git reflog sẽ hiển thị một danh sách các hành động gần đây của HEAD cùng với các commit hash. Chúng ta có thể sử dụng git checkout để chuyển đến trạng thái tập tin tại thời điểm cụ thể bằng cú pháp sau:

git checkout <hash>
  • Khôi phục nhánh đã bị xóa: Tìm đến dòng chứa thông tin lệnh xóa nhánh, sau đó sử dụng git checkout với commit hash trước dòng này để quay trở lại trạng thái trước khi xóa nhánh
  • Khôi phục commit bị xóa: Tìm đến dòng chứa thông tin lệnh xóa commit (ví dụ: git reset –hard HEAD~1), sau đó dùng git checkout với commit hash trước đó.

Các lỗi thường gặp khi làm việc với Git Checkout

Lỗi “pathspec … did not match any file(s) known to git”

Khi bạn sử dụng git checkout sang một nhánh hoặc một commit không tồn tại hoặc đã bị xóa trong repository, bạn sẽ nhận được một tin nhắn lỗi với nội dung có dạng như sau:

git checkout - itviec blog

Để khắc phục tình trạng này, bạn cần kiểm tra lại tên nhánh hoặc tên tag mà bạn muốn checkout đã chính xác hay chưa. Bạn có thể sử dụng:

git branch

Hoặc

git tag

để xem lại danh sách nhánh hoặc tag.

Không thể checkout do có tập tin thay đổi

Lỗi xảy ra khi bạn đang cố gắng checkout từ một nhánh làm việc đang có những thay đổi trên tập tin, tuy nhiên chúng chưa được commit. Git yêu cầu bạn phải commit hoặc lưu tạm thời (git stash) các thay đổi này trước khi chuyển nhánh để tránh xung đột mã nguồn và mất dữ liệu.

git checkout - itviec blog

Để tránh tình trạng này, bạn có thể thực hiện commit lại các thay đổi:

git add .
git commit -m "commit message"

Hoặc lưu tạm thời các thay đổi:

git stash

Lỗi Detached HEAD

Khi bạn sử dụng git checkout để chuyển đến một commit hoặc một tag cụ thể thay vì một nhánh, thì lúc này bạn đã tách biệt khỏi dòng làm việc hiện tại, không còn liên kết vào một nhánh nào. Lúc này Git sẽ cảnh báo bạn đang trong trạng thái detached HEAD.

git checkout - itviec blog

Để thoát khỏi Detached HEAD, bạn có thể chuyển về một nhánh cụ thể trong repository.

Các câu hỏi thường gặp về Git Checkout

So sánh git checkout và git switch

Git switch là một lệnh mới, được bổ sung từ phiên bản git 2.23 để thay thế nhiệm vụ chuyển đổi giữa các nhánh của git checkout. Tuy nhiên, git checkout vẫn đóng một vai trò quan trọng vì sự đa nhiệm của nó. Dưới đây là một số điểm so sánh giữa hai lệnh này:

Tiêu chí Git checkout Git switch
Chuyển đổi giữa các nhánh
Tạo nhánh mới và chuyển sang nhánh đó
Hoàn tác thay đổi của tập tin Không
Detached HEAD Không
Khả năng sử dụng Có thể bị nhầm lẫn do đa dụng Dễ sử dụng vì chỉ tập trung vào một chức năng chuyển nhánh

So sánh “git checkout — .” và “git reset HEAD –hard”

Hai cú pháp này để dùng để hoàn tác các thay đổi xảy ra trên thư mục làm việc hiện tại. Tuy nhiên giữa chúng có những khác biệt quan trọng về nguyên lý hoạt động và phạm vi ảnh hưởng.

Tiêu chí git checkout — . git reset HEAD –hard
Phạm vi ảnh hưởng Hoàn tác các thay đổi chưa được commit trong thư mục làm việc Hoàn tác mọi thay đổi trong cả thư mục làm việc và vùng staging, đồng thời loại bỏ commit sau vị trí HEAD.
Lịch sử commit Không gây ảnh hưởng đến lịch sử commit Có thể xóa bỏ commit nếu sử dụng HEAD với tùy chọn STEP
Trường hợp sử dụng Chỉ muốn hoàn tác các thay đổi đã xảy ra trên thư mục hiện tại nhưng chưa commit Muốn hoàn tác các thay đổi đã được commit vào repository.

Làm sao để chuyển trạng thái làm việc sang một nhánh từ xa?

Trước tiên, bạn cần cập nhật các nhánh từ xa về kho lưu trữ cục bộ:

git fetch -all
git branch -r # hiển thị các nhánh từ xa

Sau đó bạn có thể chuyển sang một nhánh từ xa bằng lệnh:

git checkout <tên nhánh từ xa>

Đối với các phiên bản git cũ, chúng ta không thể chuyển sang làm việc trực tiếp một nhánh từ xa, mà cần phải tạo một nhánh cục bộ dựa trên nhánh từ xa bằng lệnh sau:

git checkout -b <nhánh cục bộ> <tên kho lưu trữ từ xa>/<tên nhánh từ xa>

Ví dụ: để chuyển sang nhánh develop ở kho lưu trữ từ xa, ta sử dụng:

git fetch -all
git checkout develop

Hoặc

git checkout -b develop origin/develop

Tổng kết Git Checkout

Git checkout là một lệnh đa dụng và quan trọng trong Git. Qua bài viết này, ITviec hi vọng đã cung cấp các thông tin hữu ích để bạn có thể nắm vững được cách sử dụng Git checkout trong các trường hợp thực tế. Từ đó tạo tiền đề để bạn từng bước chinh phục được công cụ quản lý mã nguồn mạnh mẽ Git, mang lại nhiều cơ hội việc làm hơn.