Skip to content

Push

push

GitPushTool — push current branch with dirty-check and upstream detection.

GitPushTool

Bases: AXMTool

Push the current branch after verifying a clean working tree.

Registered as git_push via axm.tools entry point.

Source code in packages/axm-git/src/axm_git/tools/push.py
class GitPushTool(AXMTool):
    """Push the current branch after verifying a clean working tree.

    Registered as ``git_push`` via axm.tools entry point.
    """

    @property
    def name(self) -> str:
        """Tool name used for MCP registration."""
        return "git_push"

    def execute(
        self,
        *,
        path: str = ".",
        remote: str = "origin",
        set_upstream: bool = True,
        force: bool = False,
        **kwargs: Any,
    ) -> ToolResult:
        """Push the current branch to a remote.

        Args:
            path: Project root directory.
            remote: Remote name (default ``origin``).
            set_upstream: Auto-set upstream for new branches.
            force: If True, force-push.

        Returns:
            ToolResult with branch, remote, and push status.
        """
        resolved = Path(path).resolve()

        # 1. Verify this is a git repo.
        check = run_git(["rev-parse", "--git-dir"], resolved)
        if check.returncode != 0:
            return not_a_repo_error(check.stderr, resolved)

        # 2. Dirty check.
        dirty_err = _check_dirty(resolved)
        if dirty_err is not None:
            return dirty_err

        # 3. Get current branch.
        branch_result = run_git(["branch", "--show-current"], resolved)
        branch = branch_result.stdout.strip()
        if not branch:
            return ToolResult(
                success=False,
                error="No branch checked out (detached HEAD).",
            )

        # 4. Detect upstream.
        upstream = run_git(
            ["rev-parse", "--abbrev-ref", "@{u}"],
            resolved,
        )
        has_upstream = upstream.returncode == 0

        # 5. Push.
        cmd = _build_push_cmd(
            force=force,
            has_upstream=has_upstream,
            set_upstream=set_upstream,
            remote=remote,
            branch=branch,
        )
        push_result = run_git(cmd, resolved)
        if push_result.returncode != 0:
            return ToolResult(
                success=False,
                error=(push_result.stderr.strip() or push_result.stdout.strip()),
            )

        return ToolResult(
            success=True,
            data={
                "branch": branch,
                "remote": remote,
                "pushed": True,
                "set_upstream": not has_upstream and set_upstream,
            },
        )
name property

Tool name used for MCP registration.

execute(*, path='.', remote='origin', set_upstream=True, force=False, **kwargs)

Push the current branch to a remote.

Parameters:

Name Type Description Default
path str

Project root directory.

'.'
remote str

Remote name (default origin).

'origin'
set_upstream bool

Auto-set upstream for new branches.

True
force bool

If True, force-push.

False

Returns:

Type Description
ToolResult

ToolResult with branch, remote, and push status.

Source code in packages/axm-git/src/axm_git/tools/push.py
def execute(
    self,
    *,
    path: str = ".",
    remote: str = "origin",
    set_upstream: bool = True,
    force: bool = False,
    **kwargs: Any,
) -> ToolResult:
    """Push the current branch to a remote.

    Args:
        path: Project root directory.
        remote: Remote name (default ``origin``).
        set_upstream: Auto-set upstream for new branches.
        force: If True, force-push.

    Returns:
        ToolResult with branch, remote, and push status.
    """
    resolved = Path(path).resolve()

    # 1. Verify this is a git repo.
    check = run_git(["rev-parse", "--git-dir"], resolved)
    if check.returncode != 0:
        return not_a_repo_error(check.stderr, resolved)

    # 2. Dirty check.
    dirty_err = _check_dirty(resolved)
    if dirty_err is not None:
        return dirty_err

    # 3. Get current branch.
    branch_result = run_git(["branch", "--show-current"], resolved)
    branch = branch_result.stdout.strip()
    if not branch:
        return ToolResult(
            success=False,
            error="No branch checked out (detached HEAD).",
        )

    # 4. Detect upstream.
    upstream = run_git(
        ["rev-parse", "--abbrev-ref", "@{u}"],
        resolved,
    )
    has_upstream = upstream.returncode == 0

    # 5. Push.
    cmd = _build_push_cmd(
        force=force,
        has_upstream=has_upstream,
        set_upstream=set_upstream,
        remote=remote,
        branch=branch,
    )
    push_result = run_git(cmd, resolved)
    if push_result.returncode != 0:
        return ToolResult(
            success=False,
            error=(push_result.stderr.strip() or push_result.stdout.strip()),
        )

    return ToolResult(
        success=True,
        data={
            "branch": branch,
            "remote": remote,
            "pushed": True,
            "set_upstream": not has_upstream and set_upstream,
        },
    )