This lets someone set git config options at whatever scope (per-repo, global, etc.) for the options that they care about. This provides similar functionality to just wrapping the script in a shell script with one's desired options without the need to do that. We need to be careful about how when we get the flags and how to execute the git command to get the flags. For now, we do this before normal argument parsing and fail silently to avoid printing output if someone passes something like --quiet through the git config. This means options like --verbose and --dry-run don't work for this specific command, but I think that is a reasonable tradeoff.
7.6 KiB
How to Use the LLVM Pull Request Automator
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.
Prerequisites
Before running the script, ensure you have the following set up:
-
gitcommand line tool: The script relies ongitfor all local repository operations. -
GitHub Token: You must have a GitHub Personal Access Token with
reposcope. 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.
- The script defaults to using
upstream(e.g.,https://github.com/llvm/llvm-project.git) for the main LLVM repository andoriginfor your personal fork. - If your remotes are named differently, you can override these defaults using the
--upstream-remoteand--remoteflags.
- The script defaults to using
Basic Usage
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:
- Fetch the latest changes from
upstream/main. - Rebase your current branch on top of
upstream/main. - For each commit in your branch (from oldest to newest):
a. Push the commit to a temporary branch on your fork (
origin). b. Create a pull request targeting theupstreamrepository'smainbranch. 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.
Cleanup Steps
Regardless of success or failure, the script performs the following cleanup steps to ensure your local repository is left in a consistent state:
- Checkout Original Branch: The script will check out the branch you were on when you started the script.
- Delete Temporary Remote Branches: Any temporary branches created on your fork (e.g.,
users/johndoe/my-feature-1) will be deleted from the remote. This prevents clutter in your fork.
Configuration
In addition to accepting command line flags, git-llvm-push can also be configured
through the git config. To do this, edit your git config (using a command like
git config --edit to edit your repo specific configuration) and add the following
section header:
[git-llvm-push]
<flag> = <flag value>
The flags are spelled the exact same as they are on the command line. All flags
are supported, although --verbose and --dry-run will not have an impact on
the git invocation to read the configuration.
Examples
Dry Run (Safe Mode)
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
Creating Draft Pull Requests
If you want to create pull requests but not have them ready for review immediately, use the --draft flag.
python3 git-llvm-push --draft
Enabling Auto-Merge
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
Creating PRs Without Merging
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
Working with alternate remotes
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
Alternate usage via git llvm-push
If the script is available on your PATH, you can use it as a git subcommand, similar to git clang-format.
git llvm-push [FLAGS] ...
Auto-Detection Features
To simplify usage, the script attempts to auto-detect certain values if they are not explicitly provided via command-line arguments:
- GitHub Login (
--login): If the--loginflag is omitted, the script will attempt to fetch your GitHub username using the providedLLVM_GITHUB_TOKENby making an API call to GitHub. - Temporary Branch Prefix (
--prefix): If the--prefixflag is omitted, temporary branches created on your fork will be prefixed withusers/<your_github_login>/. For example, if your login isjohndoe, branches will be named likeusers/johndoe/my-feature-1.
Command-Line Options
| 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) |
--use-gh-cli-token |
Automatically acquires a token by calling gh auth token |
(not set). |