# Cách hoàn tác thay đổi trong Claude Code: /rewind và git

> Các chế độ quay lui, giới hạn của checkpointing, git checkout, stash, reflog và cách bảo vệ trước các lệnh phá hoại. Năm cách khôi phục trạng thái.

Source: https://ailoot.ai/blog/vi/claude-code-undo-changes/
Canonical: https://ailoot.ai/blog/vi/claude-code-undo-changes/
Language: vi
Publisher: Ailoot (https://ailoot.ai/)
Translation: guide-138
Revision: sha256-ce220de0b38cb57423ccc2f1cb0c24497b5484b35b7fe9955d41ff10ccdd865e




[Thông tin thực tế về cách làm việc với Ailoot có trong tài liệu hướng dẫn](https://ailoot.ai/docs/).

## Hoàn tác trong Claude Code là gì, và tại sao ba cấp độ vẫn chưa đủ?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Hoàn tác trong Claude Code có ba cấp độ: lệnh tích hợp `/rewind` (khôi phục tức thì trong một phiên), `git checkout` (khôi phục về commit gần nhất) và `git reflog` (lưới an toàn trong trường hợp khẩn cấp nếu ai đó chạy `git reset --hard`). Mỗi cấp độ xử lý một nhóm lỗi riêng và không vượt quá phạm vi của nó. Chỉ biết `/rewind` đồng nghĩa với việc bạn sẽ lúng túng khi gặp sự cố nghiêm trọng đầu tiên.

</div>

Tôi bật `/rewind` trong tuần đầu sử dụng Claude Code, sau khi nó làm hỏng logic xác thực của dự án chỉ trong hai prompt. Tôi quay lui, thở phào nhẹ nhõm rồi tiếp tục. Một tháng sau, tình huống khác xảy ra: tôi đang viết schema migration, Claude hỗ trợ, tôi commit, chuyển nhánh—rồi nhận ra mình đã quên một bước cần thiết. `/rewind` không giúp được—phiên đã khác. `git checkout` về commit trước đó đã giúp ích. Một tháng sau nữa, tôi vô tình bảo agent “đưa mọi thứ trở lại lần push gần nhất”, và nó chạy `git reset --hard`, phá hỏng ba giờ làm việc. `git reflog` đã cứu tôi—hash của các commit bị phá hủy vẫn còn ở đó.

Ba câu chuyện này đại diện cho ba cấp độ bảo vệ hoạt động khác nhau, xử lý những lỗi khác nhau và đều cần thiết. Hướng dẫn này giải thích từng cấp độ cùng các lệnh, giới hạn và ví dụ, đồng thời chỉ cách cấu hình dự án từ trước để Claude không làm hỏng dự án ngay lần đầu.

**3 cấp độ hoàn tác—dùng gì và khi nào:**

| Cấp độ | Lệnh | Xử lý được | KHÔNG xử lý được |
|----|----|----|----|
| 1\. Trong một phiên | `/rewind` hoặc `Esc Esc` | Tệp Claude thay đổi bằng công cụ của chính nó; lịch sử hội thoại | Lệnh Bash, trình soạn thảo bên ngoài, database migration |
| 2\. Trước khi commit | `git checkout .` hoặc `git stash` | Mọi thay đổi chưa commit trong các tệp | Các commit đã được commit |
| 3\. Thảm họa | `git reflog` + `git reset --hard <hash>` | Commit bị phá hủy bằng `reset --hard` hoặc force-push | Lệnh Bash phá hoại (rm, database migration) |

Tiếp theo, chúng ta sẽ đi qua từng cấp độ—cần làm chính xác những gì, các điểm dễ mắc sai lầm và cách cấu hình để không có gì phải hoàn tác vì chẳng có gì bị hỏng.

## Gọi /rewind như thế nào: dùng lệnh hay nhấn Esc-Esc?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Có hai cách mở menu Rewind trong Claude Code. Cách thứ nhất là nhập `/rewind` vào ô nhập liệu. Cách thứ hai là nhấn `Esc` hai lần khi ô nhập liệu trống. Nếu trong ô có văn bản, lần nhấn đúp đầu tiên sẽ xóa văn bản và lưu nội dung vào lịch sử nhập liệu; nhấn đúp thêm lần nữa sẽ mở menu. Lệnh `/rewind` có bí danh `/checkpoint`.

</div>

Sau mỗi câu trả lời, Claude tự động tạo ảnh chụp trạng thái của tất cả tệp mà nó đã chỉnh sửa trong phiên đó. Các ảnh chụp trạng thái được lưu tại `~/.claude/file-history/{sessionId}/` và giữ tối đa 30 ngày. Ảnh chụp trạng thái có tính tăng dần—chỉ những khác biệt giữa các trạng thái được lưu, không phải toàn bộ tệp. Theo mặc định, mỗi phiên lưu tối đa 100 ảnh chụp trạng thái. Điều này có nghĩa là trong hầu hết dự án thực tế, bạn luôn có thể xem toàn bộ lịch sử các thay đổi của Claude trong ngày làm việc bất cứ lúc nào.

Để mở menu quay lui, nhấn `Esc` hai lần khi ô nhập liệu trống:

```
[user-input is empty]
> _

[press Esc, Esc]

Rewind to which message?
  1. Create a migration for the User table          (3 files changed)
  2. Add the lastLoginAt field                      (1 file changed)
  3. Rewrite the authorization logic                (5 files changed)
  ...
```

Nếu trong ô nhập liệu có văn bản, lần nhấn đúp `Esc` đầu tiên sẽ xóa văn bản và lưu vào lịch sử `Up`. Điều này hữu ích khi bạn đã bắt đầu nhập rồi mới nhận ra mình cần quay lui. Sau đây là trích dẫn từ tài liệu chính thức của Anthropic:

<figure>
<blockquote>
<p>Nếu có văn bản trong trường prompt, nhấn Esc hai lần trước tiên sẽ xóa văn bản thay vì mở menu. Văn bản đã xóa được lưu trong lịch sử nhập liệu, vì vậy bạn có thể khôi phục bằng phím mũi tên lên sau menu quay lui.</p>
</blockquote>
<figcaption>— Tài liệu Anthropic, https://code.claude.com/docs/en/checkpointing</figcaption>
</figure>

Lệnh `/rewind` cũng làm điều tương tự—mở menu. Ngoài ra còn có bí danh `/checkpoint` dẫn đến cùng nơi. Cách nào tiện hơn tùy vào thói quen. Tôi dùng `Esc Esc`—nhanh hơn và không cần rời tay khỏi bàn phím.

## Có 6 chế độ trong menu Rewind: nên chọn chế độ nào và khi nào?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Sau khi chọn một điểm quay lui trong menu Rewind, menu thứ hai sẽ xuất hiện với sáu chế độ. Ba chế độ khôi phục trạng thái (`Restore code and conversation`, `Restore conversation`, `Restore code`), hai chế độ nén lịch sử (`Summarize from here`, `Summarize up to here`) và một chế độ hủy thao tác (`Never mind`). Tình huống phổ biến nhất—“quay lui cả mã lẫn hội thoại”—là tùy chọn đầu tiên.

</div>

Chọn một điểm trong danh sách, rồi bạn sẽ đến menu thao tác. Có sáu mục, mỗi mục thực hiện một việc khác nhau.

**Bảng đầy đủ các chế độ:**

| Chế độ | Tác dụng | Khi nào nên chọn |
|----|----|----|
| `Restore code and conversation` | Khôi phục cả tệp và lịch sử hội thoại về điểm đã chọn | Tình huống phổ biến nhất: Claude đi sai hướng, và tôi muốn bắt đầu lại với cách diễn đạt đúng |
| `Restore conversation` | Chỉ quay lui lịch sử hội thoại; tệp giữ nguyên trạng thái hiện tại | Mã vẫn ổn, nhưng hội thoại đi chệch hướng; tôi sẽ diễn đạt lại từ điểm này và giữ nguyên các thay đổi hiện tại |
| `Restore code` | Quay lui tệp; hội thoại giữ nguyên như hiện tại | Một số thay đổi của Claude không cần thiết, nhưng tôi vẫn cần ngữ cảnh hội thoại (ví dụ, chúng ta đã thống nhất các bước tiếp theo) |
| `Summarize from here` | Nén mọi thứ SAU điểm đã chọn thành bản tóm tắt. Không tác động đến tệp | Một phiên gỡ lỗi dài đã dùng hết ngữ cảnh; tôi cần giải phóng chỗ nhưng vẫn giữ nguyên đầy đủ chỉ dẫn ban đầu |
| `Summarize up to here` | Nén mọi thứ TRƯỚC điểm đã chọn thành bản tóm tắt. Không tác động đến tệp | Có phần hướng dẫn ban đầu dài, sau đó là một nhiệm vụ cụ thể—chúng ta nén phần hướng dẫn thành một tin nhắn và giữ nguyên công việc gần đây |
| `Never mind` | Đóng menu mà không thay đổi gì | Tôi đổi ý |

Tính năng `Summarize up to here` xuất hiện trong Claude Code v2.1.139-v2.1.142, phát hành từ ngày 11–15 tháng 5 năm 2026, tuần 20:

<figure>
<blockquote>
<p>Bạn có thể nén ngữ cảnh ban đầu thông qua menu Rewind bằng cách dùng 'Summarize up to here'.</p>
</blockquote>
<figcaption>— Anthropic có gì mới, https://code.claude.com/docs/en/whats-new</figcaption>
</figure>

Khác biệt giữa `Restore` và `Summarize` là căn bản. Restore đưa về trạng thái trước đó, hoàn tác mọi thứ diễn ra sau điểm được chọn. Summarize không hoàn tác gì cả; nó chỉ nén—các tin nhắn gốc vẫn nằm trong bản ghi phiên để tham khảo, nhưng chỉ bản tóm tắt còn trong ngữ cảnh đang hoạt động. Dùng restore khi bạn muốn mọi thứ “như thể việc này chưa từng xảy ra”. Dùng summarize khi bạn muốn “giữ lại, nhưng không chiếm chỗ trong ngữ cảnh”.

Sau `Restore conversation` hoặc `Summarize from here`, nội dung ban đầu của prompt được chọn sẽ quay lại ô nhập liệu—bạn có thể chỉnh sửa và gửi lại. Sau `Summarize up to here`, ô nhập liệu trống và bạn vẫn ở cuối cuộc hội thoại.

## /rewind KHÔNG hoàn tác những thay đổi nào?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

`/rewind` chỉ theo dõi các thay đổi Claude thực hiện bằng công cụ chỉnh sửa tệp của chính nó. Nó không thể nhìn thấy hoặc khôi phục bất cứ thứ gì khác. Có ba loại thay đổi vô hình: lệnh Bash (rm, mv, cp), chỉnh sửa bên ngoài (bạn tự sửa trong IDE, thay đổi từ các phiên khác) và thao tác ngoài tệp (database migration, git push, lệnh gọi API từ xa).

</div>

Đây là giới hạn chính mà mọi người gặp phải: `/rewind` hiển thị dấu kiểm màu xanh và báo “quay lui thành công”, nhưng dự án vẫn hỏng vì Claude đã tác động đến nhiều thứ hơn chỉ là tệp. Hãy xem ba trường hợp.

**1. Lệnh Bash không được theo dõi.** Nếu Claude chạy `rm file.txt` hoặc `mv old.txt new.txt` trong một lượt, các thay đổi đó sẽ không nằm trong checkpoint. Tài liệu của Anthropic nêu rõ:

<figure>
<blockquote>
<p>Checkpointing không theo dõi các tệp bị thay đổi thông qua lệnh Bash. Ví dụ, nếu Claude Code chạy rm file.txt, mv old.txt new.txt, cp source.txt dest.txt thì không thể hoàn tác những thay đổi tệp này bằng cách quay lui.</p>
</blockquote>
<figcaption>— Tài liệu Anthropic, https://code.claude.com/docs/en/checkpointing</figcaption>
</figure>

Điều này có nghĩa là nếu Claude tự xóa, di chuyển hoặc sao chép tệp bằng công cụ Bash, `/rewind` sẽ không khôi phục được mọi thứ. `git checkout` hoặc khôi phục từ bản sao lưu có thể hữu ích, nhưng phải làm nhiều hơn việc nhấn hai phím.

**2. Chỉnh sửa bên ngoài không được ghi nhận.** Nếu bạn mở tệp trong VS Code và tự sửa, hoặc một phiên Claude thứ hai đồng thời thay đổi cùng các tệp đó, phiên đầu tiên không thể thấy những thay đổi ấy. Ảnh chụp trạng thái của checkpoint được tạo khi Claude kết thúc một lượt trong phiên hiện tại. Những gì xảy ra giữa các lượt nằm ngoài phạm vi của nó.

**3. Các thao tác ngoài tệp hoàn toàn không được bao phủ.** Một Prisma migration được áp dụng qua `npx prisma migrate dev` đã thay đổi schema cơ sở dữ liệu—`/rewind` không thể hoàn tác vì cơ sở dữ liệu nằm ngoài hệ thống tệp của dự án. Force-push lên `origin/main` cũng vậy: commit đã lên máy chủ từ xa và checkpoint không thể đưa nó trở lại. Một lệnh gọi API từ xa tính phí hoặc xóa bản ghi chỉ có thể được hoàn tác bằng cơ chế riêng của API đó.

**Quy tắc:** Nếu một nhiệm vụ ảnh hưởng đến thứ gì bên ngoài các tệp dự án—database migration, git push, API từ xa—hãy chuẩn bị chiến lược rollback riêng cho từng tác động bên ngoài. `/rewind` chỉ là lịch sử tệp cục bộ trong phiên hiện tại.

## /rewind và git khác nhau thế nào, và tại sao cần cả hai?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

`/rewind` là thao tác quay lui cục bộ trong một phiên Claude Code. Nó lưu ảnh chụp trạng thái tăng dần trong tối đa 30 ngày, tối đa 100 ảnh chụp mỗi phiên. git là lịch sử dự án dài hạn được chia sẻ trong nhóm, có branch, xung đột merge và repository từ xa. Cái này không thay thế cái kia. Cách làm tốt nhất là tạo `git commit` ở mỗi mốc hợp lý và dựa vào `/rewind` giữa các commit.

</div>

Tài liệu Anthropic nói trực tiếp về việc kết hợp này:

<figure>
<blockquote>
<p>Checkpoint được thiết kế để khôi phục nhanh ở cấp độ phiên. Với commit, branch và lịch sử dài hạn, hãy tiếp tục dùng hệ thống kiểm soát phiên bản (ví dụ: Git). Checkpoint bổ trợ chứ không thay thế kiểm soát phiên bản thông thường. Hãy nghĩ về checkpoint như 'hoàn tác cục bộ' và Git như 'lịch sử vĩnh viễn'.</p>
</blockquote>
<figcaption>— Tài liệu Anthropic, https://code.claude.com/docs/en/checkpointing</figcaption>
</figure>

Các điểm khác biệt trong một bảng:

| Tham số | /rewind | git |
|----|----|----|
| Mức độ chi tiết | Mỗi lượt hội thoại | Mỗi commit |
| Lưu trữ | Tối đa 30 ngày, tối đa 100 mỗi phiên, lưu cục bộ trong `~/.claude/file-history/` | Vĩnh viễn trong `.git/` của repository và trên máy chủ từ xa |
| Theo dõi gì | Các chỉnh sửa của Claude qua công cụ của chính nó | Mọi thay đổi đã commit |
| KHÔNG theo dõi gì | Bash, chỉnh sửa bên ngoài, migration, push | Các thay đổi chưa commit |
| Lệnh | Một lệnh bên trong Claude | Hệ thống kiểm soát phiên bản bên ngoài |
| Quay lui hội thoại | Có | Không |
| Hoạt động giữa các phiên | Chỉ trong cùng một phiên | Mọi nơi |

Cách kết hợp rất đơn giản: mỗi khi đạt đến trạng thái “mọi thứ đang hoạt động tốt và tôi không muốn mất nó”, hãy tạo `git commit`. Giữa các commit, hãy dùng `/rewind`—nó tức thì, không cần thông điệp commit và không làm lịch sử git lộn xộn với các trạng thái trung gian. Khi hoàn tất công việc, hãy commit—tốt nhất là một commit có ý nghĩa và nguyên tử.

## Tại sao một lần /rewind không thể bao quát toàn bộ nhiệm vụ?

Hoàn tác là một trường hợp của **context engineering**. Quản lý ngữ cảnh phiên (khi nào commit, khi nào nhấn `/rewind`, đặt quy tắc nào trong `CLAUDE.md`) sẽ giúp Claude hoạt động có thể dự đoán, không phá hỏng dự án hoặc làm mất công việc.



## Vì sao `git reset --hard` nguy hiểm khi bạn yêu cầu Claude “quay lui”?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Trong ngôn ngữ tự nhiên, “quay lui” có nghĩa là “xem lại lịch sử”, không phải “phá hủy lịch sử”; theo mặc định, Claude nên đề xuất `git checkout`, không phải `reset --hard`; hãy cấu hình bảo vệ trong CLAUDE.md.

</div>

Một yêu cầu “lưu trạng thái hiện tại và quay lại lần push gần nhất” có thể dẫn đến các lệnh sau:

```bash
git stash save "WIP: Tracker enter/leave disabled + fsSyncModule fix"  # saved uncommitted changes
git reset --hard 35eb731                                                # destroyed commits d63695e..882e618
```

Lệnh đầu tiên đúng—nó lưu các thay đổi chưa commit vào stash. Lệnh thứ hai mang tính phá hoại: nó viết lại branch về commit `35eb731`, khiến mọi commit giữa commit đó và `882e618` trở thành orphan. Theo mặc định, các commit orphan vẫn nằm trong `.git/objects/` cho đến khi `git gc` chạy, thường tự động xảy ra trong vòng hai tuần. Nhưng nếu lúc đó bạn không biết phải làm gì, thời gian đã bắt đầu chống lại bạn.

Lý lẽ rất đơn giản: trong ngôn ngữ tự nhiên, “quay lui”, “quay lại”, “khôi phục”, “hoàn nguyên” và “hoàn tác” có nghĩa là “xem lại” hoặc “trở về nơi an toàn”. Chúng không có nghĩa là “phá hủy lịch sử”. Lệnh `git reset --hard` phá hủy lịch sử—nó viết lại branch và loại bỏ các commit khỏi nhóm có thể truy cập qua HEAD. Một phương án an toàn là `git checkout <commit>`, tạo detached HEAD và cho phép bạn xem trạng thái cũ mà không động đến branch.

Điểm thực tế chính là hãy `git commit` trạng thái hiện tại trước mọi nhiệm vụ quan trọng, nhất là trước khi refactor nhiều tệp. Một commit sẽ biến mọi lỗi của Claude thành một lệnh `git checkout .` mà không làm mất công việc.

## git reflog cứu bạn sau một lần reset phá hoại như thế nào?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

`git reflog` hiển thị lịch sử cục bộ của mọi lần di chuyển HEAD trong repository—even cả các commit bị loại bỏ bằng `git reset --hard` hoặc force-push. Theo mặc định, mỗi lần di chuyển được lưu trong 90 ngày. Nếu Claude (hoặc bạn hay người khác) phá hủy commit bằng một lệnh phá hoại, `git reflog` sẽ hiển thị hash của chúng và bạn có thể khôi phục branch bằng `git reset --hard <reflog-hash>`.

</div>

Sau một lần reset phá hoại, hãy chạy `git reflog` ngay lập tức:

```bash
git reflog
```

Kết quả trông như sau:

```
35eb731 HEAD@{0}: reset: moving to 35eb731
882e618 HEAD@{1}: commit: middleware refactoring complete
d63695e HEAD@{2}: commit: leaveRemove method finalized
1f9c8a3 HEAD@{3}: commit: tracker enter/leave disabled
35eb731 HEAD@{4}: pull origin main
```

`HEAD@{1}` đến `HEAD@{3}` chính là những commit “bị phá hủy” đó. Chúng chưa biến mất khỏi object store cục bộ của git; chúng chỉ không còn có thể truy cập qua branch. Để khôi phục chúng:

```bash
# Create a branch from the last “destroyed” commit
git branch recovered-work 882e618

# Or switch directly
git reset --hard 882e618
```

Sau đó, branch sẽ lại chứa toàn bộ lịch sử cho đến thời điểm xảy ra thảm họa.

**Giới hạn của Reflog:**

1.  **Chỉ ở máy cục bộ.** Reflog được lưu trong `.git/logs/HEAD`; nó không có trên repository từ xa. Nếu bạn force-push rồi xóa bản sao repository cục bộ, reflog cũng mất theo thư mục.
2.  **Mặc định là 90 ngày.** Các mục cũ hơn có thể bị xóa bởi git gc. Bạn có thể cấu hình bằng `git config gc.reflogExpire 200.days.ago`.
3.  **Không bao gồm thứ chưa từng nằm trong HEAD.** Nếu một commit chỉ nằm trong stash rồi stash bị phá hủy, reflog chỉ hiển thị trạng thái mới nhất của stash, không phải lịch sử bên trong nó.

**Quy tắc cho nhóm:** đừng bao giờ chạy `git gc --aggressive` ngay sau thảm họa. Trước tiên hãy điều tra bằng reflog và khôi phục; sau đó mới làm những việc khác. Và đừng xóa bản sao repository cục bộ cho đến khi chắc chắn mọi thứ cần thiết đã được push.

## Làm thế nào để bảo vệ dự án trước các lệnh git phá hoại thông qua CLAUDE.md?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Trong `CLAUDE.md` của dự án, hãy thêm một khối chỉ dẫn xác định lệnh git nào Claude có thể tự chạy, lệnh nào cần xác nhận rõ ràng và lệnh nào bị cấm nếu người dùng không đưa ra một cụm từ chính xác. Claude coi CLAUDE.md là system prompt của dự án và mặc định tuân theo các quy tắc này. Cách này biến một prompt “nguy hiểm” thành hai lệnh an toàn.

</div>

Lỗ hổng là Claude không có ngữ cảnh bảo vệ theo mặc định. Nó diễn giải “quay lui” thành `git reset --hard` vì về mặt kỹ thuật đó là một phương pháp hợp lệ. Hãy đặt biện pháp bảo vệ trong `CLAUDE.md`—tệp system prompt của dự án.

**Quy tắc tối thiểu** (chèn vào `CLAUDE.md` của bạn):

```markdown
## Git Safety Protocol

- NEVER run destructive git commands (push --force, reset --hard, checkout ., restore ., clean -f, branch -D) unless I explicitly request these actions. Taking unauthorized destructive actions is unhelpful and can result in lost work.
- When I say "roll back", "go back", "restore", "revert", "undo" - interpret as REVIEW commands: use `git log`, `git diff`, `git checkout <commit>` (creates detached HEAD), or `git stash` (preserves changes).
- ALWAYS ask for confirmation before ANY command that:
  - Changes HEAD position to a different commit on a branch
  - Modifies commit history
  - Could lose uncommitted work
  - Includes flags --hard, --force, --aggressive
- Before any destructive command, output a numbered comparison:
  - SAFE: use `git checkout <commit>` to view temporarily
  - DESTRUCTIVE: use `git reset --hard` to permanently destroy
- Wait for my explicit choice before executing.
```

**Quy tắc mở rộng** cho nhóm (thêm vào `CLAUDE.md` ở thư mục gốc repository):

```markdown
## Git Workflow Rules

- Commit ở mốc hoạt động. Trước WIP, chạy `git status`, `git diff`, chỉ stage tệp có tên đã xem bằng `git add -- path/to/file`, rồi xem diff staged trước commit. Đồng hồ nhắc xem lại, không cho stage cả working tree.
- Never use `git add .` or `git add -A` for commits by Claude. Only specify files by name, after `git status` + `git diff`.
- Before `git push --force` to main—stop and ask me. In feature branches, force-push cautiously, only if you're sure I'm willing to lose the previous version.
- When resolving merge conflicts, never choose "ours" or "theirs" immediately—show me both versions first, then I'll decide.
- `.gitignore` must contain `.env*`, `.claude/personal/`, `node_modules/`, `dist/`. If they're missing, add them.
```

Sau khi thêm các khối này, câu “quay lại lần push gần nhất” sẽ dẫn đến câu trả lời như sau:

> Tôi thấy 3 tệp chưa commit và có 4 commit kể từ lần push gần nhất. Có hai lựa chọn:
>
> 1.  AN TOÀN: tạo branch `view-last-push` bằng `git checkout <last-push-hash>`—tôi sẽ giữ nguyên mọi công việc, nhưng tạm thời hiển thị trạng thái của lần push đó.
> 2.  PHÁ HOẠI: `git reset --hard <last-push-hash>`—tôi sẽ phá hủy vĩnh viễn 4 commit và các thay đổi chưa commit. Chỉ có thể khôi phục bằng `git reflog` trong vòng 90 ngày. Bạn chọn cách nào?

Đó là nửa phút trò chuyện thay vì bốn giờ mất việc.

## 5 cách hoàn tác trong Claude Code là gì, và làm sao chọn cách phù hợp?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Khi xảy ra sự cố, có năm cấp độ ứng phó: `/rewind` (trong một phiên), `git checkout .` (thay đổi chưa commit), `git checkout <commit>` (quay về commit cũ mà không mất lịch sử), `git reset --hard <commit>` (đưa branch lùi lại và mất các commit phía trước), `git reflog` + khôi phục (thảm họa, mọi thứ đã biến mất). Mỗi cấp độ nặng nề và nguy hiểm hơn cấp độ trước.

</div>

Tình huống “Claude làm hỏng rồi, tôi cần khôi phục gấp” sẽ đi từ dưới lên theo bậc thang này. Luôn bắt đầu ở cấp độ 1.

**Cấp độ 1. `/rewind`—hoàn tác tức thì trong một phiên.**

Nhấn `Esc Esc` hoặc nhập `/rewind`. Chọn điểm trước khi xảy ra lỗi. Chọn chế độ (thường là `Restore code and conversation`). Một giây sau, bạn đã trở lại quá khứ và có thể bắt đầu lại. Xử lý được 80% trường hợp “Claude làm sai”.

**Cấp độ 2. `git checkout .`—hoàn tác mọi thay đổi chưa commit.**

```bash
git diff                    # first see what actually changed
git checkout .              # undo all uncommitted changes in all files
# or selectively:
git checkout -- path/to/file.ts   # only one file
```

Hữu ích khi `/rewind` không hoạt động (ví dụ, Claude tác động đến tệp qua Bash) hoặc khi cần hoàn tác ngoài lịch sử phiên. Mọi thay đổi chưa commit sẽ biến mất vĩnh viễn. Nếu có thể bạn sẽ hối tiếc, hãy chạy `git stash` trước (xem cấp độ 2.5).

**Cấp độ 2.5. `git stash`—cất thay đổi vào chỗ lưu tạm.**

```bash
git stash save "might still need this"
# return to a clean state (without changes)
# ...
# if you change your mind—restore from stash:
git stash pop
```

Đây là sự thỏa hiệp tốt giữa “mất vĩnh viễn” và “giữ nguyên như vậy”. Stash vẫn nằm trong máy cho đến khi được xóa rõ ràng.

**Cấp độ 3. `git checkout <commit>`—quay về commit cũ mà không mất lịch sử.**

```bash
git log --oneline               # find the hash of the right commit, e.g. abc1234
git checkout abc1234            # detached HEAD—view without changing anything
# like the state? create a branch from it:
git checkout -b recovery abc1234
# return:
git checkout main
```

Đây là cách “quay về tạm thời” an toàn. Detached HEAD không làm thay đổi branch; công việc hiện tại của bạn trong `main` (hoặc branch đang dùng) vẫn nguyên vẹn. Nếu muốn làm việc với trạng thái này, hãy tạo branch.

**Cấp độ 4. `git reset --hard <commit>`—đưa branch lùi về một điểm.**

⚠️ Có tính phá hoại. Các commit nằm sau hash được chỉ định sẽ trở thành orphan.

```bash
git reflog                                  # note the hash of the current state
git reset --hard abc1234                    # rewrite the branch
# found a mistake? return through reflog:
git reset --hard HEAD@{1}                   # to where you were before the reset
```

Chỉ sử dụng nếu bạn chắc chắn không cần các commit phía trước. Và luôn kiểm tra `git reflog` TRƯỚC khi reset để biết đường quay lại nếu đổi ý.

**Cấp độ 5. `git reflog` + khôi phục—tình huống thảm họa.**

Ai đó (Claude, bạn hoặc đồng nghiệp) đã chạy `git reset --hard` hoặc force-push và xóa mất công việc. Bạn cần làm gì?

```bash
git reflog                                          # look for the last hash before the disaster
git branch recovered HEAD@{N}                       # create a branch from it
git checkout recovered                              # switch to it
git diff main                                       # compare with the current state
git checkout main && git merge recovered            # restore into main, if you're sure
```

Nếu reflog đã bị xóa (theo mặc định sau 90 ngày), phương án cuối cùng là `git fsck --lost-found`, lệnh này sẽ hiển thị các commit mồ côi trong `.git/objects/`. Đây gần như là khảo cổ học, nhưng đôi khi có hiệu quả.

**Quy tắc chọn cấp độ:**

| Chuyện gì đã xảy ra | Cấp độ |
|-----------------------------------------------|-----------------------------|
| Claude viết lại 3 tệp theo cách sai | 1\. `/rewind` |
| Tôi đã thử, không thích, phiên cũng không giúp được | 2\. `git checkout .` |
| Tôi tự làm hỏng, tiếc nếu mất, có thể sẽ khôi phục | 2.5. `git stash` |
| Tôi đã commit; cần quay lại một commit | 3\. `git checkout <commit>` |
| Tôi chắc chắn không cần các commit phía trước | 4\. `git reset --hard` |
| Đã xóa bằng lệnh phá hoại | 5\. `git reflog` |

## Làm sao bảo vệ dự án để không có gì cần hoàn tác?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Cách hoàn tác tốt nhất là không cần phải hoàn tác. Ba quy tắc bảo vệ: xem tiến độ mỗi 30 phút và commit mốc chạy được bằng cách chỉ stage đường đã kiểm; thêm các dòng `.claude/personal/` và `.env*` bắt buộc vào `.gitignore`; thực hiện thử nghiệm lớn trên branch riêng bằng `git checkout -b experiment-<name>`. Cách này thu hẹp khoảng khôi phục tệp đã commit; hệ thống ngoài và việc chưa commit vẫn cần kế hoạch riêng.

</div>

**Quy tắc 1. Commit mỗi 30 phút.**

Đừng đợi đến khi “xong nhiệm vụ”. Hãy commit mọi bước trung gian đang hoạt động. Nội dung commit có thể là bất cứ gì; điều quan trọng là Claude (hoặc bạn) có thể quay về trạng thái hoạt động bằng một lệnh `git checkout`.

```bash
# at the beginning of a task
git status                        # xem mọi đường staged và unstaged
git diff                          # xem thay đổi
# Thay đường mẫu bằng tệp thực đã kiểm.
git add -- path/to/file.ts
git diff --cached                 # xác nhận đúng phần sẽ commit
git commit -m "wip: starting User schema migration"

# after 30 minutes (or after the first working iteration)
git status
git diff
git add -- path/to/file.ts         # đường thực đã xem, không wildcard thư mục
git diff --cached
git commit -m "wip: User schema is ready, migration applied locally"

# at the end of the task—a meaningful commit
git reset --soft HEAD~2           # combine the three wip commits into one
git commit -m "feat(auth): add lastLoginAt field to User table"
```

Nếu thêm nhắc PostToolUse, giữ cùng quy tắc xem và stage đường tường minh. Đừng biến timer thành auto-commit chưa kiểm: sửa ngoài việc hoặc tệp đã stage từ trước có thể lọt commit.

**Quy tắc 2. `.gitignore` tối thiểu.**

Các dòng này cần có ở thư mục gốc của dự án:

```gitignore
# secrets
.env
.env.local
.env.*.local

# local Claude Code settings (not pushed to the team repository)
.claude/personal/
.claude/sessions/
.claude/file-history/

# dependencies and build
node_modules/
dist/
.next/
build/
```

Tôi giữ thư mục `.claude/personal/` cho các thử nghiệm và ghi chú riêng, không được đưa vào repository dùng chung. Các thư mục `.claude/sessions/` và `.claude/file-history/` là nơi lưu trữ cục bộ của Claude Code; chúng không thuộc repository, chiếm nhiều dung lượng và gắn với một máy cụ thể.

**Quy tắc 3. Thử nghiệm trên branch riêng.**

Nếu nhiệm vụ lớn (refactor 10+ tệp, chuyển sang cơ sở dữ liệu mới, viết lại một module), đừng làm trên branch chính:

```bash
git checkout -b experiment/auth-rewrite
# work, commit every 30 minutes
# if it works:
git checkout main
git merge experiment/auth-rewrite
# if it doesn't:
git checkout main
git branch -D experiment/auth-rewrite     # delete the branch
# that's it, the main branch is intact
```

Thói quen đơn giản này biến “Claude phá hỏng dự án” thành “Claude phá hỏng một branch, tôi xóa nó và chúng ta bắt đầu lại”.

**Quy tắc 4. Dùng `git tag` trước các thao tác nguy hiểm.**

Trước database migration, refactor lớn hoặc cập nhật dependency, hãy tạo tag:

```bash
git tag pre-prisma-migration-v2
# work
# something went wrong:
git reset --hard pre-prisma-migration-v2
# or just take a look:
git checkout pre-prisma-migration-v2
```

Tag là một con trỏ có tên đến commit mà bạn sẽ không mất ngay cả khi dọn dẹp reflog.

## Tiếp theo: hoàn tác gắn với context engineering như thế nào?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Điểm chính trong phần này">

Điểm chính

Hoàn tác không phải một kỹ năng riêng mà là một phần của việc quản lý ngữ cảnh phiên Claude Code. Khi biết lúc nào nhấn `/rewind`, lúc nào `git commit` và lúc nào `git stash`, bạn đang quản lý cả quy trình làm việc chứ không chỉ một lệnh. Điều này thuộc về **Context Engineering**. Không có nó, Claude hành xử như một trợ lý thông thường; có nó, Claude giống một công cụ có thể dự đoán.

</div>

Ba cấp độ hoàn tác này là cơ sở hạ tầng cho một kỹ năng: biết cách khôi phục trạng thái khi có sự cố. Bản thân kỹ năng đó khá hẹp. Nhưng khi kết hợp với các công cụ context engineering khác, nó trở thành điều gì đó lớn hơn.

Plan Mode không cho phép bạn viết mã ngay lập tức—trước tiên là kế hoạch, sau đó là xác nhận, rồi mới thực hiện. Đây là cách phòng ngừa việc phải hoàn tác: bạn không viết thứ mà sau này phải hoàn tác vì kế hoạch đã được xem xét trước. Đọc thêm trong hướng dẫn về [Plan Mode trong Claude Code](https://ailoot.ai/blog/vi/claude-code-plan-mode/).

[CLAUDE.md](https://ailoot.ai/blog/vi/claude-md-template/) đặt ra các quy tắc mà Claude mặc định tôn trọng, bao gồm Git Safety Protocol đã đề cập ở trên. Đây là biện pháp bảo vệ chủ động trước các lệnh phá hoại.

[Second Brain](https://ailoot.ai/blog/vi/claude-code-second-brain/) cung cấp cho Claude bộ nhớ về dự án giữa các phiên—Claude biết bạn có mã nào, logic nghiệp vụ ra sao và trước đây đã thống nhất những gì. Bộ nhớ càng nhiều thì khả năng Claude làm sai càng thấp.

[Skills và subagents](https://ailoot.ai/blog/vi/claude-code-skills-library/) là phương pháp của bạn được viết thành mã. Nếu quy trình git đúng được tích hợp trong Skill, sẽ không có subagent nào chạy `git reset --hard` mà không xác nhận.

Tất cả những điều này hợp lại thành **Context Engineering**. Quản lý ngữ cảnh trước prompt, không phải trong lúc thực hiện. Đọc thêm tại [context engineering là gì](https://ailoot.ai/blog/vi/context-engineering/).

Hoàn tác là tuyến phòng thủ cuối cùng. Plan Mode + CLAUDE.md + Second Brain + Skills là bốn tuyến đầu tiên. Khi chúng được thiết lập, việc hoàn tác sẽ hiếm khi xảy ra và xử lý nhanh chóng. Nếu không có chúng, hoàn tác trở thành nghi thức hằng ngày.

<div class="section" role="doc-bibliography" aria-label="Nguồn">

### Nguồn

- [Tài liệu Anthropic - Checkpointing](https://code.claude.com/docs/en/checkpointing)
- [Tài liệu Anthropic - What's new (Tuần 20, 11-15 tháng 5 năm 2026)](https://code.claude.com/docs/en/whats-new)
- [Tài liệu Anthropic - Permission Modes](https://code.claude.com/docs/en/permission-modes)
- [Tham chiếu Git - reflog](https://git-scm.com/docs/git-reflog)

</div>

Hoàn tác bắt đầu ở nơi việc lập kế hoạch kết thúc.





[Truy cập Ailoot](https://ailoot.ai/).

## Câu hỏi thường gặp

### Checkpoint WIP có nên dùng git add . không?

Không. Chạy `git status`, `git diff`, chỉ stage tệp có tên đã xem rồi kiểm tra `git diff --cached` trước commit. Lịch checkpoint không cho phép gom thay đổi ngoài việc hay đã stage từ trước.

### /rewind có hoàn tác migration cơ sở dữ liệu hoặc hành động API từ xa không?

Không. Hướng dẫn giới hạn checkpoint ở sửa tệp được hỗ trợ trong phiên. Cơ sở dữ liệu, Git từ xa và API cần cách khôi phục riêng; dùng Git hoặc bản sao lưu cho tệp ngoài phạm vi checkpoint.


## Ailoot · Công ty và danh mục dự án của công ty

Ailoot dựa trên kinh nghiệm vận hành tích lũy, cơ sở khách hàng lớn, dịch vụ ổn định và việc kiểm soát KPI liên tục.

Công ty và danh mục dự án của công ty: hàng triệu khách hàng; doanh số hàng tỷ mỗi tháng.

Ailoot áp dụng kinh nghiệm vận hành này để cung cấp quyền truy cập API vào các tính năng AI trong sản phẩm của khách hàng, tác tử, ứng dụng và quy trình tự động hóa.
