This script is designed to automate the process of creating and landing a stack of pull requests from a local commit branch to the main branch of LLVM‘s GitHub repository. While it’s possible to use this for normal workflows, its main purpose is to give contributors a practical alternative to pushing directly to LLVM's main branch. See the discussion at https://discourse.llvm.org/t/rfc-require-pull-requests-for-all-llvm-project-commits/88164 for more context.
Before running the script, ensure you have the following set up:
git command line tool: The script relies on git for all local repository operations.
GitHub Token: You must have a GitHub Personal Access Token with repo scope. This token must be set as an environment variable:
export LLVM_GITHUB_TOKEN="your_github_token_here"
or to avoid having your token in your shell history something like:
export LLVM_GITHUB_TOKEN="$(gh auth token)"
Git Remotes: Your local repository should be configured with remotes for the upstream LLVM repository and your personal fork.
upstream (e.g., https://github.com/llvm/llvm-project.git) for the main LLVM repository and origin for your personal fork.--upstream-remote and --remote flags.To run the script, navigate to your local llvm-project repository, check out the branch containing your stack of commits, and run:
python3 git-llvm-push
Assuming your remotes are configured with upstream pointing to https://github.com/llvm/llvm-project.git and origin pointing to your personal fork:
This will:
upstream/main.upstream/main.origin). b. Create a pull request targeting the upstream repository's main branch. c. Attempt to merge the pull request. d. If the merge is successful, it will rebase the local branch again and proceed to the next commit.If any rebase or merge fails, the script will abort and clean up after itself, leaving your repository in the last good state. This means any commits that were successfully merged before the failure will remain merged, but temporary branches and other transient state will be removed.
Regardless of success or failure, the script performs the following cleanup steps to ensure your local repository is left in a consistent state:
users/johndoe/my-feature-1) will be deleted from the remote. This prevents clutter in your fork.To see what actions the script would perform without actually creating branches, pushing code, or opening pull requests, use the --dry-run flag.
python3 git-llvm-push --dry-run
If you want to create pull requests but not have them ready for review immediately, use the --draft flag.
python3 git-llvm-push --draft
You can use the --auto-merge flag to create a pull request and enable the “auto-merge” feature on GitHub, rather than having the script try to merge it directly. This is only supported for a single commit, as the script would need to block until your first PR landed to move onto the next, or otherwise be too complex for a simple script.
python3 git-llvm-push --auto-merge
If you only want to create the pull requests and then merge them manually later, use the --no-merge flag. Currently, this is only supported for single-commit branches.
python3 git-llvm-push --no-merge
If you have cloned the main llvm/llvm-project.git repository directly, your origin remote will point to upstream. If your personal fork is tracked under a different remote name (e.g., my-fork), you will need to specify both the --upstream-remote and --remote flags:
python3 git-llvm-push --upstream-remote origin --remote my-fork
git llvm-pushIf the script is available on your PATH, you can use it as a git subcommand, similar to git clang-format.
git llvm-push [FLAGS] ...
To simplify usage, the script attempts to auto-detect certain values if they are not explicitly provided via command-line arguments:
--login): If the --login flag is omitted, the script will attempt to fetch your GitHub username using the provided LLVM_GITHUB_TOKEN by making an API call to GitHub.--prefix): If the --prefix flag is omitted, temporary branches created on your fork will be prefixed with users/<your_github_login>/. For example, if your login is johndoe, branches will be named like users/johndoe/my-feature-1.| Flag | Description | Default |
|---|---|---|
--base | The base branch to target with the pull requests. | main |
--remote | The remote for your personal fork to push temporary branches to. | origin |
--upstream-remote | The remote for the upstream repository to create pull requests against. | upstream |
--login | Your GitHub username. If not provided, it will be queried from the token. | (auto-detected) |
--prefix | The prefix for temporary branches created on your fork. | users/<username>/ |
--draft | Create pull requests as drafts. | (not set) |
--no-merge | Create pull requests but do not attempt to merge them. (Single commit only) | (not set) |
--auto-merge | Enable auto-merge on created pull requests instead of merging directly. (Single commit only) | (not set) |
--dry-run | Print the commands that would be run without executing them. | (not set) |
-v, --verbose | Print all commands being run and other verbose output. | (not set) |
-q, --quiet | Print only essential output and errors, suppressing progress messages. | (not set) |