βββββββ βββββββββββββββββββββββββββββββββ βββ
ββββββββ ββββββββββββββββββββββββββββββββββ βββ
βββ βββββββ βββ βββ ββββββ ββββββ βββ
βββ ββββββ βββ βββ ββββββ ββββββββββ
ββββββββββββ βββ βββ βββββββββββ ββββββ
βββββββ βββ βββ βββ βββββββββββ βββββ
Git, the way it should feel.
gitten covers the 20% of Git operations that solve 80% of daily friction β standardized branches, safe cleanup, fast cherry-picks, one-command syncing β all through a clean, interactive terminal UI.
No config files. No dependencies to install. A single binary that just works.
- Why gitten?
- Install
- Demo
- Quickstart β gitten vs native Git
- Features
- Quick Guide
- Architecture
- Development
- Contributing
- License
Git is powerful. It is also a command-line tool designed by kernel engineers for kernel engineers, and its daily-use ergonomics show it.
Here is what the average developer types before lunch on a normal workday:
git checkout -b feat/user-auth # hope the name format is right
git add .
git diff --staged # review what I'm about to commit
git commit -m "feat: add user auth" # conventional commits? which prefix again?
git push # "fatal: no upstream branch" β now what?
git push --set-upstream origin feat/user-auth
git log other-branch --oneline # need to cherry-pick that one fix
git cherry-pick a3f91bc
# CONFLICT β now manually editing files + running git cherry-pick --continue
git branch # which branches can I delete?
git branch -d feat/old-thing
git push origin --delete feat/old-thing # don't forget the remote!That is 12 commands to do 4 conceptual operations. Each one requires you to remember flags, formats, and sequences β and one wrong move means a conflict, a broken branch, or accidental data loss.
gitten collapses each of those operations into a single interactive flow:
- Type
gitten, pick from a menu, answer two questions, done. - Branch names are enforced and formatted for you.
- Diff preview before every commit.
- Missing upstream is detected and fixed automatically.
- Protected branches (
main,dev,master) can never be accidentally deleted. - Conflicts are guided step-by-step β no googling the recovery command.
It is not a replacement for Git. It is the interface Git never had.
curl -fsSL https://raw.githubusercontent.com/jmpanozzoz/gitten/main/install.sh | bashirm https://raw.githubusercontent.com/jmpanozzoz/gitten/main/install.ps1 | iexbrew tap jmpanozzoz/gitten
brew install gittenSupported platforms: macOS Apple Silicon Β· macOS Intel Β· Linux x64 Β· Linux ARM64 Β· Windows x64
gitten --versionThe install script is idempotent β running it again fetches the latest release and shows the delta:
β Updated v0.4.0 β v0.5.0. Run: gitten
β
β π± Gitten β Your Git assistant
β
β my-api Β· main Β· +87 β12 Β· 3 files
β
β What do you want to do?
β β π Sync
β β π½ Pull
β β πΏ New Branch
β β π Switch Branch
β β π¦ Stash
β β π Cherry Pick
β β π§Ή Clean Branches
β β β― More
β β πͺ Exit
β Έ Staging...
β +87 β12 lines staged
β
β +import { jwtMiddleware } from "./middleware/jwt";
β +app.use("/api", jwtMiddleware);
β -// TODO: add auth
β
β Commit message:
β feat: add JWT middleware
β
β Έ Committing...
β Έ Pushing...
β β Pushed to origin/feat/auth
β Switch to branch
β / feat_
β
β dev
β β― feat/login-page β matches highlighted
β feat/user-profile
β
β ββ navigate Β· Enter select Β· Esc cancel
β Branch type?
β β feat β fix β hotfix β chore β docs
β
β Short description:
β user authentication
β
β Έ Creating branch...
β β Switched to feat/user-authentication
β Έ Pulling latest changes...
β β Pulled. 4 file(s) changed.
β or β
β βΉ Already up to date.
β Select branches to delete 2 selected
β / feat_
β
β β feat/old-experiment
β β―β feat/user-profile
β β fix/typo-header
β (current branch never listed; main/dev/master shown but need extra confirm)
β
β Space toggle Β· Enter confirm Β· Esc cancel
This section walks through the most common daily workflows side by side. Each example shows what you would type in raw Git and what you do in gitten instead.
TL;DR: gitten replaces multi-step command sequences with a single interactive flow. You answer questions; gitten runs the commands.
With raw Git:
# You have to remember the naming convention yourself
git checkout -b feat/user-authentication
# Did I spell it right? Is the format correct? Did I use the right prefix?With gitten:
gitten β πΏ New Branch
β Branch type? β feat
β Description: user authentication
β Switched to feat/user-authentication
What gitten handles for you:
- Enforces
type/kebab-caseformat automatically. - Lowercases and strips special characters from your description.
- Warns you if the branch already exists instead of silently overwriting.
- AI can suggest the branch name slug from a free-text description.
With raw Git:
git add .
git diff --staged # manually review what you're committing
git commit -m "..." # remember conventional commits format
git push
# Fatal: The current branch has no upstream branch.
git push --set-upstream origin feat/user-authenticationThat's 4β5 commands in the best case, 6 when the upstream is missing (which it always is on a new branch).
With gitten:
gitten β π Sync
β +42 β3 lines staged
β +import { jwtMiddleware } ... β diff preview built-in
β Commit message: feat: add JWT middleware
β Pushed to origin/feat/user-authentication
What gitten handles for you:
- Stages all changes.
- Shows a diff preview before you commit β no
git diff --stagedneeded. - Detects a missing upstream and runs
push -u originautomatically. - Detects if the remote has unpulled changes and tells you to pull first instead of silently failing.
- AI can generate a conventional commit message from the diff.
With raw Git:
git pull
# 2 files changed, 14 insertions(+), 3 deletions(-)
# Already up to date.
# (both outputs look similar, easy to miss which one you got)With gitten:
gitten β π½ Pull
β Pulled. 4 file(s) changed.
β or β
βΉ Already up to date.
The difference is cosmetic but meaningful: gitten makes the two states visually distinct so you always know whether something actually changed.
With raw Git:
git stash # save work-in-progress manually
git checkout other-branch
# ... do stuff ...
git checkout feat/user-authentication
git stash pop # remember to restore β easy to forgetWith gitten:
gitten β π Switch Branch
β You have uncommitted changes. Stash them? β Yes
/ feat_ β type to filter all branches
β Switched to feat/login-page
β Stash restored automatically on return
What gitten handles for you:
- Real-time search filter across all branches β no more typing full names.
- Detects uncommitted work and offers to stash it before switching.
- Stash is restored when you come back, so nothing is silently lost.
With raw Git:
git log other-branch --oneline # find the hash β scroll through history
# a3f91bc feat: fix payment rounding error
git cherry-pick a3f91bc
# CONFLICT (content): Merge conflict in src/payment.ts
# After fixing: git cherry-pick --continue β or β git cherry-pick --abortThe sequence itself is not hard β but remembering --continue vs --abort under pressure, while you have a conflict open, is annoying.
With gitten:
gitten β π Cherry Pick
β Source branch: fix/payment-rounding
β Pick a commit:
a3f91bc feat: fix payment rounding error β last 15 shown
β Conflict detected. Resolve it, then:
ENTER to continue Β· ESC to abort
β Cherry-pick applied.
What gitten handles for you:
- Lists recent commits of any branch (count configurable in Settings, default 30) β no hash hunting.
- Pauses on conflict with clear instructions instead of leaving you with a broken state.
- ENTER runs
cherry-pick --continue, ESC runscherry-pick --abort.
With raw Git:
git branch # list everything
git branch -d feat/old-thing # local delete
git push origin --delete feat/old-thing # remote delete (easy to forget)
# Repeat for every branch you want to clean up
# Nothing stops you from deleting main or devWith gitten:
gitten β π§Ή Clean Branches
β Select branches to delete (current branch never listed)
β β feat/old-experiment
β β fix/typo-header
β Also delete from origin? β Yes
β Deleted 2 local + 2 remote branches.
What gitten handles for you:
- The current branch (
HEAD) is never listed;main,master,dev, anddevelopare listed but require an explicit extra confirmation before they can be deleted β so you can't fat-fingermainaway. - Multi-select with a search filter β clean 10 branches in one pass.
- Remote deletion is a single follow-up question, not a separate command per branch.
- Per-branch errors are warnings, not full aborts β if one remote delete fails (e.g. no permissions), the rest still complete.
With raw Git:
git bisect start
git bisect bad # mark current commit as broken
git bisect good v1.2.0 # mark a known-good commit
# Git checks out a midpoint commit
# You test manually, then:
git bisect good # or: git bisect bad
# Repeat 6β10 times
git bisect reset # don't forget this or your HEAD is detachedThis works β but the ceremony of bisect start / bad / good / reset is a lot to remember for something you use once a month.
With gitten:
gitten β β― More β π Find Bug Commit (Bisect)
β Last known-good commit: v1.2.0 Β· "release: version 1.2.0"
β Έ Checking out midpoint...
β Does this commit have the bug? β Yes β No
(repeat ~5 times)
β Bug introduced in: a3f91bc "feat: add discount rounding"
β HEAD reset to original branch.
What gitten handles for you:
bisect start / bad / goodare hidden β you just answer "does the bug exist here?".bisect resetruns automatically when done.- The culprit commit is shown with its message, not just the hash.
With raw Git:
# Scenario: you're deep in a feature and an urgent hotfix arrives
git stash # save current work
git checkout main
git checkout -b hotfix/payment-crash
# fix the bug
git commit -m "fix: prevent payment crash on null user"
git push
git checkout feat/my-feature # back to the feature
git stash pop
# Two terminal tabs, constant context switchingWith gitten:
gitten β β― More β ποΈ Worktrees
β Add worktree
β Directory: ../gitten-hotfix
β Branch: hotfix/payment-crash
β Worktree created at ../gitten-hotfix
Now ../gitten-hotfix is a second working copy of the repo, checked out on the hotfix branch. You can run both simultaneously in separate terminal tabs β no stashing, no context switching.
With raw Git:
git log --oneline # find the commit above the one you want to undo
git reset --soft HEAD~1 # soft: keeps changes staged
# or:
git reset HEAD~1 # mixed: keeps changes unstaged
# or:
git reset --hard HEAD~1 # hard: DELETES the changes β no undoThe three modes of git reset are frequently confused. --hard in particular has deleted more work than any other single command in Git's history.
With gitten:
gitten β β― More β β© Undo Commit
β Reset to which commit?
HEAD~1 "feat: add JWT middleware" β selected
β Mode?
β Soft (keep changes staged)
β Mixed (keep changes, unstage)
β Reset complete. Your changes are preserved.
--hard is not offered. If you want to discard all changes, that is a separate "Reset" flow with an explicit confirmation step.
| Operation | Raw Git (commands) | gitten (steps) |
|---|---|---|
| New branch with correct naming | 1 command + mental format lookup | 2 prompts |
| Stage β diff β commit β push | 4β5 commands (6 for new branches) | 1 flow, 1 confirmation |
| Switch branch with stash | 3 commands, manual pop later | 1 menu pick + 1 confirm |
| Cherry-pick with conflict handling | 2 commands + manual recovery | 1 flow, guided pause |
| Delete N branches + remotes | 2 commands Γ N | multi-select + 1 confirm |
| Bisect to find bad commit | 5+ commands + manual loop | guided yes/no loop |
| Worktrees for parallel work | 2 commands + mental bookkeeping | 2 prompts |
| Undo commit (safe modes only) | 1 command (but --hard danger lurks) | 2 prompts, --hard hidden |
| What it does | |
|---|---|
| π Sync | Stage β diff preview β optional AI code review β AI commit message β push. Auto-detects missing upstream. |
| π½ Pull | Pulls with upstream detection. Distinguishes "already up to date" from "N files changed". |
| πΏ New Branch | Enforces type/kebab-case-name. AI-suggested names. Prevents duplicates. |
| π Switch Branch | Real-time search filter across all local branches. Stashes uncommitted work if needed. |
| π¦ Stash | Apply, pop, or drop stashes interactively. |
| π Cherry Pick | Lists recent commits of any branch (count configurable in Settings, default 30). Guides through conflicts β ENTER continue, ESC abort. |
| π§Ή Clean Branches | Multi-select with search filter. Optionally removes from origin. Current branch never listed; protected branches need an extra confirm. |
| What it does | |
|---|---|
| ποΈ Worktrees | List, add, and remove git worktrees. Work on multiple branches in parallel in separate directories. |
| β© Undo Commit | Search and select how far back to reset. Soft or mixed mode. |
| β‘ Reset | Discard all local changes or reset to remote HEAD. |
| π Remotes | Add, change URL, or remove remotes. Handles git init for new repos. |
| π .gitignore | Add patterns from templates or AI-generated suggestions. |
| π₯ Purge History | Remove files from the entire git history (irreversible). Real-time search filter for large repos. |
| βοΈ Settings | Configure the AI provider (Anthropic / OpenAI) for smart suggestions. |
What gitten deliberately does NOT do: interactive rebase, hunk-level staging, GitHub API integration, config files. Sharp focus, zero configuration.
Five minutes to know everything. Open gitten and follow these flows:
gitten β πΏ New Branch
Pick a type (feat, fix, hotfix, chore, docs), type a short description.
gitten names the branch for you: feat/user-authentication.
Why: consistent names mean consistent history. feat/, fix/ prefixes let release automation infer version bumps automatically.
gitten β π Sync
Select the files you want to include, review the diff preview, type a commit message (or let AI suggest one), confirm push. If the branch has no upstream yet, gitten sets it automatically.
Best practice: commit messages in Conventional Commits format (feat: add login, fix: correct redirect). gitten uses them to calculate the next version number.
gitten β π½ Pull
Pulls and tells you exactly what changed ("4 files changed" or "already up to date").
When to do it: before starting new work and before pushing if you've been working for a while.
gitten β π Switch Branch
Type to filter. All local branches shown with last activity date. If you have uncommitted changes, gitten asks whether to stash them first.
gitten β π Cherry Pick
Choose the source branch, pick one commit from the last 15. If there's a conflict, gitten pauses and waits: ENTER to continue, ESC to abort.
When to use it: a fix was made on main and you need it on your feature branch without merging everything.
gitten β π§Ή Clean Branches
Multi-select with search filter. The current branch is never listed; main, master, dev, and develop are listed but require an explicit extra confirmation before deletion. Optionally delete from origin too.
Best practice: clean up after every PR merge. One branch per feature.
gitten β β― More β βοΈ Amend Last Commit
Three modes: message only, add staged files, or both. Use it when you forgot a file or have a typo in the commit message.
Important: only amend commits that haven't been pushed yet, or that you're OK force-pushing (own branch only).
gitten β β― More β π·οΈ Tag / Release
gitten reads your commits since the last tag, infers the version bump (patch/minor/major from fix:/feat:/feat!:), pre-fills the suggested version, creates the annotated tag, and optionally pushes it.
This is how releases work in this project: the tag push triggers CI which builds and publishes the binaries automatically.
gitten β β― More β π Find Bug Commit (Bisect)
Select the last commit you know was working. gitten does a binary search: it checks out commits and asks "does this have the bug?" until it finds the exact commit that introduced it. Resets HEAD automatically when done.
When to use it: you know a bug exists now but not when it appeared. Faster than manual git log archaeology.
gitten β β― More β ποΈ Worktrees
Add a worktree: choose a directory path and a branch. That branch opens in a separate directory β you can run both codebases simultaneously without stashing anything.
When to use it: you're in the middle of a feature and an urgent hotfix arrives. Add a worktree for hotfix/payment-crash, fix it there, push, and come back to your feature without touching your current work.
gitten β β― More β β© Undo Commit
Pick how far back to go. Soft reset (keeps changes staged) or mixed reset (keeps changes in working tree).
Soft vs mixed: use soft when you want to recommit with a different message or split into multiple commits. Use mixed when you want to review and re-stage everything from scratch.
All AI features are optional and clearly prompted β gitten never calls AI without asking first.
| Prompt | What it does |
|---|---|
| "Generate commit message with AI?" | Analyzes the staged diff and suggests a conventional commit message |
| "Review staged diff with AI?" | Flags potential bugs, hardcoded values, security issues before you commit |
| In Branch Creator | Suggests a branch name slug from your description |
| In .gitignore Manager | Suggests patterns based on your tracked files |
Configure under: gitten β β― More β βοΈ Settings
Clean Architecture with strict Single Responsibility. Each layer has exactly one reason to change.
src/
βββ index.ts # Entry point β version flag + error boundaries
βββ app.ts # Composition root β wires all layers, drives menu loop
β
βββ core/ # Business logic β the "What"
β βββ branch-creator.ts
β βββ branch-cleaner.ts
β βββ branch-switcher.ts
β βββ cherry-picker.ts
β βββ pull-flow.ts
β βββ sync-flow.ts
β βββ stash-manager.ts
β βββ amend-flow.ts
β βββ undo-commit.ts
β βββ reset-manager.ts
β βββ remote-manager.ts
β βββ gitignore-manager.ts
β βββ history-purge.ts
β βββ worktree-manager.ts
β βββ settings.ts
β βββ ai-suggester.ts
β βββ ports/ # Interfaces for dependency injection
β βββ git-client.port.ts
β βββ ui.port.ts
β
βββ git/ # Infrastructure β the "How" (talks to Git)
β βββ git-client.ts
β
βββ ui/ # Presentation β the "How" (talks to the human)
βββ prompts.ts
βββ search-select.ts # Real-time search component
βββ theme.ts
βββ go-back.ts
core/ depends on git/ and ui/ only through interfaces β every class is independently testable with mocks.
Requirements: Bun v1.2+
git clone https://github.com/jmpanozzoz/gitten.git
cd gitten
bun install
bun run dev # hot reload
bun test # 279 unit tests, no real git process spawned
bun run build # compile to ./gitten binaryTests follow TDD: write the failing test first, make it green, refactor. All core logic is unit-tested with mocked Git and UI dependencies.
- Branch off
devβ never offmain - Write tests first β Red β Green β Refactor
bun testmust pass with zero failures- Open a PR targeting
devwith a Conventional Commits title
MIT β see LICENSE for details.