Bạn amend một commit rồi muốn xem lại nội dung trước đó. git log trên nhánh hiện tại không còn hiển thị commit cũ như trước, nhưng điều đó chưa đồng nghĩa object đã biến mất. Reflog có thể giúp tìm một vị trí cũ của HEAD trong repository local.
Bài này tạo tình huống bằng dữ liệu giả trong repository riêng. Các lệnh đã được kiểm tra với Git 2.54.0; tài liệu được đối chiếu ngày 25/10/2026. Chúng ta tạo một nhánh giữ commit tìm được, không reset nhánh dự án thật hoặc force-push lên remote.
1. Hiểu reflog ghi điều gì
Tham chiếu git reflog mô tả nhật ký cập nhật của các ref trong repository local. Ký hiệu HEAD@{1} trỏ vào một vị trí cũ theo reflog, không phải quy tắc cố định “commit cha của HEAD”. Các thao tác khác như chuyển nhánh có thể làm số thứ tự thay đổi.
Với git commit amend, Git tạo commit mới để thay đầu nhánh. Vì vậy, ta có thể dựng một bài học không cần xóa nhánh hay dùng hard reset: tạo bản nháp, rồi amend thành bản sửa.
2. Tạo repository thử
Chạy trong thư mục mới. Không dán phần tạo tình huống amend vào repository đang làm việc.
mkdir git-reflog-demo
cd git-reflog-demo
git init -b main
git config user.name 'Reflog Demo'
git config user.email '[email protected]'
printf '%s\n' 'base' > note.txt
git add note.txt
git commit -m 'Create base note'
printf '%s\n' 'draft-v1' > note.txt
git add note.txt
git commit -m 'Write first draft'
printf '%s\n' 'draft-v2' > note.txt
git add note.txt
git commit --amend -m 'Revise draft'
Hai lệnh config chỉ áp dụng cho repository thử. Sau amend, file hiện tại chứa draft-v2. Commit “Write first draft” không còn là một commit nằm trên đường lịch sử của main trong fixture này; commit thay thế trỏ về cùng phần lịch sử trước nó.
Amend lịch sử đã chia sẻ là một quyết định khác, cần phối hợp theo quy trình nhóm. Ví dụ chỉ dùng commit local chưa push để học cách quan sát object và ref.
3. Đọc lại trước khi phục hồi
git log --oneline --decorate
git reflog --date=iso
git show 'HEAD@{1}':note.txt
Trong đúng chuỗi lệnh thử bên trên, vị trí trước amend cho nội dung draft-v1. Kết quả này đã được chạy và kiểm tra. Tuy nhiên, trong repository thật, hãy đọc dòng reflog và xem commit trước khi chọn số thứ tự; đừng mặc định dùng 1 vì bài viết dùng 1.
Khi cần chắc hơn, lấy SHA từ dòng đã xác minh và dùng SHA đó cho bước tiếp theo. SHA nhận diện commit không phụ thuộc việc bạn vừa thực hiện thêm một lần chuyển nhánh làm các số thứ tự reflog dịch đi.
Nếu chỉ cần đọc một file, git show đã cho bạn một điểm kiểm tra mà chưa đổi working tree. Hãy tận dụng khoảng dừng đó để xác nhận đúng nội dung thay vì vội di chuyển nhánh đang làm về một vị trí cũ.
4. Gắn một nhánh vào commit tìm được
Với fixture chưa thực hiện thêm thao tác đổi HEAD sau bước trên, chạy:
git branch recovered-note 'HEAD@{1}'
git show recovered-note:note.txt
git show main:note.txt
git log --all --oneline --decorate
Kết quả đã kiểm tra: nhánh recovered-note giữ draft-v1, main vẫn giữ draft-v2, working tree hiện tại không bị thay thành bản cũ. Theo tài liệu git branch, lệnh tạo nhánh có thể nhận một start point cụ thể; nó không tự chuyển sang nhánh vừa tạo.
Từ đây, bạn có thể so sánh hai nhánh và quyết định lấy lại toàn bộ hay một phần nội dung bằng quy trình review của nhóm. Việc tìm lại commit và quyết định đưa thay đổi vào nhánh chính là hai bước khác nhau.
Kiểm tra và giới hạn
Trước khi làm trên repository thật, xem git status và bảo toàn công việc đang dở. Đọc reflog của đúng checkout và đúng ref. Nếu commit không có trong HEAD reflog, điều đó chưa chứng minh không tồn tại ở ref khác hoặc bản sao khác; phạm vi tra cứu cần được xác định theo tình huống.
Reflog không phải lịch sử được tự động chia sẻ như commit qua push. Tài liệu cũng có chính sách expire cho entry cũ và entry không còn reachable; khả năng phục hồi còn phụ thuộc object chưa bị dọn. Đừng xem nó là backup vô thời hạn hoặc cố chạy garbage collection để “làm mới” trước khi tìm dữ liệu mất.
Đối với file chưa từng được commit hay cất bằng cơ chế phù hợp, reflog không tự tạo lại nội dung chỉ từ tên file. Cần phân biệt mất ref đến một commit với mất thay đổi chưa từng đi vào object database của Git.
Lỗi thường gặp
Nếu HEAD@{1} cho nội dung khác bài, xem lại chuỗi thao tác của bạn và chọn đúng dòng reflog. Nếu tên recovered-note đã tồn tại, chọn tên nhánh mới thay vì dùng force ghi đè một nhánh chưa đọc. Nếu một clone mới không có reflog bạn cần, quay lại repository local nơi thao tác đã xảy ra.
Kết luận
Reflog hữu ích khi bạn cần tìm một vị trí ref trước đó. Đọc nội dung rồi tạo nhánh giữ commit là cách chia nhỏ việc phục hồi thành những bước có thể kiểm tra, trước khi quyết định thay đổi nhánh đang làm.



