A fancy git worktree manager. You call it as mg through a shell wrapper.
Projects live at <project>/trunk, and every other worktree (PRs, feature branches) lives as a sibling folder next to trunk:
myproject/
βββ trunk/ # main worktree
βββ feat-login/ # mg work feat/login
βββ fix-typo/ # mg pr 42 (branch: fix/typo)
cargo install --git https://github.com/marc2332/gitThen wire the mg shell function into your rc:
# bash
eval "$(marcgit init bash)"
# zsh
eval "$(marcgit init zsh)"
# fish
marcgit init fish | source
# nushell β add to config.nu
marcgit init nushell | save -f ~/.config/nushell/marcgit.nu
# then: source ~/.config/nushell/marcgit.nuThe binary prints paths; the wrapper cds to them. Same trick zoxide and direnv use.
mg pr requires gh (GitHub CLI) to look up the PR's branch name.
| Command | What it does |
|---|---|
mg new <name> / mg n |
Create ./<name>/trunk and git init it. Jump in. |
mg clone <url> <name> / mg c |
Clone a repo into ./<name>/trunk. Jump in. |
mg work <branch> / mg w |
Create (or jump to) a sibling worktree for <branch>. Creates branch if new. |
mg pr <number> / mg p |
Fetch the PR via gh, create a worktree named after its head branch, jump in. |
mg trunk / mg t |
Jump to the project's trunk from any sibling worktree. |
mg list / mg l |
Print git worktree list for the current project. |
mg remove <branch> / mg r |
Remove the worktree and delete its branch. Jump back to trunk. |
mg prune <days> |
Remove sibling worktrees whose last commit is older than <days> days. Asks for confirmation; skips worktrees with modified or stashed files. -n / --dry-run to preview. |
mg init <shell> |
Print the shell wrapper for bash / zsh / fish / nushell. |
mg config init |
Write a default marcgit.toml at the project root. Print its path. |
mg config path |
Print the path of the marcgit.toml reachable from the current directory. |
mg new myproject # β ./myproject/trunk
mg clone https://github.com/user/repo.git foo # β ./foo/trunk
mg work feat/login # β ./myproject/feat-login (branch feat/login)
mg pr 42 # β ./myproject/fix-typo (PR #42's head branch)
mg trunk # β ./myproject/trunk
mg remove feat/login # removes worktree + branch
mg prune 30 # prune worktrees idle β₯ 30 days (asks first)
mg prune 30 -n # dry-run: just list what would be pruned- Slashes in a branch name become dashes in the folder β
feat/loginβfeat-login. No nested subfolders. mg workandmg prare idempotent: if the worktree already exists, they just jump.mg prrequiresgh(GitHub CLI) to look up the PR's head branch name.mg prunemeasures age by each worktree's last commit date (git log -1). It refuses to remove worktrees with uncommitted changes, untracked files, or stashes recorded against their branch.
Optional marcgit.toml at the project root (next to trunk/). mg config init writes the default:
init-submodules = true # pull submodules on `mg work` (default: true)Every command other than new, clone, and init needs to know which project you're in. It runs git worktree list --porcelain and picks the worktree whose folder is literally named trunk. That's the anchor β so don't rename it.
MIT Β© Marc EspΓn Sanz