[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-94623":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":13,"stars30d":14,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":15,"rankGlobal":8,"rankLanguage":8,"license":8,"archived":16,"fork":16,"defaultBranch":17,"hasWiki":18,"hasPages":16,"topics":19,"createdAt":8,"pushedAt":8,"updatedAt":20,"readmeContent":21,"aiSummary":22,"trendingCount":13,"starSnapshotCount":13,"syncStatus":23,"lastSyncTime":24,"discoverSource":25},94623,"git-knife","TheRealYT\u002Fgit-knife","TheRealYT",null,"TypeScript",333,10,1,0,114,47.12,false,"main",true,[],"2026-08-24 04:01:22","# git-knife 🔪\n\n*Stab your git history into shape — every commit's message, author, and dates,\nedited like a table.*\n\n![git-knife screenshot](docs\u002Fscreenshot.png)\n\nA clean desktop GUI for editing git commit metadata directly — **message,\nauthor date, committer date, author name\u002Femail**.\n\nExisting GUIs (GitKraken, Sublime Merge, Fork, lazygit) reword and reorder well\nbut treat commit **dates** as effectively immutable and don't expose committer\ndate \u002F author identity for arbitrary commits. The tools that *can* rewrite that\nmetadata (`git-filter-repo`, `git rebase` env tricks, `git commit-tree`) have no\nGUI. git-knife fills that gap.\n\nIt never reimplements git — it shells out to the system `git` CLI and rebuilds\ncommits with `git commit-tree`, reusing each commit's original tree so **file\ncontents are provably never changed**.\n\n## How it compares\n\n| Tool | Clean GUI | Reword msg | Reorder \u002F squash \u002F drop | Edit **author date** | Edit **committer date** | Edit author\u002Femail | Bulk find & replace (regex) |\n|------|:--:|:--:|:--:|:--:|:--:|:--:|:--:|\n| **git-knife** | ✅ | ✅ | 🚧 planned | ✅ | ✅ | ✅ | ✅ |\n| GitKraken | ✅ | ✅ | ✅ | ⚠️ amend-only | ❌ | ⚠️ | ❌ |\n| Sublime Merge | ✅ | ✅ | ✅ | ❌ | ❌ | ⚠️ amend | ❌ |\n| Fork | ✅ | ✅ | ✅ | ❌ | ❌ | ⚠️ | ❌ |\n| SmartGit | ✅ | ✅ | ✅ | ⚠️ | ❌ | ✅ | ❌ |\n| git-cola | ◐ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |\n| lazygit (TUI) | ◐ TUI | ✅ | ✅ | ❌ | ❌ | ⚠️ | ❌ |\n| git-filter-repo (CLI) | ❌ | ✅ | via callback | ✅ | ✅ | ✅ | ✅ |\n\nLegend: ✅ first-class · ⚠️ possible but awkward\u002Flimited · ◐ dated or terminal UI · ❌ not supported · 🚧 planned.\n\nThe polished GUIs reword and reorder well but treat commit **dates** — especially\nthe committer date — as effectively immutable, and none offer a bulk regex pass\nover author identity. The tools that *can* rewrite that metadata have no GUI.\ngit-knife is the intersection: a clean GUI that edits every field, in bulk, safely.\n\n## Status (MVP)\n\n- ✅ Open a repo and pick **any local branch** to view\u002Fedit — by its ref, no checkout, so your working tree is never touched\n- ✅ Edit message \u002F author name+email \u002F author date \u002F committer date \u002F committer name+email\n- ✅ Bulk find & replace across those text fields, literal or regex (great for fixing a wrong email everywhere)\n- ✅ Preview every change before applying\n- ✅ Automatic backup ref before each rewrite + one-click restore\n- ✅ Warns when a rewrite would touch already-pushed history\n- ✅ Signed-commit aware — badges signed commits, warns a rewrite strips signatures, and can **re-sign** with your key\n- ✅ Merge commits are locked (not editable in this version)\n- ⛔ Not yet: reorder \u002F squash \u002F drop, merge rewriting, staging\u002Fbranches\u002Fremotes\n\n## Requirements\n\n- **git** (2.x)\n- **Node.js** + **pnpm** (`corepack enable pnpm`, or `npm i -g pnpm`)\n- **Rust** (stable) — install via \u003Chttps:\u002F\u002Frustup.rs>\n- Linux system deps for Tauri v2: `webkit2gtk-4.1`, `libgtk-3`, `libayatana-appindicator3`, `librsvg2`\n  (Debian\u002FUbuntu: `sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev`)\n\n## Run (dev)\n\n```bash\npnpm install\npnpm tauri dev\n```\n\nThe first `cargo` build downloads and compiles the Tauri crates (a few minutes).\n\n## Build a bundle\n\n```bash\npnpm tauri build\n```\n\n> Packaging (`tauri build`) needs app icons. They're already committed under\n> `src-tauri\u002Ficons\u002F`; regenerate from any square PNG with\n> `pnpm tauri icon path\u002Fto\u002Ficon.png`. Dev runs don't need them.\n\n### Automated releases (GitHub Actions)\n\n`.github\u002Fworkflows\u002Frelease.yml` builds native installers for **macOS, Linux, and\nWindows** with [`tauri-action`](https:\u002F\u002Fgithub.com\u002Ftauri-apps\u002Ftauri-action) and\nattaches them to a draft GitHub Release. Cut a release by pushing a tag:\n\n```bash\ngit tag v0.1.0\ngit push origin v0.1.0\n```\n\n(or trigger it manually from the repo's **Actions** tab). No code signing is set\nup yet, so macOS\u002FWindows builds are unsigned — fine for early testers.\n\n## Editing history & pushing\n\n### Edit a commit\n\n1. **Open** a repository (Browse… or paste the path), then pick a **branch**\n   from the dropdown — git-knife edits it by its ref, without checking it out,\n   so your working tree and current checkout stay exactly as they are.\n2. Click any **non-merge** commit to expand its editor.\n3. Change the message, author\u002Fcommitter name, email, or dates. Edited rows are\n   highlighted; the date fields keep the commit's original UTC offset.\n4. Click **Review & apply**, check the old → new preview, and confirm.\n\ngit-knife rewrites **only your local branch**. It never contacts a remote and\nnever pushes for you — pushing is always your explicit step.\n\n### Bulk find & replace\n\nClick **Bulk find & replace** above the commit table to change text across many\ncommits at once:\n\n- Pick which fields to target (message, author\u002Fcommitter name, author\u002Fcommitter\n  email — any combination).\n- Enter **Find** \u002F **Replace**. Toggle **Regex** for pattern matching with `$1`\n  backreferences, or leave it off for a literal search. **Case-sensitive** is on\n  by default.\n- The panel live-counts matching commits and replacements. Click **Stage edits**\n  to turn them into highlighted rows, then **Review & apply** as usual.\n\nExample — move every commit from an old email to a new one: target *Author\nemail* + *Committer email*, find `old@example.com`, replace `new@example.com`.\nMerge commits are skipped, and successive passes compose.\n\n### Push a rewrite\n\nEditing a commit changes its hash **and the hash of every commit after it**, so\nyour local branch and the remote have diverged. A normal `git push` is rejected\nas *non-fast-forward*. Push with a lease:\n\n```bash\ngit push --force-with-lease origin \u003Cbranch>\n```\n\n`--force-with-lease` refuses the push if the remote moved since your last fetch,\nso you can't silently clobber a teammate's commits. Prefer it over plain\n`--force`, which skips that safety check.\n\n> git-knife shows a **\"rewrites pushed history\"** warning when your edit reaches\n> into commits that already exist on the upstream. If you can, edit only unpushed\n> commits — rewriting shared history forces everyone else to re-sync.\n\n### After rewriting shared history\n\nAnyone who already pulled the old commits now has divergent history. Each of them\nre-syncs their local branch to the new remote state:\n\n```bash\ngit fetch origin\ngit reset --hard origin\u002F\u003Cbranch>   # discards local-only commits — coordinate first\n```\n\n### Undo a rewrite\n\n- **In-app:** the **Backups** panel restores the pre-rewrite tip in one click.\n- **From the CLI:** every apply saved a backup ref —\n\n  ```bash\n  git for-each-ref refs\u002Fknife-backup      # find the pre-rewrite tip\n  git reset --hard \u003Cbackup-ref-or-hash>   # move the branch back\n  ```\n\n  `git reflog` also lists the old tip. If you already force-pushed, restore\n  locally and then `git push --force-with-lease` again.\n\n### Signed commits\n\nRewriting a commit changes its hash, which **invalidates any GPG\u002FSSH signature**\non it (a raised concern on HN). git-knife detects signed commits by their raw\n`gpgsig` header — independent of verification, so it catches SSH signatures even\nwithout an `allowedSignersFile` — and:\n\n- **badges** them `signed` in the table,\n- **warns** in the apply bar how many signed commits a rewrite would strip,\n- offers a **re-sign** toggle that re-signs the rebuilt commits with your\n  configured key (`user.signingkey` \u002F `gpg.format`). If re-signing is on but no\n  key is configured, the apply fails safely before touching any ref.\n\n### Signature note (transparent)\n\nBy default git-knife attaches a small, **disclosed** note to each rewritten tip\ncommit, on its own notes ref so it never touches your regular notes:\n\n```bash\ngit notes --ref=git-knife show \u003Ccommit>   # read it\ngit for-each-ref refs\u002Fnotes\u002Fgit-knife      # was this repo edited by git-knife?\n```\n\nIt's invisible in a normal `git log` (separate ref) but fully discoverable — no\nhidden encoding. Toggle it off anytime with the **🔪 signature note** checkbox in\nthe app (the setting is remembered). To strip it from a repo entirely:\n\n```bash\ngit update-ref -d refs\u002Fnotes\u002Fgit-knife\n```\n\n## How it works\n\n- `src-tauri\u002Fsrc\u002Fgit.rs` — the only place that spawns `git`.\n- `commits.rs` — `open_repo`, `list_commits` (NUL\u002Frecord-separator parsing).\n- `rewrite.rs` — `preview_edits` + `apply_edits`: rebuilds the chain from the\n  earliest edited commit to the tip via `commit-tree`, then saves a backup ref\n  and moves the branch with a compare-and-swap on the old tip.\n- `backup.rs` — lists `refs\u002Fknife-backup\u002F*` and restores via `git reset --hard`.\n\nThe rewrite strategy is validated at the git level by\n`scratchpad\u002Fverify_engine.sh` (reproduces the exact commit-tree flow and asserts\nthe content diff is empty).\n\n## Safety\n\nEvery apply creates `refs\u002Fknife-backup\u002F\u003Cbranch>\u002F\u003Cepoch>` pointing at the old tip\nbefore touching anything. Nothing is force-deleted; restore is always available\nfrom the Backups panel.\n","git-knife 是一款基于 Tauri 的桌面 GUI 工具，专用于安全地编辑 Git 提交元数据（提交信息、作者\u002F提交者姓名与邮箱、作者日期与提交者日期）。它通过调用系统 git CLI 和 git commit-tree 命令实现底层操作，不修改文件内容，确保历史重写过程可验证且工作区不受影响。支持批量正则查找替换、变更预览、自动备份与一键恢复，并能识别和重新签名 GPG 签名提交。适用于需修正提交时间戳、统一作者身份或清理敏感邮箱等合规性\u002F协作场景，尤其适合 Git 历史规范化、开源贡献整理及企业代码审计前的元数据治理。",2,"2026-08-13 02:30:03","CREATED_QUERY"]