If you find yourself in a bad state and are unsure how to proceed, please submit a bug report with metadata by running:

gt feedback --with-debug-context <your-message-here> This allows us to reproduce and fix most issues.

To unblock yourself you have a few options:

  • gt dev cache --clear is a safe command that sometimes fixes inadvertent issues that we haven't caught before release. It doesn't change any git or Graphite state.

  • This combination of commands allows you to start from scratch on the rare occasion you run into a troubled state on the CLI.

gt repo init --reset && gt dev cache --clearThis combination of commands resets Graphite repository metadata and clears the cache

If neither of these work, and you would like specific help for your issue, reach out in our Community slack channel.

You can try to fix your state manually, but this is an advanced method.

  • Use gt branch untrack to stop tracking any affected branches with Graphite.

  • Then use a combination of git rebase, gt downstack track and gt branch track to get your repository back in working order. The extreme of this is gt repo init --reset which will reset all Graphite metadata such that all branches will need to be re-tracked.

We use git push --force-with-lease under the hood for our push, which should ensure this doesn't happen. You should only be able to overwrite changes that you have already pushed from your machine or synced to your machine with gt downstack get.

Using this option is just like using --force (push to a branch on remote even if remote's SHA cannot be fast-forwarded to the new SHA), with the caveat that if the remote's SHA for the branch doesn't match the "remote-tracking branch" on your machine (for example, refs/remotes/origin/feature), it will fail, as this means that someone else has updated the branch since you last pushed to it or pulled it. Graphite respects the "remote-tracking branch", only updating it on a gt stack submit or gt downstack get operation.

The issue can arise if you have some other tooling (for example, some VS Code extension) that is git fetching your branches in the background. This could update the "remote-tracking branch" and result in the --force-with-lease check passing—even if someone has updated the branch to a commit that you haven't synced to your repository (or pushed yourself).

Because gt stack submit both performs a git push and a GitHub API call, occasionally GitHub will pick up both as a synchronize event on the PR.

We recommend using GitHub's concurrency configuration to ensure that you do not have duplicated CI.

For example, the following configuration will cancel previous CI runs on the same pull request:

group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || ''}}
cancel-in-progress: true

The Graphite CLI use branches instead of commits to represent atomic changes in a stack. But it's possible to replicate the single-commit workflow.

Just don't use gt commit create, and if you end up with multiple commits on a branch by accident, you can always use gt branch squash to get your branch back to a single commit. This way, you can essentially only use gt, and your workflow will look something like (making use of lots of shortcuts and short-form flags):

# make changes to the codebase
gt bc -am "my first commit"
# make some more changes
gt bc -am "my second commit"
# now we're ready to submit!
gt ss -np
# got some feedback?
gt bco my_first_commit
# address comments
gt ca -an
gt ss
# ... etc