fix(repos create): default new repos to main, not master

`git init` without `-b` inherits the ambient `init.defaultBranch` config,
which is `master` unless the host has configured otherwise, so `pkgmgr
repos create` produced master-based repositories. On top of that, the
push fallback renamed an already-correct `main` branch back to `master`
whenever the initial push failed (missing remote, auth error).

`init()` now requires an explicit `initial_branch` and runs
`git init -b <branch>`; the bootstrapper passes `main` and no longer
falls back to `master` on push failure.

`resolve_base_branch()` keeps its main -> master fallback, since it reads
existing repositories that may legitimately use master.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-Birkenbach
2026-07-27 15:06:09 +02:00
parent d0e99b6483
commit f1517963a5
3 changed files with 73 additions and 15 deletions

View File

@@ -10,10 +10,12 @@ from pkgmgr.core.git.commands import (
push_upstream, push_upstream,
) )
DEFAULT_BRANCH = "main"
class GitBootstrapper: class GitBootstrapper:
def init_repo(self, repo_dir: str, preview: bool) -> None: def init_repo(self, repo_dir: str, preview: bool) -> None:
init(cwd=repo_dir, preview=preview) init(initial_branch=DEFAULT_BRANCH, cwd=repo_dir, preview=preview)
add_all(cwd=repo_dir, preview=preview) add_all(cwd=repo_dir, preview=preview)
try: try:
commit("Initial commit", cwd=repo_dir, preview=preview) commit("Initial commit", cwd=repo_dir, preview=preview)
@@ -21,15 +23,8 @@ class GitBootstrapper:
print(f"[WARN] Initial commit failed (continuing): {exc}") print(f"[WARN] Initial commit failed (continuing): {exc}")
def push_default_branch(self, repo_dir: str, preview: bool) -> None: def push_default_branch(self, repo_dir: str, preview: bool) -> None:
branch_move(DEFAULT_BRANCH, cwd=repo_dir, preview=preview)
try: try:
branch_move("main", cwd=repo_dir, preview=preview) push_upstream("origin", DEFAULT_BRANCH, cwd=repo_dir, preview=preview)
push_upstream("origin", "main", cwd=repo_dir, preview=preview)
return
except GitPushUpstreamError:
pass
try:
branch_move("master", cwd=repo_dir, preview=preview)
push_upstream("origin", "master", cwd=repo_dir, preview=preview)
except GitPushUpstreamError as exc: except GitPushUpstreamError as exc:
print(f"[WARN] Push failed: {exc}") print(f"[WARN] Push failed: {exc}")

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from ..errors import GitRunError, GitCommandError from ..errors import GitCommandError, GitRunError
from ..run import run from ..run import run
@@ -8,14 +8,17 @@ class GitInitError(GitCommandError):
"""Raised when `git init` fails.""" """Raised when `git init` fails."""
def init(*, cwd: str = ".", preview: bool = False) -> None: def init(*, initial_branch: str, cwd: str = ".", preview: bool = False) -> None:
""" """
Initialize a repository. Initialize a repository with an explicit initial branch.
Equivalent to: Equivalent to:
git init git init -b <initial_branch>
initial_branch: required, so the branch never depends on the ambient
`init.defaultBranch` git config (which is `master` unless configured).
""" """
try: try:
run(["init"], cwd=cwd, preview=preview) run(["init", "-b", initial_branch], cwd=cwd, preview=preview)
except GitRunError as exc: except GitRunError as exc:
raise GitInitError("Failed to initialize git repository.", cwd=cwd) from exc raise GitInitError("Failed to initialize git repository.", cwd=cwd) from exc

View File

@@ -0,0 +1,60 @@
from __future__ import annotations
import unittest
from unittest.mock import patch
from pkgmgr.actions.repository.create.git_bootstrap import GitBootstrapper
from pkgmgr.core.git.commands import GitPushUpstreamError
class TestGitBootstrapperDefaultBranch(unittest.TestCase):
def test_init_repo_uses_main_as_initial_branch(self):
with (
patch("pkgmgr.actions.repository.create.git_bootstrap.init") as init,
patch("pkgmgr.actions.repository.create.git_bootstrap.add_all"),
patch("pkgmgr.actions.repository.create.git_bootstrap.commit"),
):
GitBootstrapper().init_repo("/repo", preview=False)
init.assert_called_once_with(
initial_branch="main", cwd="/repo", preview=False
)
def test_push_default_branch_pushes_main(self):
with (
patch(
"pkgmgr.actions.repository.create.git_bootstrap.branch_move"
) as branch_move,
patch(
"pkgmgr.actions.repository.create.git_bootstrap.push_upstream"
) as push_upstream,
):
GitBootstrapper().push_default_branch("/repo", preview=False)
branch_move.assert_called_once_with("main", cwd="/repo", preview=False)
push_upstream.assert_called_once_with(
"origin", "main", cwd="/repo", preview=False
)
def test_failed_push_does_not_fall_back_to_master(self):
with (
patch(
"pkgmgr.actions.repository.create.git_bootstrap.branch_move"
) as branch_move,
patch(
"pkgmgr.actions.repository.create.git_bootstrap.push_upstream",
side_effect=GitPushUpstreamError("boom"),
) as push_upstream,
):
GitBootstrapper().push_default_branch("/repo", preview=False)
self.assertEqual(
[call.args[0] for call in branch_move.call_args_list], ["main"]
)
self.assertEqual(
[call.args[1] for call in push_upstream.call_args_list], ["main"]
)
if __name__ == "__main__":
unittest.main()