name: git-machete
description: Use whenever invoking the git machete CLI to organize branch chains, compute fork points, run stacked rebases/merges, or manage GitHub/GitLab PR/MR chains - especially in a repo that already has a .git/machete file. Lists which subcommands modify .git/machete, run rebase/merge, run hooks, or read stdin, so the agent can pick the right one and pass the right flags. Crucially, names the commands that MUST be invoked with -y/--yes (and the few that have no -y and therefore must NOT be invoked at all without a tty) so the agent never hangs on an interactive prompt. Also warns against hand-editing the .git/machete layout file.
git-machete
git machete is a logic- and feature-heavy CLI for managing chains of branches, but it keeps almost no extra state of its own: the only user-visible file it owns is .git/machete (the "branch layout" - a tree of branches with parent/child relationships, fork points and PR/MR annotations). It also maintains a transparent merge-base cache for performance, which the user never needs to touch. Everything else - rebases, merges, pushes, status rendering, PR/MR creation - is driven straight off git and the hosting API.
If the repo has no .git/machete file yet (check with git machete file && test -s "$(git machete file)"), the layout has not been initialized: run git machete discover -y (or ask the user) before anything else.
Do not run git machete discover against an already-initialized layout unless the user explicitly asks for it. discover re-derives the entire layout from heuristics (recent commit dates, branch reachability) and silently overwrites any hand-curated ordering, parenting, or annotations the user has built up. Use the targeted commands (add, slide-out, hand-edit) for incremental changes.
Hard rules - read first
Prefer dedicated subcommands over hand-editing
.git/machetewhen one fits the task. You can edit the layout file directly, but parse errors are quiet, so reach for a subcommand whenever there is one that fits:git machete add [-y] [<branch>] [--as-root|--onto <parent>]- add a branchgit machete slide-out [<branch>...]- remove a branch and re-parent its children (non-interactive by default; see rule 4 for--delete)git machete anno [<text>]- set/clear annotation on the current branchgit machete rename <new-name>- rename a local branch and its layout entry (use this instead ofgit branch -m)
The layout file grammar is small: one branch per line, each child indented one level deeper than its parent, with an optional annotation after whitespace on the same line. Any consistent indent unit works (a tab or N spaces), but the same unit must be used throughout the file.
For operations with no dedicated command (e.g. reparenting an existing branch, splitting one branch into two, ad-hoc reordering of siblings), hand-edit
.git/machetedirectly. The file is small and brittle: edit it in place with the agent's structured editing tool (StrReplace/ equivalent string-replacement primitive), not by piping it throughsed/awkor rewriting it from a shell heredoc - one stray space changes the parent/child relationship silently. Recommended sequence:MACHETE="$(git machete file)"- resolve the actual path (worktree/submodule-aware).cp -a "$MACHETE" "$MACHETE~"- back up; the file is NOT tracked by git, so this is your only undo.- Read the file, perform a structured in-place edit (preserve the existing indent unit), write it back.
git machete status- verify the parse. If it errors, restore withcp -a "$MACHETE~" "$MACHETE".
When indenting, match the unit already used in the file (could be a tab or any number of spaces, but it must stay consistent throughout). For a brand-new layout, use two spaces.
In the common case the layout file lives at
.git/macheteand hard-coding that is fine. The two exceptions are submodules (.git/modules/<path>/machete) and linked worktrees withgit config machete.worktree.useTopLevelMacheteFile false(.git/worktrees/<wt-name>/machete); when in doubt,git machete filealways resolves correctly.Register every new branch in the layout. Whenever you create a branch as part of the user's actual work (
git checkout -b ...,git switch -c ...,git branch ...), follow it withgit machete add -y [--onto <parent>]so the new branch joins.git/machete. In a git-machete-managed repo, the layout is the index of "branches I care about": users typically keep every branch they actively touch under git-machete, and the only branches deliberately left out are unrelated ones (someone else's WIP, throwaway branches checked out for a quick look). Defer to the user if they ask you to leave a branch unmanaged - but don't silently skip theaddstep; ask if you're unsure.Never invoke a command that reads stdin without
-y/--yes. Commands with a-y/--yesflag:add,advance,clean,delete-unmanaged,discover,traverse,github create-pr,gitlab create-mr. Always pass-yfrom a non-interactive context (CI, agent, script).Some commands prompt and have no
-yto suppress it - avoid or work around them:git machete update- prompts only if the current branch is missing from the layout. Workaround:git machete add -yfirst, thengit machete update.git machete status- prompts to slide out stale branches when stdout is a tty. Workaround: pipe through| cator redirect, or usegit machete status --color=never > /tmp/status.txt.git machete slide-out --delete ...- prompts once per branch and the prompt can't be silenced. Workaround: run plaingit machete slide-out <branch>...first, thengit branch -D <branch>...yourself (or skip the--deleteentirely). Plainslide-out(andslide-out --removed-from-remote) is non-interactive.git machete gowithout a direction - opens an interactive single-keystroke picker. Never invoke this form from an agent. Usegit machete go <direction>(up/down/prev/next/root/first/last) instead, which is non-interactive (but may still prompt ifdownis ambiguous - prefergit machete show down | head -1for scripted child discovery).git machete edit- opens$EDITOR. Never invoke this form from an agent. Use the dedicated subcommands from rule 1, or hand-edit.git/machetefor the cases that have no subcommand.
Plumbing commands have stable output across minor versions and are safe for scripting. Use these for any "I need to read state from git-machete" task:
git machete file- absolute path of.git/machetegit machete fork-point [--inferred] [<branch>]- prints fork-point SHA on stdout (and only that)git machete is-managed [<branch>]- exit code 0 if managed, non-zero otherwise; no stdoutgit machete list <category> [<branch>]- newline-separated branch names; categories:managed,addable,childless,slidable,slidable-after <branch>,unmanaged,with-overridden-fork-pointgit machete show <direction> [<branch>]- newline-separated branch names for the given directiongit machete version- printsgit-machete version X.Y.Z
All other commands' stdout/stderr formatting may change between minor versions, including
status.To open a PR/MR, use
git machete github create-pr -y(orgitlab create-mr -y), not rawgh pr create/glab mr create. The machete subcommand does three things the hosting CLI doesn't:- sets the PR/MR base to the branch's parent in the layout, not the repo default branch (correct for stacked PRs);
- writes the new PR/MR number back onto the branch in
.git/macheteso subsequentstatus/traverse/retarget-{pr,mr}see it; - uses
.git/info/descriptionfor the default PR title.
The host's own CLI is only the right tool for things git-machete doesn't cover (read-only listing/commenting, deleting a PR, fetching CI status, etc.). See the Create / restack / retarget PRs recipe.
Resolve yellow edges before running
update/traverse. A yellow edge means a child branch is a descendant of its parent but git-machete's inferred fork point lies somewhere earlier than the parent tip - usually because the branch was rebased over commits from another branch, or its real parent is a different managed branch. In ASCII-only output the edge marker is?-(e.g.?-feature-x); with colour it's yellow. Do not rungit machete update/git machete traverseblindly in this state - a rebase from the inferred fork point will pull extra commits onto the branch.Instead, run
git machete status --list-commits --color=never | cat(which prints the relevant suggestion under the tree) and present the options to the user. The three resolutions, in roughly the order to consider them, are:git machete fork-point <branch> --override-to-parent- accept the parent branch tip as the fork point (use when the branch was rebased and the inferred fork point is stale).git machete update(rebase) - only after confirming the inferred fork point really is correct and the extra commits should be re-applied.- Reattach the branch under a different parent (e.g. hand-edit
.git/macheteas in rule 1) - use when the layout is wrong and the branch's real parent is a different managed branch.
Pick based on what the user wants; don't auto-choose.
Command catalog with side effects
The table lists every non-deprecated top-level command and github/gitlab subcommand. The brace notation {github,gitlab} verb-{pr,mr} is shorthand for the pair github verb-pr and gitlab verb-mr.
Commands absent from every row (completion, diff, help, log, plus the plumbing commands listed above, plus {github,gitlab} update-{pr,mr}-descriptions which only talks to the hosting API) do not satisfy any of these properties.
| Side effect | Commands |
|---|---|
| reads stdin[1] | add, advance, clean, delete-unmanaged, discover, {github,gitlab} create-{pr,mr}, go[2], slide-out[3], status[4], traverse, update |
displays status (runs machete-status-branch hook) |
discover, {github,gitlab} create-{pr,mr}, {github,gitlab} restack-{pr,mr}, go[2], status, traverse |
writes .git/machete (branch layout) |
add, advance, anno, clean, discover, edit[5], {github,gitlab} anno-{pr,mr}s, {github,gitlab} checkout-{pr,mr}s, {github,gitlab} create-{pr,mr}, {github,gitlab} restack-{pr,mr}, {github,gitlab} retarget-{pr,mr}, rename, slide-out, traverse |
| mutates the git repository (refs / index / worktree / config)[6] | add, advance, clean, delete-unmanaged, fork-point[7], {github,gitlab} checkout-{pr,mr}s, {github,gitlab} create-{pr,mr}, {github,gitlab} restack-{pr,mr}, go, reapply, rename, slide-out, squash, traverse, update |
checks out a branch (git checkout, switching which branch HEAD points to)[11] |
add[12], {github,gitlab} checkout-{pr,mr}s, go, slide-out, traverse |
runs git merge |
advance[8], slide-out, traverse, update |
runs git rebase (runs machete-pre-rebase hook) |
reapply[9], slide-out, traverse, update |
slides out a branch (runs machete-post-slide-out hook) |
advance, slide-out[10], traverse |
| requires no ongoing rebase / merge / cherry-pick / revert / am / bisect | advance, go, reapply, slide-out, squash, traverse, update |
Footnotes
[1]: Commands with a -y/--yes flag (add, advance, clean, delete-unmanaged, discover, traverse, {github,gitlab} create-{pr,mr}) are safe to run from an agent as long as -y is passed. Without -y they read stdin to confirm decisions. The rest (see [2]-[4]) cannot be silenced and need a workaround.
[2]: go without a direction is fully interactive (single-keystroke picker reading stdin). Never run this form from an agent. go <direction> (up/down/prev/next/root/first/last) is non-interactive, but down may prompt if there are multiple children; prefer git machete show down to enumerate them and then check out manually with git checkout.
[3]: slide-out only reads stdin under --delete (one yes/no per branch). slide-out and slide-out --removed-from-remote without --delete are non-interactive.
[4]: status reads stdin only when stdout is a tty and the layout references branches that no longer exist in the repo. Redirected/non-tty runs (| cat, > file) skip the prompt entirely. CI runs are safe.
[5]: edit doesn't itself write the layout file; it just opens $GIT_MACHETE_EDITOR/$GIT_EDITOR on it and any change is done by the editor. Never run this form from an agent.
[6]: Pure hosting-API operations don't count here - that's why {github,gitlab} retarget-{pr,mr} and {github,gitlab} update-{pr,mr}-descriptions are absent.
[7]: fork-point mutates .git/config only under its override flags (--override-to=..., --override-to-inferred, --override-to-parent, --unset-override). The default mode and --inferred/--explain are read-only.
[8]: advance can only run fast-forward merge (git merge --ff-only).
[9]: reapply can run rebase but can't run merge (merging a branch with its own fork point is a no-op).
[10]: slide-out --removed-from-remote removes branches from the layout but does NOT run the machete-post-slide-out hook. The regular slide-out and the slide-out triggered by advance/traverse do.
[11]: This is the operation that fails with fatal: '<branch>' is already used by worktree at <path> when the target branch is already checked out in another linked worktree - the class of bug that has to be guarded against (and was fixed for traverse and slide-out; each command in this row needs auditing for it, ideally refusing before any layout/refs mutation rather than midway through). Commands that only fast-forward or rewrite the current branch in place are deliberately NOT in this row, because they never switch to a different branch and so can't hit that conflict: advance (git merge --ff-only advances the current branch), squash (rewrites the current branch tip), and update/reapply (rebase the current branch). Note that git rebase <branch> does implicitly check <branch> out, but the rebase-running commands either rebase the already-current branch (update, reapply) or check the branch out explicitly just beforehand (slide-out, traverse, already counted here via that explicit checkout).
[12]: add checks out a branch only when it has to create or fetch a new local branch (e.g. git machete add <new-branch>, or adding a branch that exists only on the remote) - the CLI path opts into switching HEAD onto the freshly created branch. Adding a branch that already exists locally (including the common git machete add on the current branch) doesn't move HEAD.
Recipes
Initialize the branch layout for a fresh repo
git machete discover -y
Only run this when the layout doesn't exist yet (or the user explicitly asks to re-derive). On an existing layout, discover silently replaces any user-curated parenting/ordering.
Add the current branch under its parent
git checkout -b feature/new-thing
git machete add -y
Add a branch under an explicit parent
git machete add -y --onto develop feature/new-thing
Rename a branch (keeping the layout consistent)
git machete rename feature/new-name
Do not use git branch -m; it leaves the layout out of sync.
Get current branch state
git machete status -l # human-friendly, with commits
git machete status -l --color=never | cat # safe for agents (never prompts)
Sync the current branch with its parent
git machete update --no-interactive-rebase # rebase-based (default)
If update complains the current branch isn't in the layout, run git machete add -y (or git machete discover -y) first.
Walk the whole chain and bring everything up to date
git machete traverse -y --no-push # rebase only, don't push
git machete traverse -y # rebase + push (default)
Do not pass -M/--merge (to update, traverse, or slide-out). For stacked branches, merge-based sync entangles history quickly and recovery is non-trivial (see the README FAQ for rationale). Rebase is the only mode an agent should use. If the user explicitly asks for merge mode, repeat the warning and ask them to confirm.
Drop a branch from the layout (after merge)
git machete slide-out <branch> # branch still exists locally; non-interactive
git machete slide-out --removed-from-remote # clean up branches whose remote is gone (non-interactive, no hook)
To also delete the branch from git, run git branch -D <branch> yourself after slide-out - the built-in --delete flag prompts per branch and can't be silenced.
Inspect / set / clear fork-point overrides
git machete fork-point # prints SHA
git machete fork-point --inferred # what git-machete would infer
git machete fork-point --explain # human-readable rationale (uses stderr)
git machete fork-point --override-to-parent # pin fork point to the parent branch tip
git machete fork-point --unset-override
Create / restack / retarget PRs (GitHub)
git machete github create-pr -y # safe: -y skips push/sync prompts
git machete github restack-pr # non-interactive
git machete github retarget-pr # non-interactive, hosting-API only
git machete github checkout-prs --mine # non-interactive (forces non-interactive `add`)
GitLab equivalents: gitlab create-mr -y, restack-mr, retarget-mr, checkout-mrs --mine.
Discover children/parent for scripting (instead of go)
git machete show up # parent
git machete show down # all children, one per line
git machete show prev # previous in DFS order
git machete show next # next in DFS order
git machete show root # root of the current chain
git machete list managed # everything in the layout
git machete list slidable # branches that can be slid out
Hooks
git machete invokes three optional hooks if executable scripts of the matching names exist in .git/hooks/:
machete-pre-rebase <onto> <fork-point> <branch>- run before eachgit rebaseinitiated by git-machete (i.e. fromreapply,slide-out,traverse,update). Non-zero exit aborts the rebase.machete-post-slide-out <new-upstream> <slid-out-branch> [<new-downstream>...]- run after a successful slide-out triggered byadvance,slide-out(without--removed-from-remote), ortraverse.machete-status-branch <branch>- run once per branch during status display; its stdout is appended to the branch's line instatusoutput.
Files this tool reads/writes
| Path | Purpose |
|---|---|
.git/machete |
branch layout (parent/child tree, annotations, qualifiers). The literal path varies by context (worktree, submodule); always resolve via git machete file. Not git-tracked, so back up to .git/machete~ before manual edits. |
.git/machete-merge-base-cache |
transparent merge-base cache. |
.git/config (machete.* keys) |
fork-point overrides set via fork-point --override-to=...; also feature toggles like machete.worktree.useTopLevelMacheteFile, machete.traverse.push, machete.squashMergeDetection. |
.git/info/description |
used as PR/MR title default when creating with github create-pr / gitlab create-mr. |
~/.github-token |
GitHub API token (alternative: GITHUB_TOKEN env var). |
~/.gitlab-token |
GitLab API token (alternative: GITLAB_TOKEN env var). |
Further reading
For per-command detail (full flag list, exit codes, examples), run git machete help <command> (e.g. git machete help traverse). It prints the same content as the readthedocs page for that subcommand, but in a single plain-text response that's cheap to ingest.