Skip to content

fix(git): use git CLI in git_add to avoid GitPython index corruption bug#3156

Closed
schuyler wants to merge 1 commit intomodelcontextprotocol:mainfrom
schuyler:main
Closed

fix(git): use git CLI in git_add to avoid GitPython index corruption bug#3156
schuyler wants to merge 1 commit intomodelcontextprotocol:mainfrom
schuyler:main

Conversation

@schuyler
Copy link
Copy Markdown

Description

GitPython's index.add() has a known bug that corrupts the git index when paths contain ./ prefixes or when . is included in the file list. The bug causes:

  • Files appearing with ./ prefix (e.g., ./index.md)
  • The .git directory itself being staged
  • Corrupted commits requiring git filter-repo to fix

Motivation and Context

The previous implementation only handled the exact case of ["."] but failed to handle [".", "other.md"] or ["./README.md"]. This fix uses repo.git.add() (CLI wrapper) for all cases, which is consistent with how other git operations are implemented in this file and correctly handles all edge cases.

Testing

I have been using the mcp-server-git MCP to allow Claude to edit a private otterwiki. Prior to making this change locally, I was seeing corruption of the Git repository every few commits. Since applying the change about a week ago, I have been using the wiki with Claude every single day and have not seen a single error of any kind.

Breaking Changes

None

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Protocol Documentation
  • My changes follows MCP security best practices
  • I have updated the server's README accordingly
  • I have tested this with an LLM client
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have documented all environment variables and configuration options

References

GitPython's index.add() has a known bug that corrupts the git index when
paths contain ./ prefixes or when . is included in the file list. The bug
causes:
- Files appearing with ./ prefix (e.g., ./index.md)
- The .git directory itself being staged
- Corrupted commits requiring git filter-repo to fix

The previous implementation only handled the exact case of ["."] but failed
to handle [".", "other.md"] or ["./README.md"]. This fix uses repo.git.add()
(CLI wrapper) for all cases, which is consistent with how other git
operations are implemented in this file and correctly handles all edge cases.

References:
- gitpython-developers/GitPython#375
- gitpython-developers/GitPython#292
@olaservo
Copy link
Copy Markdown
Member

Thanks for catching this and for the great reproduction!

The GitPython index.add() bug you describe is real, but the core fix has already landed. Commit db96050800 ("git: improve file path validation in add operation") on 2025-12-29 — two days after you opened this PR — replaced repo.index.add(files) with repo.git.add("--", *files). Both branches of git_add now shell out to the git CLI, so GitPython issue #375 no longer applies.

Unfortunately, the change proposed here (repo.git.add(files)) would drop the -- separator, which we rely on as defense-in-depth against flag injection — see also the related hardening in commit ae40ec239d for the other git tools. So we can't merge the source change as-is.

Your two new tests (test_git_add_with_dot_prefix and test_git_add_mixed_dot_and_files) are genuinely useful regression coverage though — both should pass on current main. Would you be willing to open a small follow-up PR with just those tests? That would guard against anyone reverting to index.add in the future.

Closing on that basis — thanks again for the thorough investigation!

(Triaged with help from Claude Code.)

@olaservo olaservo closed this Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants