Git là hệ thống kiểm soát phiên bản được sử dụng rộng rãi nhất hiện nay và nó theo dõi các thay đổi theo nhiều cách khác nhau để đảm bảo rằng bạn không bao giờ mất một thay đổi đã cam kết. Hơn nữa, sự kiểm soát mà nó cung cấp cho bạn đối với các quy trình phát triển có nghĩa là bạn có thể xác định chính xác lịch sử dự án của mình trông như thế nào. Git có một số cơ chế để viết lại lịch sử cam kết để trợ giúp việc này, bao gồm git commit --amend
, git rebase
và git reflog
.
Trong bài viết này, bạn sẽ học cách sử dụng git reflog
để sắp xếp lại và viết lại lịch sử cam kết Git của mình một cách hiệu quả và dễ dàng, đồng thời giảm thiểu rủi ro mà việc viết lại lịch sử cam kết thường mang lại.
Git sử dụng một hệ thống được gọi là nhật ký tham chiếu , hoặc đơn giản là " nhật ký lại", để theo dõi các sửa đổi đối với các mẹo của các nhánh. Một tham chiếu, thường được gọi là " ref ", là một con trỏ đến một cam kết hoặc nhánh mà nhiều lệnh Git chấp nhận như một tham số. git checkout
, git reset
và git merge
là những ví dụ về một số lệnh git phổ biến chấp nhận ref làm tham số.
Theo mặc định, nhật ký theo dõi từng vị trí HEAD
trong suốt 90 ngày qua. Hơn nữa, lịch sử reflog chỉ dành riêng cho kho lưu trữ và không thể truy cập từ xa. Ngoài các bản cập nhật đầu chi nhánh, có một bản cập nhật riêng cho kho lưu trữ Git .
Nhật ký được lưu trữ trong các thư mục cụ thể trong .git
của kho lưu trữ cục bộ. Các thư mục git reflog
này có thể được tìm thấy tại .git/logs/refs/heads/.
, .git/logs/HEAD
và cả .git/logs/refs/stash
nếu git stash
đã được sử dụng trên kho lưu trữ.
Các lệnh reflog cơ bản như sau:
# To see activity on HEAD git reflog show
Đầu ra của lệnh trên trông giống như sau:
0a2e358 HEAD@{0}: reset: moving to HEAD~2 0254ea7 HEAD@{1}: checkout: moving from 2.2 to main c10f740 HEAD@{2}: checkout: moving from main to 2.2
Các cách sử dụng phổ biến khác như sau:
# To see activity on HEAD, including timestamp git reflog show --date=relative #or git reflog --relative-date # same, on some_branch git reflog show --date=relative some_branch
Theo mặc định, git reflog
xuất ra reflog của HEAD
ref. Biểu tượng HEAD
biểu thị chi nhánh hiện đang hoạt động. Ngoài ra còn có các bản cập nhật có sẵn cho các bản giới thiệu khác. Ví dụ: cú pháp được sử dụng để truy cập git ref là name@{qualifier}
- otherbranch@{0}
. Ngoài các tham chiếu HEAD
, các nhánh khác, thẻ, điều khiển từ xa và kho lưu trữ Git cũng có thể được tham chiếu.
Để xem bản cập nhật đầy đủ của tất cả các bản tham chiếu, bạn có thể thực hiện:
git reflog show --all
Ngoài các chỉ mục được sắp xếp theo thứ tự, mỗi mục nhập nhật ký lại có một dấu thời gian gắn liền với nó cũng có thể được sử dụng như một mã thông báo định tính cho cú pháp con trỏ tham chiếu Git. Đây là điều cho phép lọc các mục reflog này theo thời gian. Ví dụ về các bộ định lượng thời gian thường được sử dụng bao gồm:
@{0}
@{6.minutes.ago}
@{2.hour.ago}
@{3.day.ago}
@{5.weeks.ago}
@{8.years.ago}
@{today}
@{2022-01-23.08:30:00}
@{1.day.10.hours.ago}
Các định tính thời gian này có thể được kết hợp với nhau (ví dụ: 1.day.3.hours.ago
). Các dạng số nhiều của các định tính thời gian này cũng được chấp nhận (ví dụ: 5.minutes.ago
). Chúng có thể được sử dụng cùng với git reflog
như sau:
git reflog show develop@{3.days.ago}
git reflog
chấp nhận một số đối số bổ sung, do đó được coi là lệnh con, chẳng hạn như show
, expire
và delete
. Hãy thảo luận chi tiết về các lệnh con này.
Như đã thảo luận trước đó, show
được truyền ngầm theo mặc định. Việc thực thi git reflog show
sẽ hiển thị nhật ký cho các đối số được truyền vào.
Ví dụ:
git reflog develop@{0}
giống như
git reflog show develop@{0}
Ngoài ra, git reflog show
là bí danh cho git log -g --abbrev-commit --pretty=oneline
.
Lệnh con expire
giúp xóa các mục nhập reflog cũ hoặc không thể truy cập được.
Lệnh con
expire
có khả năng gây mất dữ liệu.
Tuy nhiên, lệnh phụ này thường không được sử dụng bởi người dùng cuối mà được sử dụng bởi git trong nội bộ.
“Chạy khô” có thể được thực hiện bằng cách chuyển tùy chọn -n
hoặc --dry-run
để git reflog expire
để xuất ra các mục reflog được đánh dấu là cần cắt bớt, sao cho chúng sẽ không thực sự bị cắt. Điều này có thể giúp ích như một mạng lưới an toàn trong khi dọn dẹp các mục reflog đã hết hạn.
Ngoài ra, thời gian hết hạn có thể được chỉ định bằng cách truyền đối số dòng lệnh --expire=time
để git reflog expire
hoặc bằng cách đặt tên cấu hình git của gc.reflogExpire
.
Lệnh con xóa, như tên gọi của nó, sẽ xóa mục nhập nhật ký đã chuyển. Xóa, chẳng hạn như hết hạn, có khả năng gây mất dữ liệu và không được người dùng cuối thường xuyên sử dụng.
git reflog
và git log
là hai thành phần có tên giống nhau được cung cấp bởi Git, cho phép chúng ta xâm nhập vào lịch sử cam kết, nhật ký và nhật ký của kho lưu trữ. Thực tế là hai thành phần thường thể hiện cùng một lịch sử, đặc biệt là khi một nhà phát triển hoàn thành một số cam kết cục bộ mà không tìm nạp hoặc kéo, là một trong những lý do gây ra sự nhầm lẫn giữa Git reflog và log.
Tuy nhiên, về cơ bản chúng khác nhau và có các trường hợp sử dụng khác nhau.
Chúng ta hãy hiểu sự khác biệt cơ bản cũng như điểm tương đồng của hai lệnh trên.
Sự khác biệt đáng chú ý nhất giữa bản ghi Git và bản ghi là bản ghi là bản ghi công khai về lịch sử cam kết của kho lưu trữ, trong khi bản ghi lại là bản ghi riêng tư, dành riêng cho không gian làm việc về các lần cam kết cục bộ của kho lưu trữ.
Sau một lần đẩy, tìm nạp hoặc kéo, nhật ký Git được sao chép như một phần của kho lưu trữ Git. Mặt khác, reflog Git không được bao gồm trong repo nhân bản. Nếu không có quyền truy cập vật lý vào máy tính nơi lưu trữ cục bộ, nhà phát triển không thể kiểm tra bản ghi lại.
Reflog là một tệp được tìm thấy trong .git\logs\refs\heads
theo dõi lịch sử của các cam kết cục bộ cho một nhánh cụ thể và loại trừ bất kỳ cam kết nào có thể đã bị quá trình thu gom rác Git loại bỏ. Mặt khác, nhật ký Git cung cấp một quá trình cam kết lịch sử của một nhánh bắt đầu với lần cam kết gần đây nhất và kết thúc với lần cam kết đầu tiên trong lịch sử của nhánh.
Git reflog có thể được sử dụng như một mạng lưới an toàn trong quá trình phát triển vì bạn không thể mất dữ liệu từ repo của mình khi nó đã được cam kết nếu bạn hiểu đúng khái niệm về reflog. Bạn có thể sử dụng reflog để xem bạn đã ở đâu trước đó và git reset --hard
quay lại ref đó để khôi phục trạng thái trước đó của bạn nếu bạn vô tình đặt lại về cam kết cũ hơn, rebase không chính xác hoặc thực hiện bất kỳ thao tác nào khác có thể "xóa" cam kết.
Hãy nhớ rằng các tham chiếu đề cập đến toàn bộ lịch sử của cam kết, không chỉ bản thân cam kết.
Trong bài viết này, chúng tôi đã thảo luận về các tùy chọn cấu hình mở rộng của git reflog
, các trường hợp sử dụng phổ biến và các cạm bẫy của git reflog
.
Tóm lại, Git giữ một bản cập nhật lại, là bản ghi về vị trí của các tham chiếu HEAD
và chi nhánh của bạn trong vài tháng qua (90 ngày), ở chế độ nền trong khi bạn đang làm việc. Git lưu thông tin trong lịch sử tạm thời này mỗi khi mẹo chi nhánh của bạn được sửa đổi vì bất kỳ lý do gì.
Lệnh reflog cũng có thể được sử dụng để xóa hoặc hết hạn các mục nhập đã quá cũ trong bản reflog. Lệnh con expire
được sử dụng để xóa các mục nhập reflog đã lỗi thời và lệnh phụ delete
được sử dụng để xóa và chỉ định mục cụ thể sẽ bị xóa khỏi reflog.