Git: Đặt lại, kiểm tra, và hoàn nguyên


Đăng ký nhận thông báo về những video mới nhất

Các lệnh git resetgit checkout và git revert là một số trong những công cụ hữu ích nhất trong hộp công cụ Git của bạn. Tất cả đều cho phép bạn hoàn tác một số loại thay đổi trong kho lưu trữ của bạn và hai lệnh đầu tiên có thể được sử dụng để thao tác với các commit hoặc các tệp riêng lẻ.

Vì chúng rất giống nhau, nên rất dễ trộn lẫn lệnh nào sẽ được sử dụng trong bất kỳ kịch bản phát triển cụ thể nào. Trong bài viết này, chúng tôi sẽ so sánh các cấu hình phổ biến nhất của git resetgit checkoutvà git revert. Hy vọng rằng, bạn sẽ tự tin bỏ đi để điều hướng kho lưu trữ của mình bằng bất kỳ lệnh nào trong số này.

Ba cây Git

Nó giúp suy nghĩ về từng lệnh về tác dụng của chúng đối với ba cơ chế quản lý trạng thái của kho lưu trữ Git: thư mục làm việc, ảnh chụp theo giai đoạn và lịch sử cam kết. Những thành phần này đôi khi được gọi là "Ba cây" của Git. Chúng tôi khám phá ba cây sâu trong git resettrang. Hãy ghi nhớ các cơ chế này khi bạn đọc qua bài viết này.

Thanh toán là một hoạt động di chuyển HEADcon trỏ ref đến một xác nhận đã chỉ định. Để chứng minh điều này hãy xem xét ví dụ sau đây.

Di chuyển con trỏ ref tới một xác định

Ví dụ này cho thấy một chuỗi các cam kết trên masternhánh. Các HEADref và masterchi nhánh hiện đang trỏ đến cam kết d. Bây giờ hãy để chúng tôi thực hiện git checkout b

Trình tự cam kết trên nhánh chính

Đây là bản cập nhật cho cây "Lịch sử cam kết". Các git checkoutlệnh có thể được sử dụng trong một cam kết, hoặc cấp tập tin phạm vi. Kiểm tra cấp độ tệp sẽ thay đổi nội dung của tệp thành các cam kết cụ thể.

Hoàn nguyên là một hoạt động có một cam kết được chỉ định và tạo ra một cam kết mới đảo ngược cam kết đã chỉ định. git revertchỉ có thể được chạy ở phạm vi mức cam kết và không có chức năng cấp tệp.

Thiết lập lại là một hoạt động có một cam kết được chỉ định và đặt lại "ba cây" để khớp với trạng thái của kho lưu trữ tại cam kết đã chỉ định đó. Một thiết lập lại có thể được gọi trong ba chế độ khác nhau tương ứng với ba cây.

Thanh toán và đặt lại thường được sử dụng để thực hiện 'hoàn tác' cục bộ hoặc riêng tư. Họ sửa đổi lịch sử của một kho lưu trữ có thể gây ra xung đột khi đẩy vào kho lưu trữ được chia sẻ từ xa. Revert được coi là một hoạt động an toàn cho 'công khai hoàn tác' vì nó tạo ra lịch sử mới có thể được chia sẻ từ xa và không ghi đè lên lịch sử mà các thành viên nhóm từ xa có thể phụ thuộc vào.

Tham chiếu Git vs Revert vs Checkout

Bảng dưới đây tổng hợp các trường hợp sử dụng phổ biến nhất cho tất cả các lệnh này. Hãy chắc chắn để giữ tài liệu tham khảo này tiện dụng, vì chắc chắn bạn sẽ cần sử dụng ít nhất một số trong số chúng trong sự nghiệp Git của bạn.

Chỉ huy Phạm vi Các trường hợp sử dụng phổ biến
git reset Cam kết cấp Hủy bỏ cam kết trong một chi nhánh tư nhân hoặc vứt bỏ những thay đổi không được cam kết
git reset Cấp độ tệp Bỏ tập tin
git checkout Cam kết cấp Chuyển đổi giữa các chi nhánh hoặc kiểm tra ảnh chụp nhanh cũ
git checkout Cấp độ tệp Hủy thay đổi trong thư mục làm việc
git revert Cam kết cấp Hoàn tác cam kết trong một chi nhánh công cộng
git revert Cấp độ tệp (Không có)

Cam kết hoạt động cấp

Các tham số mà bạn truyền đến git resetvà git checkoutxác định phạm vi của chúng. Khi bạn không bao gồm đường dẫn tệp làm tham số, chúng sẽ hoạt động trên toàn bộ cam kết. Đó là những gì chúng ta sẽ khám phá trong phần này. Lưu ý rằng git revertkhông có đối tác cấp tệp.

Đặt lại một cam kết cụ thể

Ở cấp độ cam kết, đặt lại là một cách để di chuyển đầu nhánh sang một cam kết khác. Điều này có thể được sử dụng để loại bỏ các cam kết từ chi nhánh hiện tại. Ví dụ, lệnh sau di chuyển hotfixnhánh ngược lại bằng hai lần xác nhận.

git checkout hotfix
git reset HEAD~2

Hai cam kết cuối cùng hotfixhiện đang lơ lửng, hoặc mồ côi. Điều này có nghĩa là chúng sẽ bị xóa vào lần tới khi Git thực hiện bộ sưu tập rác. Nói cách khác, bạn đang nói rằng bạn muốn vứt bỏ những cam kết này. Điều này có thể được hình dung như sau:

Đặt lại nhánh hotfix thành HEAD-2

Cách sử dụng git resetnày là một cách đơn giản để hoàn tác các thay đổi chưa được chia sẻ với bất kỳ ai khác. Đó là mệnh lệnh của bạn khi bạn bắt đầu làm việc với một tính năng và thấy mình suy nghĩ, cùi Oh, tôi đang làm gì vậy? Tôi chỉ nên bắt đầu lại.

Ngoài việc di chuyển nhánh hiện tại, bạn cũng có git resetthể thay đổi ảnh chụp nhanh theo giai đoạn và / hoặc thư mục làm việc bằng cách chuyển qua một trong các cờ sau:

  • --soft - Ảnh chụp nhanh và thư mục làm việc không bị thay đổi theo bất kỳ cách nào.
  • --mixed- Ảnh chụp theo giai đoạn được cập nhật để phù hợp với cam kết đã chỉ định, nhưng thư mục làm việc không bị ảnh hưởng. Đây là tùy chọn mặc định.
  • --hard - Ảnh chụp nhanh theo giai đoạn và thư mục làm việc đều được cập nhật để phù hợp với cam kết đã chỉ định.
     

Dễ dàng hơn khi nghĩ về các chế độ này khi xác định phạm vi git resethoạt động. Để biết thêm thông tin chi tiết truy cập git resettrang.

Thanh toán các cam kết cũ

Các git checkoutlệnh được sử dụng để cập nhật trạng thái của kho lưu trữ đến một điểm cụ thể trong lịch sử dự án. Khi được thông qua với một tên chi nhánh, nó cho phép bạn chuyển đổi giữa các chi nhánh.

git checkout hotfix

Trong nội bộ, tất cả các lệnh trên làm là di chuyển HEADđến một nhánh khác và cập nhật thư mục làm việc cho phù hợp. Vì đây có khả năng ghi đè lên thay đổi địa phương, Git buộc bạn phải cam kết hoặc giấu bất kỳ thay đổi trong thư mục làm việc đó sẽ bị mất trong các hoạt động thanh toán. Không giống như git resetgit checkoutkhông di chuyển bất kỳ chi nhánh xung quanh.

Di chuyển CHÍNH từ chủ sang hotfix

Bạn cũng có thể kiểm tra các cam kết tùy ý bằng cách chuyển tham chiếu cam kết thay vì một nhánh. Điều này thực hiện chính xác tương tự như kiểm tra một nhánh: nó di chuyển HEADtham chiếu đến cam kết đã chỉ định. Ví dụ: lệnh sau sẽ kiểm tra ông bà của cam kết hiện tại:

git checkout HEAD~2

Di chuyển `ĐẦU` đến một cam kết tùy ý

Điều này rất hữu ích để nhanh chóng kiểm tra một phiên bản cũ của dự án của bạn. Tuy nhiên, vì không có tham chiếu chi nhánh nào cho hiện tại HEAD, điều này đặt bạn vào HEADtrạng thái tách rời . Điều này có thể nguy hiểm nếu bạn bắt đầu thêm các cam kết mới vì sẽ không có cách nào để quay lại với chúng sau khi bạn chuyển sang chi nhánh khác. Vì lý do này, bạn phải luôn tạo một nhánh mới trước khi thêm các xác nhận vào một tách ra HEAD.

Hoàn tác các cam kết công khai với Revert

Hoàn nguyên cam kết bằng cách tạo một cam kết mới. Đây là một cách an toàn để hoàn tác các thay đổi, vì nó không có cơ hội viết lại lịch sử cam kết. Ví dụ, lệnh sau sẽ chỉ ra các thay đổi có trong lần xác nhận thứ 2 đến lần cuối, tạo một cam kết mới hoàn tác các thay đổi đó và giải quyết cam kết mới đối với dự án hiện có.

git checkout hotfix
git revert HEAD~2

Điều này có thể được hình dung như sau:

Hoàn nguyên cam kết thứ 2 đến lần cuối

Tương phản điều này với git reset, điều này làm thay đổi lịch sử cam kết hiện có. Vì lý do này, git revertnên được sử dụng để hoàn tác các thay đổi trên một nhánh công cộng và git resetnên được dành riêng cho các thay đổi hoàn tác trên một nhánh riêng.

Bạn cũng có thể nghĩ về git revertnhư một công cụ để hoàn tác các thay đổi đã cam kết , trong khi đó git reset HEADlà hoàn tác các thay đổi không được cam kết .

Giống như git checkoutgit revertcó khả năng ghi đè lên các tệp trong thư mục làm việc, vì vậy nó sẽ yêu cầu bạn thực hiện hoặc xóa các thay đổi sẽ bị mất trong quá trình hoàn nguyên.

Hoạt động cấp tệp

Các lệnh git resetvà git checkoutcũng chấp nhận một đường dẫn tệp tùy chọn làm tham số. Điều này làm thay đổi đáng kể hành vi của họ. Thay vì hoạt động trên toàn bộ ảnh chụp nhanh, điều này buộc họ phải giới hạn hoạt động của mình trong một tệp duy nhất.

Git Đặt lại một tệp cụ thể

Khi được gọi với đường dẫn tệp, git resetcập nhật ảnh chụp theo giai đoạn để khớp với phiên bản từ cam kết đã chỉ định. Ví dụ: lệnh này sẽ tìm nạp phiên bản của foo.pycam kết thứ 2 đến lần cuối và thực hiện nó cho lần xác nhận tiếp theo:

git reset HEAD~2 foo.py

Như với phiên bản cấp độ cam kết git reset, điều này thường được sử dụng HEADhơn là một cam kết tùy ý. Chạy git reset HEAD foo.pysẽ ra sân khấu foo.py. Những thay đổi mà nó chứa vẫn sẽ hiện diện trong thư mục làm việc.

Di chuyển tệp từ lịch sử cam kết vào ảnh chụp nhanh

Các --soft--mixedvà các --hardcờ không có bất kỳ ảnh hưởng nào đến phiên bản cấp tệp git reset, vì ảnh chụp nhanh theo giai đoạn luôn được cập nhật và thư mục làm việc không bao giờđược cập nhật.

Tệp thanh toán Git

Kiểm tra một tệp tương tự như sử dụng git resetvới đường dẫn tệp, ngoại trừ nó cập nhật thư mục làm việc thay vì giai đoạn. Không giống như phiên bản mức cam kết của lệnh này, điều này không di chuyển HEADtham chiếu, điều đó có nghĩa là bạn sẽ không chuyển nhánh.

Di chuyển tệp từ lịch sử cam kết vào thư mục làm việc

Ví dụ, lệnh sau làm cho foo.pytrong thư mục làm việc khớp với lệnh từ lần xác nhận thứ 2 đến lần cuối:

git checkout HEAD~2 foo.py

Giống như lời gọi mức cam kết git checkout, điều này có thể được sử dụng để kiểm tra các phiên bản cũ của một dự án, nhưng phạm vi được giới hạn trong tệp được chỉ định.

Nếu bạn thực hiện và cam kết tệp đã thanh toán, điều này có tác dụng của việc hoàn nguyên lại thành phiên bản cũ của tệp đó. Lưu ý rằng điều này loại bỏ tất cả các thay đổi tiếp theo đối với tệp, trong khi git revertlệnh chỉ hoàn tác các thay đổi được đưa ra bởi cam kết đã chỉ định.

Giống như git reset, điều này thường được sử dụng với HEADtham chiếu cam kết. Chẳng hạn, git checkout HEAD foo.pycó tác dụng loại bỏ những thay đổi không có căn cứ thành foo.py. Đây là hành vi tương tự git reset HEAD --hard, nhưng nó chỉ hoạt động trên tệp được chỉ định.

Tóm lược

Bây giờ bạn sẽ có tất cả các công cụ bạn cần để hoàn tác các thay đổi trong kho Git. Các git resetgit checkoutvà git revertcác lệnh có thể gây nhầm lẫn, nhưng khi bạn nghĩ về ảnh hưởng của chúng trên thư mục làm việc, tổ chức ảnh chụp, và cam kết lịch sử, nó phải là dễ dàng hơn để phân biệt mà chỉ huy phù hợp với nhiệm vụ phát triển trong tầm tay.

Đăng ký nhận thông báo về những video mới nhất
« Prev: Git: Merging so với Rebasing
» Next: Git: Nhật ký Git nâng cao
Copied !!!