Hacker News

Show HN: Git-knife - edit commit messages, authors, and dates like a spreadsheet

Stab your git history into shape - every commit's message, author, and dates, edited like a table. A clean desktop GUI for editing git commit metadata directly - message, author date, committer date, author name/email. Existing GUIs (GitKraken, Sublime Merge, Fork, lazygit) reword and reorder well but treat commit dates as effectively immutable and don't expose committer date / author identity for arbitrary commits. The tools that can rewrite that metadata (git-filter-repo , git rebase env tricks, git commit-tree ) have no GUI. git-knife fills that gap. It never reimplements git - it shells out to the system git CLI and rebuilds commits with git commit-tree , reusing each commit's original tree so file contents are provably never changed. | Tool | Clean GUI | Reword msg | Reorder / squash / drop | Edit author date | Edit committer date | Edit author/email | Bulk find & replace (regex) | |---|---|---|---|---|---|---|---| | git-knife | βœ… | βœ… | 🚧 planned | βœ… | βœ… | βœ… | βœ… | | GitKraken | βœ… | βœ… | βœ… | ❌ | ❌ | || | Sublime Merge | βœ… | βœ… | βœ… | ❌ | ❌ | ❌ | | | Fork | βœ… | βœ… | βœ… | ❌ | ❌ | ❌ | | | SmartGit | βœ… | βœ… | βœ… | ❌ | βœ… | ❌ | | | git-cola | ◐ | βœ… | βœ… | βœ… | ❌ | βœ… | ❌ | | lazygit (TUI) | ◐ TUI | βœ… | βœ… | ❌ | ❌ | ❌ | | | git-filter-repo (CLI) | ❌ | βœ… | via callback | βœ… | βœ… | βœ… | βœ… | Legend: βœ… first-class Β· The polished GUIs reword and reorder well but treat commit dates - especially the committer date - as effectively immutable, and none offer a bulk regex pass over author identity. The tools that can rewrite that metadata have no GUI. git-knife is the intersection: a clean GUI that edits every field, in bulk, safely. - βœ… Open a repo, list commits on the current branch - βœ… Edit message / author name+email / author date / committer date / committer name+email - βœ… Bulk find & replace across those text fields, literal or regex (great for fixing a wrong email everywhere) - βœ… Preview every change before applying - βœ… Automatic backup ref before each rewrite + one-click restore - βœ… Warns when a rewrite would touch already-pushed history - βœ… Merge commits are locked (not editable in this version) - β›” Not yet: reorder / squash / drop, merge rewriting, staging/branches/remotes - git (2.x) - Node.js + pnpm ( corepack enable pnpm , ornpm i -g pnpm ) - Rust (stable) - install via https://rustup.rs - Linux system deps for Tauri v2: webkit2gtk-4.1 ,libgtk-3 ,libayatana-appindicator3 ,librsvg2 (Debian/Ubuntu:sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev ) pnpm install pnpm tauri dev The first cargo build downloads and compiles the Tauri crates (a few minutes). pnpm tauri build Packaging ( tauri build ) needs app icons. They're already committed undersrc-tauri/icons/ ; regenerate from any square PNG withpnpm tauri icon path/to/icon.png . Dev runs don't need them. .github/workflows/release.yml builds native installers for macOS, Linux, and Windows with tauri-action and attaches them to a draft GitHub Release. Cut a release by pushing a tag: git tag v0.1.0 git push origin v0.1.0 (or trigger it manually from the repo's Actions tab). No code signing is set up yet, so macOS/Windows builds are unsigned - fine for early testers. - Open a repository (Browse… or paste the path). - Click any non-merge commit to expand its editor. - Change the message, author/committer name, email, or dates. Edited rows are highlighted; the date fields keep the commit's original UTC offset. - Click Review & apply, check the old β†’ new preview, and confirm. git-knife rewrites only your local branch. It never contacts a remote and never pushes for you - pushing is always your explicit step. Click Bulk find & replace above the commit table to change text across many commits at once: - Pick which fields to target (message, author/committer name, author/committer email - any combination). - Enter Find / Replace. Toggle Regex for pattern matching with $1 backreferences, or leave it off for a literal search. Case-sensitive is on by default. - The panel live-counts matching commits and replacements. Click Stage edits to turn them into highlighted rows, then Review & apply as usual. Example - move every commit from an old email to a new one: target Author email + Committer email, find o**@example.com , replace n**@example.com . Merge commits are skipped, and successive passes compose. Editing a commit changes its hash and the hash of every commit after it, so your local branch and the remote have diverged. A normal git push is rejected as non-fast-forward. Push with a lease: git push --force-with-lease origin --force-with-lease refuses the push if the remote moved since your last fetch, so you can't silently clobber a teammate's commits. Prefer it over plain --force , which skips that safety check. git-knife shows a "rewrites pushed history" warning when your edit reaches into commits that already exist on the upstream. If you can, edit only unpushed commits - rewriting shared history forces everyone else to re-sync. Anyone who already pulled the old commits now has divergent history. Each of them re-syncs their local branch to the new remote state: git fetch origin git reset --hard origin/ # discards local-only commits - coordinate first - In-app: the Backups panel restores the pre-rewrite tip in one click. - From the CLI: every apply saved a backup ref - git for-each-ref refs/knife-backup # find the pre-rewrite tip git reset --hard # move the branch back git reflog also lists the old tip. If you already force-pushed, restore locally and thengit push --force-with-lease again. By default git-knife attaches a small, disclosed note to each rewritten tip commit, on its own notes ref so it never touches your regular notes: git notes --ref=git-knife show # read it git for-each-ref refs/notes/git-knife # was this repo edited by git-knife? It's invisible in a normal git log (separate ref) but fully discoverable - no hidden encoding. Toggle it off anytime with the πŸ”ͺ signature note checkbox in the app (the setting is remembered). To strip it from a repo entirely: git update-ref -d refs/notes/git-knife src-tauri/src/git.rs - the only place that spawnsgit .commits.rs -open_repo ,list_commits (NUL/record-separator parsing).rewrite.rs -preview_edits +apply_edits : rebuilds the chain from the earliest edited commit to the tip viacommit-tree , then saves a backup ref and moves the branch with a compare-and-swap on the old tip.backup.rs - listsrefs/knife-backup/* and restores viagit reset --hard . The rewrite strategy is validated at the git level by scratchpad/verify_engine.sh (reproduces the exact commit-tree flow and asserts the content diff is empty). Every apply creates refs/knife-backup/ / pointing at the old tip before touching anything. Nothing is force-deleted; restore is always available from the Backups panel.

Read on Hacker News ↗ ← Back to News

Comments

No comments yet. Start the discussion.