Skip to content

Commit

Permalink
Merge pull request #166 from mikegehard/feature/git-checkout-command
Browse files Browse the repository at this point in the history
Allow to check out branches
  • Loading branch information
dsp-ant authored Dec 10, 2024
2 parents 854f48e + 98e78c3 commit 79794fe
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/git/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ Please note that mcp-server-git is currently in early development. The functiona
- `branch_name` (string): Name of the new branch
- `start_point` (string, optional): Starting point for the new branch
- Returns: Confirmation of branch creation
8. `git_checkout`
- Switches branches
- Inputs:
- `repo_path` (string): Path to Git repository
- `branch_name` (string): Name of branch to checkout
- Returns: Confirmation of branch switch

## Installation

Expand Down
8 changes: 7 additions & 1 deletion src/git/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.uv]
dev-dependencies = ["pyright>=1.1.389", "ruff>=0.7.3"]
dev-dependencies = ["pyright>=1.1.389", "ruff>=0.7.3", "pytest>=8.0.0"]

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
python_classes = "Test*"
python_functions = "test_*"
21 changes: 21 additions & 0 deletions src/git/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class GitCreateBranch(BaseModel):
branch_name: str
base_branch: str | None = None

class GitCheckout(BaseModel):
repo_path: str
branch_name: str

class GitTools(str, Enum):
STATUS = "git_status"
DIFF_UNSTAGED = "git_diff_unstaged"
Expand All @@ -58,6 +62,7 @@ class GitTools(str, Enum):
RESET = "git_reset"
LOG = "git_log"
CREATE_BRANCH = "git_create_branch"
CHECKOUT = "git_checkout"

def git_status(repo: git.Repo) -> str:
return repo.git.status()
Expand Down Expand Up @@ -104,6 +109,10 @@ def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None
repo.create_head(branch_name, base)
return f"Created branch '{branch_name}' from '{base.name}'"

def git_checkout(repo: git.Repo, branch_name: str) -> str:
repo.git.checkout(branch_name)
return f"Switched to branch '{branch_name}'"

async def serve(repository: Path | None) -> None:
logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -165,6 +174,11 @@ async def list_tools() -> list[Tool]:
description="Creates a new branch from an optional base branch",
inputSchema=GitCreateBranch.schema(),
),
Tool(
name=GitTools.CHECKOUT,
description="Switches branches",
inputSchema=GitCheckout.schema(),
),
]

async def list_repos() -> Sequence[str]:
Expand Down Expand Up @@ -269,6 +283,13 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
text=result
)]

case GitTools.CHECKOUT:
result = git_checkout(repo, arguments["branch_name"])
return [TextContent(
type="text",
text=result
)]

case _:
raise ValueError(f"Unknown tool: {name}")

Expand Down
30 changes: 30 additions & 0 deletions src/git/tests/test_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest
from pathlib import Path
import git
from mcp_server_git.server import git_checkout
import shutil

@pytest.fixture
def test_repository(tmp_path: Path):
repo_path = tmp_path / "temp_test_repo"
test_repo = git.Repo.init(repo_path)

Path(repo_path / "test.txt").write_text("test")
test_repo.index.add(["test.txt"])
test_repo.index.commit("initial commit")

yield test_repo

shutil.rmtree(repo_path)

def test_git_checkout_existing_branch(test_repository):
test_repository.git.branch("test-branch")
result = git_checkout(test_repository, "test-branch")

assert "Switched to branch 'test-branch'" in result
assert test_repository.active_branch.name == "test-branch"

def test_git_checkout_nonexistent_branch(test_repository):

with pytest.raises(git.GitCommandError):
git_checkout(test_repository, "nonexistent-branch")
89 changes: 87 additions & 2 deletions src/git/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 79794fe

Please sign in to comment.