Tooling gotcha — do NOT trust RTK-filtered git log/--graph for history rewriting

When RTK (the token-optimizing CLI proxy that auto-rewrites git …rtk git … via a Claude Code hook) filters git log output — especially git log --oneline --graph — it drops merge commits from the displayed list. The result is a deceptively linear-looking graph: a merge commit gets collapsed out of view, so a child commit appears to descend from the merge’s first parent’s parent. Trusting this for a squash / rebase / reset operates on the wrong commit range and can lose work.

This gotcha surfaced during git history surgery on esign_css (update/customization/instacash-2026-05-27 branch). See esign-css-instacash-orphan-history for the broader esign_css instacash history shape.

The symptom (concrete case)

RTK-filtered git log --oneline --graph rendered an apparently linear chain and collapsed merge commit 27e6cc7 (a real two-parent merge) out of the displayed list. This made it look like:

  • 9cce25f’s parent was 5d5b407

…when its actual parent was the merge 27e6cc7. Operating on the visible “parent” would have squashed/reset across the merge boundary and dropped a parent’s worth of history.

Why it happens

RTK’s output filter elides commit lines it treats as noise; merge commits’ own list lines get filtered, so a merge silently disappears from --oneline/--graph even though it is structurally present in the DAG.

Reliable patterns for git surgery under RTK

Use parent-aware / plumbing commands that survive filtering

These expose the real DAG even when a merge’s own log line is filtered out.

Expose parents in the log itself (the %p field shows actual parent SHAs, so merges are visible by their 2+ parents even if their own list line is filtered):

git log --pretty='%h | %p | %s'

Filter-proof plumbing (porcelain-free, RTK leaves these intact):

git rev-list --parents -n 1 <sha>      # one commit's parents (2+ SHAs = a merge)
git rev-list --count A..B              # exact commit count in a range
git rev-parse <sha>                    # resolve a ref to a full SHA
git rev-parse '<sha>^{tree}'           # the tree (content) hash at a commit

rtk proxy <cmd> runs a raw, unfiltered command — but the user may prefer you avoid it; reach for the parent-aware / plumbing commands above first.

Verify a squash/rebase preserved content — compare TREE hashes

For Agents

A squash or rebase must change history only, never content. Prove zero content change by comparing the tree hash before and after — an identical tree hash is cryptographic proof the working content is byte-identical.

git rev-parse 'HEAD^{tree}'   # capture BEFORE the operation
# … perform the squash / rebase …
git rev-parse 'HEAD^{tree}'   # must equal the captured value

If the two tree hashes match, only the history was restructured. If they differ, content changed — stop and investigate.

Reusable technique — non-interactive squash of the latest N commits

git rebase -i is unavailable in this harness, so squash the latest N commits with a soft reset instead:

git branch backup/<name> HEAD        # 1. backup ref first — trivial rollback
git diff --cached --quiet            # 2. guard: nothing staged (must exit 0)
ORIG=$(git rev-parse 'HEAD^{tree}')  #    capture original tree hash
git reset --soft <base>              # 3. move HEAD back, keep all changes staged
git commit -m "<msg>"                # 4. one new commit on top of <base>
test "$(git rev-parse 'HEAD^{tree}')" = "$ORIG" && echo OK   # 5. tree-hash equality
  • <base> is the commit you want the single squashed commit to sit on top of — derive it from git log --pretty='%h | %p | %s' or git rev-list --parents, not from a filtered --graph.
  • Step 1 (backup ref) makes rollback git reset --hard backup/<name>.
  • Step 2 ensures the squash doesn’t silently absorb unrelated staged changes.
  • Step 5 is the proof gate — identical tree hash means zero content change, history-only restructure.
  • esign-css-instacash-orphan-history — esign_css customization/instacash is a single squashed orphan; same family of “the usual git tooling misleads you here” hazards (no merge base, meaningless rev-list --count A..B).
  • RTK — the token-optimizing proxy whose output filtering causes this gotcha.
  • instacash-update-2026-05-27-status — the 2026-05-27 InstaCash devel-update wave during which this surgery happened.
  • esign — esign_css / eSign service overview.