Сравнение инструментов
| Инструмент | Удобный GUI | Правка сообщения | Переупорядочивание / squash / удаление | Правка даты автора | Правка даты коммитера | Правка автора/email | Массовая замена (regex) |
|---|---|---|---|---|---|---|---|
git-knife |
✅ |
✅ |
🚧 планируется |
✅ |
✅ |
✅ |
✅ |
GitKraken |
✅ |
✅ |
✅ |
⚠️ только amend |
❌ |
⚠️ |
❌ |
Sublime Merge |
✅ |
✅ |
✅ |
❌ |
❌ |
⚠️ amend |
❌ |
Fork |
✅ |
✅ |
✅ |
❌ |
❌ |
⚠️ |
❌ |
SmartGit |
✅ |
✅ |
✅ |
⚠️ |
❌ |
✅ |
❌ |
git-cola |
◐ |
✅ |
✅ |
✅ |
❌ |
✅ |
❌ |
lazygit (TUI) |
◐ TUI |
✅ |
✅ |
❌ |
❌ |
⚠️ |
❌ |
git-filter-repo (CLI) |
❌ |
✅ |
через callback |
✅ |
✅ |
✅ |
✅ |
Обозначения: ✅ полноценная поддержка · ⚠️ возможно, но неудобно или ограниченно · ◐ устаревший или терминальный интерфейс · ❌ не поддерживается · 🚧 планируется.
Чистый десктопный графический интерфейс (GUI) для прямого редактирования метаданных коммитов — сообщения, даты автора, даты коммитера, имени и email автора.
Существующие GUI-клиенты (GitKraken, Sublime Merge, Fork, lazygit) хорошо справляются с переименованием и переупорядочиванием коммитов, однако считают даты коммитов практически неизменяемыми и не позволяют редактировать дату коммитера или идентификационные данные автора для произвольных коммитов. Инструменты, которые умеют переписывать эти метаданные (git-filter-repo, трюки с env при git rebase, git commit-tree), лишены графического интерфейса. git-knife закрывает этот пробел.
Инструмент не переизобретает git — он вызывает системный git CLI и пересобирает коммиты через git commit-tree, повторно используя оригинальное дерево каждого коммита, так что содержимое файлов гарантированно остаётся неизменным.
Отполированные GUI-клиенты хорошо справляются с переупорядочиванием и переименованием, но считают даты коммитов — особенно дату коммитера — практически неизменяемыми, и ни один из них не предлагает массовой замены по регулярным выражениям в данных об авторе. Инструменты, способные переписывать эти метаданные, не имеют GUI. git-knife — это пересечение двух миров: удобный GUI, редактирующий каждое поле, пакетно и безопасно.
Текущее состояние (MVP)
-
✅ Открыть репозиторий и выбрать любую локальную ветку для просмотра и редактирования — по её ref, без переключения, так что рабочее дерево никогда не затрагивается
-
✅ Редактирование сообщения, имени и email автора/коммитера, даты автора и даты коммитера
-
✅ Массовый поиск и замена по текстовым полям — дословный или по регулярному выражению (удобно для исправления неверного email во всей истории)
-
✅ Предварительный просмотр всех изменений перед применением
-
✅ Автоматическое создание резервной ref перед каждой перезаписью и её восстановление в один клик
-
✅ Предупреждение, если перезапись затронет уже отправленную (pushed) историю
-
✅ Поддержка подписанных коммитов — помечает их значком, предупреждает о снятии подписей при перезаписи и может заново подписать пересобранные коммиты вашим ключом
-
✅ Редактирование через merge-коммиты — пересобирает полный граф коммитов, сохраняя всех родителей каждого merge
-
⛔ Пока не реализовано: переупорядочивание / squash / удаление коммитов, работа со staging, ветками и удалёнными репозиториями
Требования
-
git (2.x)
-
Node.js + pnpm (
corepack enable pnpmилиnpm i -g pnpm) -
Rust (stable) — установить через https://rustup.rs
-
Системные зависимости Tauri v2 для Linux:
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
Первая сборка cargo загружает и компилирует крейты Tauri — это займёт несколько минут.
Сборка пакета
pnpm tauri build
|
Примечание
|
Для упаковки ( |
Автоматические релизы (GitHub Actions)
Файл .github/workflows/release.yml собирает нативные установщики для macOS, Linux и Windows с помощью tauri-action и прикрепляет их к черновику GitHub Release. Чтобы выпустить релиз, достаточно запушить тег:
git tag v0.1.0
git push origin v0.1.0
Или запустить сборку вручную из вкладки Actions репозитория. Подпись кода пока не настроена, поэтому сборки для macOS и Windows не подписаны — для ранних тестировщиков это приемлемо.
Редактирование истории и отправка изменений
Редактирование коммита
-
Откройте репозиторий (через «Обзор…» или вставив путь), затем выберите ветку из выпадающего списка — git-knife редактирует её по ref, не переключаясь на неё, так что рабочее дерево и текущий checkout остаются нетронутыми.
-
Нажмите на любой не-merge коммит, чтобы открыть его редактор.
-
Измените сообщение, имя/email автора или коммитера, даты. Изменённые строки подсвечиваются; поля дат сохраняют исходное смещение UTC коммита.
-
Нажмите Review & apply, проверьте предварительный просмотр старых и новых значений и подтвердите изменения.
git-knife переписывает только вашу локальную ветку. Он не обращается к удалённому репозиторию и не делает push за вас — отправка всегда остаётся на ваше усмотрение.
Массовый поиск и замена
Нажмите Bulk find & replace над таблицей коммитов, чтобы изменить текст сразу во многих коммитах:
-
Выберите целевые поля (сообщение, имя/email автора или коммитера — в любой комбинации).
-
Введите текст в поля Find / Replace. Включите Regex для поиска по шаблону с обратными ссылками
$1или оставьте выключенным для дословного поиска. По умолчанию включён режим Case-sensitive. -
Панель в реальном времени показывает количество совпадающих коммитов и замен. Нажмите Stage edits, чтобы превратить их в подсвеченные строки, затем используйте Review & apply как обычно.
Пример — перенести все коммиты со старого email на новый: выберите Author email + Committer email, в поле поиска введите old@example.com, в поле замены — new@example.com. Merge-коммиты также затрагиваются, а последовательные проходы применяются поверх предыдущих.
Отправка перезаписанной истории
Редактирование коммита меняет его хеш и хеши всех последующих коммитов, поэтому локальная ветка и удалённая расходятся. Обычный git push будет отклонён как non-fast-forward. Выполните push с lease (проверкой):
git push --force-with-lease origin <branch>
--force-with-lease отклоняет push, если удалённая ветка изменилась с момента последнего fetch, — это защищает от случайного затирания коммитов коллег. Предпочитайте эту опцию обычному --force, который пропускает такую проверку.
|
Примечание
|
git-knife показывает предупреждение «rewrites pushed history», если редактирование затрагивает коммиты, уже существующие в upstream. По возможности редактируйте только неотправленные коммиты — перезапись общей истории заставляет всех остальных заново синхронизироваться. |
После перезаписи общей истории
У всех, кто уже получил старые коммиты, теперь расходящаяся история. Каждый из них синхронизирует локальную ветку с новым состоянием удалённой:
git fetch origin
git reset --hard origin/<branch> # удаляет только локальные коммиты — сначала скоординируйтесь
Отмена перезаписи
-
В приложении: панель Backups восстанавливает состояние ветки до перезаписи одним нажатием.
-
Из командной строки: каждое применение сохраняет резервную ref —
git for-each-ref refs/knife-backup # найти tip до перезаписи
git reset --hard <backup-ref-or-hash> # вернуть ветку назад
git reflog также содержит старый tip. Если force-push уже был выполнен, восстановите ветку локально, а затем снова выполните git push --force-with-lease.
Подписанные коммиты
Перезапись коммита меняет его хеш, что делает недействительной любую GPG/SSH-подпись на нём (это вызывало обоснованную обеспокоенность на HN). git-knife обнаруживает подписанные коммиты по заголовку gpgsig в их raw-данных — независимо от верификации, так что SSH-подписи определяются даже без настроенного allowedSignersFile — и:
-
помечает их значком
signedв таблице, -
предупреждает в панели применения о том, сколько подписанных коммитов потеряют подпись,
-
предлагает переключатель re-sign, который заново подписывает пересобранные коммиты вашим настроенным ключом (
user.signingkey/gpg.format). Если re-sign включён, но ключ не настроен, применение безопасно завершается с ошибкой, не затронув ни одной ref.
Примечание о сигнатуре (прозрачность)
По умолчанию git-knife прикрепляет небольшую явную заметку к каждому перезаписанному tip-коммиту в отдельной notes ref, не затрагивая обычные заметки:
git notes --ref=git-knife show <commit> # прочитать заметку
git for-each-ref refs/notes/git-knife # редактировался ли этот репозиторий через git-knife?
В обычном git log она невидима (отдельная ref), но полностью доступна для обнаружения — никакого скрытого кодирования. Отключить её можно в любой момент через флажок 🔪 signature note в приложении (настройка сохраняется). Чтобы полностью удалить заметки из репозитория:
git update-ref -d refs/notes/git-knife
Как это работает
-
src-tauri/src/git.rs— единственное место, где запускаетсяgit. -
commits.rs—open_repo,list_commits(разбор с разделителями NUL/record-separator). -
rewrite.rs—preview_edits+apply_edits: пересобирает цепочку от самого раннего изменённого коммита до tip черезcommit-tree, затем сохраняет резервную ref и перемещает ветку с compare-and-swap по старому tip. -
backup.rs— выводит списокrefs/knife-backup/*и восстанавливает черезgit reset --hard.
Стратегия перезаписи проверяется на уровне git скриптом scratchpad/verify_engine.sh (воспроизводит точный процесс commit-tree и убеждается, что diff содержимого пуст).
Безопасность
Каждое применение создаёт refs/knife-backup/<branch>/<epoch>, указывающую на старый tip, прежде чем что-либо изменить. Ничто не удаляется принудительно; восстановление всегда доступно из панели Backups.