reflog.md
markdown
| 1 | # `muse reflog` — HEAD and branch movement history |
| 2 | |
| 3 | The reflog is Muse's **undo safety net**. Every time HEAD or a branch pointer moves — commit, checkout, merge, reset, cherry-pick — Muse appends an entry to a per-ref journal. If you accidentally reset to the wrong commit, the reflog tells you exactly where HEAD was before. |
| 4 | |
| 5 | ## Storage |
| 6 | |
| 7 | ``` |
| 8 | .muse/logs/ |
| 9 | HEAD ← journal for the symbolic HEAD pointer |
| 10 | refs/ |
| 11 | heads/ |
| 12 | main ← journal for the main branch ref |
| 13 | feat/audio ← journal for the feat/audio branch ref |
| 14 | … |
| 15 | ``` |
| 16 | |
| 17 | Each file is an append-only sequence of lines in the format used by Git, so tooling that understands both formats works without translation. |
| 18 | |
| 19 | ## Subcommands |
| 20 | |
| 21 | ### `muse reflog` (default) |
| 22 | |
| 23 | Show the HEAD reflog, newest entry first. |
| 24 | |
| 25 | ``` |
| 26 | muse reflog [--branch <name>] [--limit N] [--all] |
| 27 | ``` |
| 28 | |
| 29 | | Flag | Default | Description | |
| 30 | |------|---------|-------------| |
| 31 | | `--branch`, `-b` | HEAD log | Show the named branch's reflog instead of HEAD | |
| 32 | | `--limit`, `-n` | 20 | Maximum entries to show | |
| 33 | | `--all` | false | List every ref that has a reflog | |
| 34 | |
| 35 | ### Output format |
| 36 | |
| 37 | ``` |
| 38 | @{0} cccccccc0000 (initial) 2026-03-19 14:22:01 UTC commit: add chorus |
| 39 | @{1} aabbccdd1234 (cccccccc0000) 2026-03-19 14:18:44 UTC checkout: moving from dev to main |
| 40 | @{2} aaaa0000ffff (aabbccdd1234) 2026-03-19 14:15:02 UTC commit: initial |
| 41 | ``` |
| 42 | |
| 43 | - `@{N}` — reflog index (0 = newest) |
| 44 | - First SHA-256 prefix — new commit |
| 45 | - SHA-256 in parentheses — previous commit (`initial` for the first entry) |
| 46 | |
| 47 | ## When entries are written |
| 48 | |
| 49 | | Operation | Entry | |
| 50 | |-----------|-------| |
| 51 | | `muse commit` | `commit: <message>` | |
| 52 | | `muse checkout <branch>` | `checkout: moving from X to Y` | |
| 53 | | `muse checkout -b <branch>` | `branch: created from X` | |
| 54 | | `muse merge <branch>` | `merge: <branch> into <current>` | |
| 55 | | `muse reset` | `reset (soft/hard): moving to <sha12>` | |
| 56 | |
| 57 | ## Agent workflows |
| 58 | |
| 59 | ### Undo an accidental reset |
| 60 | |
| 61 | ```bash |
| 62 | # Find HEAD before the reset: |
| 63 | muse reflog --limit 5 |
| 64 | |
| 65 | # Restore: |
| 66 | muse reset <sha-from-reflog> |
| 67 | ``` |
| 68 | |
| 69 | ### Automated safety checkpoint |
| 70 | |
| 71 | ```bash |
| 72 | # Before a risky operation, note the current HEAD: |
| 73 | HEAD=$(muse plumbing rev-parse HEAD) |
| 74 | |
| 75 | # Do the risky operation… |
| 76 | muse reset --hard some-old-commit |
| 77 | |
| 78 | # If it went wrong, restore using the reflog: |
| 79 | muse reflog |
| 80 | muse reset "$HEAD" |
| 81 | ``` |
| 82 | |
| 83 | ### Pipeline inspection |
| 84 | |
| 85 | ```bash |
| 86 | # How many commits happened today? |
| 87 | muse reflog --branch main | grep "$(date +%Y-%m-%d)" | wc -l |
| 88 | ``` |
| 89 | |
| 90 | ## Security notes |
| 91 | |
| 92 | The reflog files are append-only by design. Entries are never modified after being written. The log paths are validated through the same `contain_path` primitive used throughout Muse — no path traversal is possible via branch names. |