diff --git a/README.md b/README.md index ace3c48..9450c52 100644 --- a/README.md +++ b/README.md @@ -342,6 +342,7 @@ These arguments can be used with any subcommand: - `$USERNAME`: The username of the current user - `$BRANCH`: The current branch name - `$ID`: The location for the ID of the branch. The ID is determined by the order of creation of the branches. If `$ID` is not found in the template, the template will be appended with `/$ID`. +- `--max-branches-per-push`: Maximum number of branches to push to GitHub in one push operation (default: 5) ### Subcommands @@ -401,6 +402,9 @@ stack-pr config repo.reviewer=user1,user2 # Set custom branch name template stack-pr config repo.branch_name_template=$USERNAME/stack +# Set [maximum number of branches to push to Github in one operation](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-the-push-policy-for-your-repository) +stack-pr config repo.max_branches_per_push=5 + # Disable the land command (require GitHub web interface for merging) stack-pr config land.style=disable @@ -431,6 +435,7 @@ remote=origin target=main reviewer=GithubHandle1,GithubHandle2 branch_name_template=$USERNAME/$BRANCH +max_branches_per_push=5 [land] style=bottom-only ``` diff --git a/src/stack_pr/cli.py b/src/stack_pr/cli.py index cf52324..7122351 100755 --- a/src/stack_pr/cli.py +++ b/src/stack_pr/cli.py @@ -705,11 +705,12 @@ def init_local_branches( ) -def push_branches(st: list[StackEntry], remote: str, *, verbose: bool) -> None: - log(h("Updating remote branches"), level=2) - cmd = ["git", "push", "-f", remote] - cmd.extend([f"{e.head}:{e.head}" for e in st]) - run_shell_command(cmd, quiet=not verbose) +def push_branches(st: list[StackEntry], remote: str, *, verbose: bool, max_branches_per_push: int) -> None: + for i in range(0, len(st), max_branches_per_push): + log(h("Updating remote branches"), level=2) + cmd = ["git", "push", "-f", remote] + cmd.extend([f"{e.head}:{e.head}" for e in st[i:i+max_branches_per_push]]) + run_shell_command(cmd, quiet=not verbose) def print_cmd_failure_details(exc: SubprocessError) -> None: @@ -918,6 +919,7 @@ class CommonArgs: branch_name_template: str show_tips: bool land_disabled: bool + max_branches_per_push: int @classmethod def from_args(cls, args: argparse.Namespace, *, land_disabled: bool) -> CommonArgs: @@ -931,6 +933,7 @@ def from_args(cls, args: argparse.Namespace, *, land_disabled: bool) -> CommonAr args.branch_name_template, args.show_tips, land_disabled, + args.max_branches_per_push, ) @@ -1102,7 +1105,7 @@ def command_submit( reset_remote_base_branches(st, target=args.target, verbose=args.verbose) # Push local branches to remote - push_branches(st, remote=args.remote, verbose=args.verbose) + push_branches(st, remote=args.remote, verbose=args.verbose, max_branches_per_push=args.max_branches_per_push) # Now we have all the branches, so we can create the corresponding PRs log(h("Submitting PRs"), level=1) @@ -1128,7 +1131,7 @@ def command_submit( error(ERROR_CANT_UPDATE_META.format(**locals())) raise - push_branches(st, remote=args.remote, verbose=args.verbose) + push_branches(st, remote=args.remote, verbose=args.verbose, max_branches_per_push=args.max_branches_per_push) log(h("Adding cross-links to PRs"), level=1) add_cross_links(st, keep_body=keep_body, verbose=args.verbose) @@ -1575,6 +1578,12 @@ def create_argparser( default=config.getboolean("common", "show_tips", fallback=True), help="Show or hide usage tips after commands.", ) + common_parser.add_argument( + "--max-branches-per-push", + type=int, + default=config.getint("repo", "max_branches_per_push", fallback=5), + help="Maximum number of branches to push to GitHub in one push operation (default: 5).", + ) parser_submit = subparsers.add_parser( "submit",