diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index b94af84661..0c4273b3e8 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -188,11 +188,17 @@ def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None raise BadName(f"Invalid base branch: '{base_branch}' - cannot start with '-'") if base_branch: base = repo.references[base_branch] + base_name = base.name + elif repo.head.is_detached: + # No active branch to start from; branch from the current commit. + base = repo.head.commit.hexsha + base_name = base else: base = repo.active_branch + base_name = base.name repo.create_head(branch_name, base) - return f"Created branch '{branch_name}' from '{base.name}'" + return f"Created branch '{branch_name}' from '{base_name}'" def git_checkout(repo: git.Repo, branch_name: str) -> str: # Defense in depth: reject branch names starting with '-' to prevent flag injection, diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index 05d5931466..f154691fc0 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -255,6 +255,17 @@ def test_git_create_branch_from_base(test_repository): assert "Created branch 'derived-branch' from 'base-branch'" in result +def test_git_create_branch_detached_head(test_repository): + # `git switch -c ` from a detached HEAD branches from the current commit. + detached_sha = test_repository.head.commit.hexsha + test_repository.git.checkout(detached_sha) + assert test_repository.head.is_detached + + result = git_create_branch(test_repository, "rescued-branch") + + assert "Created branch 'rescued-branch'" in result + assert test_repository.heads["rescued-branch"].commit.hexsha == detached_sha + def test_git_show(test_repository): file_path = Path(test_repository.working_dir) / "show_test.txt" file_path.write_text("show content")