git branchless submit: Push a Commit Stack
git branchless adds smartlog, sync, move, and submit for a commit-graph workflow; git submit pushes the stack and opens PRs.
git-branchless is a Git add-on for working with stacks of commits without juggling branches. After git branchless init, commands like git sync and git submit automate the stack.
What it does
git-branchless installs hooks with git branchless init and adds commands: git smartlog (git sl) shows the commit graph, git move rebases subtrees, git sync rebases your commits onto the updated main, and git submit pushes branches and creates/updates PRs on the forge.
Common usage
# one-time setup in the repo
git branchless init
# view the stack, sync onto main, push and open PRs
git sl
git sync --pull
git submit --createOptions
| Command / Flag | What it does |
|---|---|
| git branchless init | Install hooks and enable the extra commands |
| git sl / git smartlog | Show the commit graph |
| git sync [--pull] | Rebase your commits onto the latest main |
| git move -s <src> -d <dst> | Rebase a subtree onto a destination |
| git submit --create | Push branches and create PRs for the stack |
In CI
git branchless init must have run in the clone (its hooks power the commands), so either commit that state or init in the job. git submit --create talks to the forge and needs the underlying gh/token auth already configured. Prefer git sync --pull for non-interactive updating.
Common errors in CI
"Error: the branchless workflow has not been initialized" means git branchless init was not run. "This operation must be run in the context of a repository" means it ran outside a checkout. git submit failing with an auth error means the forge token (via gh) is missing. A stopped rebase after git sync leaves conflicts to resolve.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # history, tags, and git describe all need this
- run: |
git rev-parse --is-shallow-repository # expect false
git rev-parse --abbrev-ref HEAD # prints HEAD when detached