An open API service indexing awesome lists of open source software.

https://github.com/marc2332/git

marcgit 🚧, a git worktree manager that I like
https://github.com/marc2332/git

git rust worktree

Last synced: 23 days ago
JSON representation

marcgit 🚧, a git worktree manager that I like

Awesome Lists containing this project

README

          

[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md)

# 🚧 marcgit

A fancy git worktree manager. You call it as `mg` through a shell wrapper.

Projects live at `/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)
```

## Install

```sh
cargo install --git https://github.com/marc2332/git
```

Then wire the `mg` shell function into your rc:

```sh
# 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.nu
```

The binary prints paths; the wrapper `cd`s to them. Same trick `zoxide` and `direnv` use.

**`mg pr` requires `gh`** (GitHub CLI) to look up the PR's branch name.

## Commands

| Command | What it does |
| -------------------------------- | ------------------------------------------------------------------------------ |
| `mg new ` / `mg n` | Create `.//trunk` and `git init` it. Jump in. |
| `mg clone ` / `mg c` | Clone a repo into `.//trunk`. Jump in. |
| `mg work ` / `mg w` | Create (or jump to) a sibling worktree for ``. Creates branch if new. |
| `mg pr ` / `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 ` / `mg r` | Remove the worktree and delete its branch. Jump back to `trunk`. |
| `mg prune ` | Remove sibling worktrees whose last commit is older than `` days. Asks for confirmation; skips worktrees with modified or stashed files. `-n` / `--dry-run` to preview. |
| `mg init ` | 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. |

### Examples

```sh
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
```

### Notes

- Slashes in a branch name become dashes in the folder β€” `feat/login` β†’ `feat-login`. No nested subfolders.
- `mg work` and `mg pr` are idempotent: if the worktree already exists, they just jump.
- `mg pr` requires `gh` (GitHub CLI) to look up the PR's head branch name.
- `mg prune` measures 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.

## Config

Optional `marcgit.toml` at the project root (next to `trunk/`). `mg config init` writes the default:

```toml
init-submodules = true # pull submodules on `mg work` (default: true)
```

## How it finds the project

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.

## License

[MIT](./LICENSE.md) Β© Marc EspΓ­n Sanz