An open-source CLI utility tool for having a beautiful interactive command line ui for hard-forking or nuking a repo. It also has a revert helper that give you an interactive ui to revert to specifc commit hashes.
gitmust be installed and credentials configued. it uses your own git cli and credentials under the hood.
One-off (no global install)
bunx hardfork@latest
#or
npx hardfork@latestGlobal install:
bun i -g hardfork@latest
npm i -g hardfork@latest
# then invoke `hardfork` directly (no bunx prefix)
hardfork --help
hardfork nuke --help
hardfork revert --helpClone a source repo, optionally point origin at a new empty repo, and push.
| Step | Interactive | Flags |
|---|---|---|
| Source URL | Prompt | --source <url> or first positional argument |
| Clone location | Normal vs temp dir | --normal (default) / --temp |
| Branch scope | Current branch, specific branch, or all branches | --current-branch-only, --branch <name>, --all-branches |
| History | Full clone vs shallow depth vs single fresh commit | --history, --depth <n>, --no-history |
| New remote | Optional URL | --remote <url> (--temp requires --remote) |
| Push | Confirm | --push / --no-push; temp mode always pushes |
Global options: -y/--yes skip prompts (you must pass everything required), -h/--help, -v/--version.
Normal clone: --dir <path> sets the local folder (default under cwd from repo name); non-interactive -y defaults the dir name from the source slug.
Temporary clone: clones under the system temp dir, pushes, then deletes the clone.
If the destination remote rejects the first push (non-fast-forward / non-empty remote), interactive mode can:
- Pick a branch when multiple remote branches exist, or nuke all branches (force-push one primary branch
main/master, delete the rest). - Preserve remote history: either one new commit that replaces files with your fork’s tree, or replay the source’s commits on top (cleanup commit + linear replay with metadata).
- Force overwrite: force-push and replace remote history on that branch.
With -y, a rejected push exits with a hint to rerun without -y so you can choose a resolution.
Make the repo empty by either removing tracked files or pruning branches. Scope: one branch, all branches, or branch-pruning mode.
| Mode | Behavior |
|---|---|
| Preserve history | New commit(s) that delete all files (history stays). |
| Wipe history | Fresh orphan-style history per branch: force-push empty trees (destructive). |
| Branches only | Delete remote branches and keep/create one default branch. |
Options
| Flag | Purpose |
|---|---|
--preserve-history |
Keep commits; empty tree in new commit(s). |
--wipe-history |
Rewrite with fresh root / force-push (irreversible). |
--branch <name> |
Branch to nuke (default: remote HEAD, fallback main). |
--all-branches |
Nuke every branch on the remote. |
--branches-only |
Delete remote branches, leave one default branch. |
--default-branch <name> |
Default branch kept/created for --branches-only (default main). |
-m, --message <text> |
Commit message for the nuke commit. |
-y, --yes |
Skip prompts (repo URL and mode flags required where applicable). |
Move a branch to a given commit (7–40 hex).
| Mode | Behavior |
|---|---|
Keep history (--keep-history) |
git revert each commit after the target (ancestor check); push (non-destructive). |
Destructive (--destructive) |
git reset --hard to commit + force-push (rewrites remote branch). |
Options: --branch <name> (default: remote HEAD symref or main), -y/--yes.
With Bun (bunx runs the published CLI without installing globally):
# Interactive hard fork
bunx hardfork
# Scripted: clone, collapse history, push to new repo, delete temp clone
bunx hardfork --source https://github.com/org/old.git \
--remote git@github.com:you/new.git --temp --no-history -y
# Keep full history, normal folder, push
bunx hardfork --source https://gitlab.com/group/repo.git \
--remote git@gitlab.com:you/fork.git --dir my-fork --history --push -y
# Keep only the latest 25 commits
bunx hardfork --source https://github.com/org/old.git \
--remote git@github.com:you/new.git --depth 25 --push -y
# Clone and push all source branches
bunx hardfork --source https://github.com/org/old.git \
--remote git@github.com:you/new.git --all-branches --history --push -y
# Empty one branch, keep history
bunx hardfork nuke https://github.com/you/repo.git --preserve-history --branch main -y
# Force-empty all branches (dangerous)
bunx hardfork nuke https://github.com/you/repo.git --wipe-history --all-branches -m "reset" -y
# Delete extra remote branches, keep/create one default branch
bunx hardfork nuke https://github.com/you/repo.git --branches-only --default-branch main -y
# Non-destructive revert (new commits)
bunx hardfork revert https://github.com/you/repo.git abc1234 --keep-history --branch main -y
# Rewind branch and force-push
bunx hardfork revert git@github.com:you/repo.git abc1234 --destructive -yIf you installed with npm install -g hardfork, drop the bunx prefix and run hardfork … instead.
- Website: ardastroid.com
- Email: hello@ardastroid.com
- GitHub: @ardzero
MIT License
Copyright (c) 2026 Ard Astroid ardastroid@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------+
| Start: runHardfork |
+--------------------+
|
v
+------------------------------+
| Resolve source URL |
| (--source / positional / UI) |
+------------------------------+
|
v
+------------------+
| Source valid + |
| readable remote? |
+------------------+
| yes | no
| v
| +----------------------+
| | Prompt change source |
| | and retry loop |
| +----------------------+
|____________________^
|
v
+------------------------------+
| Choose clone mode |
| normal / temp |
+------------------------------+
|
v
+------------------------------+
| Preflight probe |
| branches + default + size + |
| commit count |
+------------------------------+
|
v
+------------------------------+
| Configure branch scope |
| current / specific / all |
+------------------------------+
|
v
+------------------------------+
| Configure history |
| full / depth N / no-history |
+------------------------------+
|
v
+----------------------+
| Expensive/risky |
| combination? |
+----------------------+
| no | yes
| v
| +----------------------+
| | Reconfigure loops: |
| | history + branches |
| +----------------------+
|____________________^
|
v
+------------------------------+
| Transfer estimate screen |
| continue / reconfigure loop |
+------------------------------+
|
v
+------------------------------+
| Resolve destination remote |
| validate != source |
| check write access |
+------------------------------+
|
v
+------------------------------+
| Resolve push intent |
| temp => always push |
+------------------------------+
|
v
+------------------------------+
| Resolve local path |
| temp dir OR --dir/prompt |
+------------------------------+
|
v
+------------------------------+
| Clone repo (with selected |
| branch/history mode) |
+------------------------------+
|
v
+------------------+
| Clone success? |
+------------------+
| yes | no
| v
| +----------------------+
| | Show error, cleanup |
| | temp dir, exit |
| +----------------------+
|
v
+------------------------------+
| Post-clone rewrite |
| no-history: collapse commit |
| depth: materialize shallow |
+------------------------------+
|
v
+------------------+
| New remote set? |
+------------------+
| yes | no
| v
| +----------------------+
| | Warn: origin still |
| | points to source |
| +----------------------+
v
+------------------------------+
| Update origin URL |
| (special handling for |
| multi-branch no-history) |
+------------------------------+
|
v
+----------------------+
| shouldPush && remote?|
+----------------------+
| no | yes
| v
| +----------------------+
| | Push flow |
| +----------------------+
| |
| v
| +----------------------+
| | Multi-branch? |
| +----------------------+
| | yes | no
| v v
| +----------------+ +-------------------------+
| | Keep/Nuke/Abort| | Push single branch |
| | destination | | if non-FF => resolve: |
| | branches | | force / preserve / |
| | then push | | replay / nuke-all |
| +----------------+ +-------------------------+
|___________ _________________________________/
\/
+----------------------+
| Finalize |
| temp: delete folder |
| normal: print cd |
+----------------------+
|
v
+--------+
| Done |
+--------+
The flow above mirrors the implementation in src/commands/hardfork.ts: preflight-driven branching, repeated reconfigure guards for risky combinations, destination safety checks, and separate push conflict strategies for multi-branch vs single-branch flows.