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
Python
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: object,
    ) -> 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()

        try:
            # 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()),
                )
        except subprocess.TimeoutExpired as exc:
            return timeout_error_result(exc)

        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
Python
def execute(
    self,
    *,
    path: str = ".",
    remote: str = "origin",
    set_upstream: bool = True,
    force: bool = False,
    **kwargs: object,
) -> 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()

    try:
        # 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()),
            )
    except subprocess.TimeoutExpired as exc:
        return timeout_error_result(exc)

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