Git reset hoạt động như thế nào ? Sự khác nhau của Sort, Hard, và Mixed resets ?


git reset
là một lệnh mạnh mẽ có thể sửa đổi lịch sử của Git repository của bạn và sửa các lỗi bạn đã mắc phải. Mặc dù cái tên khiến nó có vẻ đáng sợ khi sử dụng, nhưng nó thực sự khá dễ dàng. Hôm nay tôi có phỏng vấn 1 bạn Senior và thấy mặc dù bạn biết sử dụng lệnh này nhưng lại không hiểu rõ sự khác nhau giữa các cách dùm. Vì vậy trong lúc rảnh rỗi tôi cũng viết 1 bài dựa vào kinh nghiệm và tham khảo dịch lại một vài tài liệu nước ngoài với hi vọng một ai đó đọc được và thấy có ích cho họ.

Git HEAD là gì?

Trước khi tìm hiểu về cách git resets hoạt động, chúng ta sẽ nói về Git HEAD.

"HEAD" đơn giản là một alias cho commit hiện tại của bạn. Nếu bạn đang ở branch master, HEAD sẽ là commit mới nhất trên branch đó.

Mặc dù là alias cho 1 commit, nhưng HEAD không thực sự trỏ trực tiếp đến 1 commit trong hầu hết thời gian. Nó hướng tới 1 branch và tự động sử dụng commit mới nhất. 

Nó cũng có thể trỏ đến 1 commit trực tiếp, lúc này nó được gọi là "detached HEAD", cái này không quan trọng đối với git reset mà chúng ta bàn trong bài viết này.

Git reset hoạt động như thế nào?

Lịch sử commit trong Git được lưu trong 1 cây (tree) các commits,  và nó được dự định không thay đổi trong hầu hết các phần. Tuy nhiên thỉnh thoảng chúng ta cần phải thay đổi các lịch sử này, và lúc này git reset sẽ phát huy tác dụng.

Mỗi commit liên kết với commit trước nó, và có thể phân nhánh thành các chi nhánh khác nhau mà cuối cùng sẽ được merge lại ở nhánh master (Hoặc nhánh main). Trong cả 2 trường hợp, HEAD sẽ hướng tới commit mới nhất ở Branch bạn đang làm việc:


Vậy điều gì xảy ra khi bạn thực hiện một commit mà bạn muốn revert?

=> Chạy git reset cơ bản sẽ di chuyển HEAD trở lại và để lại tất cả các commit đang treo phía trước nó. Điều này viết lại lịch sử Git thường bất biến để loại bỏ các commit trước HEAD:


Điều này khá hữu ích trong nhiều trường hợp. Có thể bạn tạo 1 commit , sau đó thực hiện một số thay đổi bổ sung và bạn muốn push tất cả chúng lên Git repository như một commit duy nhất. Bạn có thể chạy : git reset để trở về commit trước sau đó thực hiện commit lại toàn bộ thay đổi.

Hoặc bạn đã vô tình thực hiện một commit bao gồm một số thay đổi mà bạn không muốn theo dõi. Điều này có thể rất khó tìm ra nếu bạn không biết git reset hoạt động như thế nào, nhưng việc đặt lại HEAD và sau đó chỉ dàn dựng các thay đổi chính xác sẽ đạt được điều này. Lưu ý rằng điều này khác với git revert, nó đảo ngược các cam kết.

Sự khác nhau của các loại git reset

Có 3 loại reset trong git, chúng khác nhau dựa trên các chúng xử lý các commit. Tất cả chung đều viết lại lịch sử git và chúng đều di chuyển HEAD trở lại, nhưng chúng xử lý các thay đổi theo cách khác nhau:

  • git reset --soft, Sẽ giữ tất cả các file của bạn và tự động chuyển tất cả các thay đổi trở lại.
  • git reset --hard, Sẽ phá huỷ hoàn toàn các thay đổi và xoá chúng khỏi local của bạn. Bạn chỉ thực hiện điều này khi bạn hiểu rõ bạn đang làm gì nếu không sẽ không có cách gì có thể cứu vãn @@. 
  • git reset --mixed, Là mặc định, nó giữ tất cả các file nhưng bỏ các thay đổi. 
Sự khác nhau giữa 3 loại reset được thể hiện chi tiết trong hình sau.


Như vậy về cơ bản, Soft và Mixed hầu như giống nhau và cho phép bạn giữ các thay đổi. Còn reset Hard sẽ hoàn toàn đặt thư mục local của bạn trở về vị trí tại thời điểm commit.

Cách sử dụng Git Reset

Một khi bạn đã hiểu rõ sự khác nhau giữa các loại reset, thì việc sử dụng bây giờ cực kỳ dễ dàng và an toàn.

Để bắt đầu reset, trước tiên bạn cần tham khảo trước danh sách các commit hiện tại và xác định đúng commit mà bạn muốn di chuyển về. Để lấy danh sách commit, bạn chạy lệnh:

git reflog

Copy 7 ký tự code bên trái, sau đó bạn reset lại bằng lệnh tương tự sau:

git reset --mixed cd79317

Hoặc bạn cũng có thể trỏ tới commit dựa vào vị trí của chúng so với HEAD. Lệnh sau trỏ mục tiêu commit ngay trước HEAD, đây là cách viết tắt hữu ích nếu bạn cần reset commit mới nhất:

git reset --mixed HEAD~


Bạn có nên reset --hard lại không?

Bạn thực sự chỉ nên sử dụng soft hoặc mixed reset. Nhưng nếu bạn làm hỏng repository của bạn tới mức bạn cần reset hoàn toàn nó => Bạn có thể sử dụng chuỗi các lệnh sau để reset hoàn toàn bình thường:

git fetch origin
git checkout master
git reset --hard origin/master
git clean -d --force


Tới đây hi vọng tôi đã cung cấp 1 chút ít kiến thức nhanh gọn lẹ để bạn hiểu rõ về git reset.


0 Nhận xét:

Đăng nhận xét

Rất mong các ý kiến của các bạn khi đọc bài viết này !