[PR #569] fix: handle cross-repo checkpoints when CWD is a different git repo #574

Closed
opened 2026-03-02 04:14:01 +03:00 by kerem · 0 comments
Owner

Original Pull Request: https://github.com/git-ai-project/git-ai/pull/569

State: closed
Merged: Yes


fix: handle cross-repo checkpoints when CWD is a different git repo

Summary

When an AI agent working from repos/repo-1 edits files in repos/repo-2, the checkpoint was only written to repo-1's working log. Files in repo-2 were silently filtered out by path_is_in_workdir in checkpoint.rs, so all changes showed as "human" when later committing in repo-2.

Root cause: In handle_checkpoint(), when the CWD is itself a git repo, needs_file_based_repo_detection is false and the code falls to the single-repo path. The single-repo checkpoint naturally ignores files outside its workdir — but nothing ever processes those external files.

Fix: After running the local repo checkpoint, detect any edited files outside the current repo's workdir, group them by their containing repository via group_files_by_repository, and run separate checkpoints for each external repo. Passes None as workspace boundary since external files are by definition outside the local workspace.

Updates since initial revision

  • Applied Devin Review suggestion: use repo workdir (not CWD repository_working_dir) when resolving relative external paths to absolute, fixing an inconsistency where the containment check and absolute path generation used different base directories.
  • Fixed Rust 1.93.0 rustfmt formatting differences.
  • Collapsed nested if to satisfy clippy::collapsible_if lint.
  • Removed std::process::exit(0) from the Err arm of the local checkpoint match. Previously, a local checkpoint failure would immediately terminate the process, preventing cross-repo checkpoints from ever executing. Now the failure is tracked via local_checkpoint_failed, cross-repo checkpoints run regardless, and exit(0) is called afterward (preserving the existing behavior of not propagating checkpoint errors to callers). This mirrors the multi-repo workspace error handling at lines 692–701, which continues processing other repos on failure.
  • Moved spawn_background_flush() out of the Ok arm to after cross-repo processing, so metrics are flushed for cross-repo checkpoints too.

Review & Testing Checklist for Human

  • Manually verify with a real agent in a multi-repo workspace. Tests use mock_ai which doesn't exercise the full agent preset pipeline. From repos/repo-1, have an AI (Claude Code, Cursor, etc.) edit a file in repos/repo-2, then commit in repo-2 and run git-ai blame to confirm AI attribution.
  • Verify the exit(0) deferral is safe. The local checkpoint Err arm no longer exits immediately — cross-repo checkpoints run first, then exit(0). Confirm no callers depend on the process exiting before cross-repo side effects occur.
  • Check AgentRunResult clone cost. agent_run_result.as_ref().cloned() copies the full struct including transcript. For agents with large transcripts, this could be non-trivial memory. Consider whether only the needed fields should be extracted.
  • Confirm group_files_by_repository(&external_files, None) with no workspace boundary is acceptable. This walks up the filesystem unbounded looking for .git dirs. It only runs for files already identified as external, but verify no edge cases with symlinks or deeply nested paths cause issues.

Notes

  • The three new tests were confirmed to fail before the fix and pass after.
  • CI passes on Ubuntu and macOS (all modes). Windows test jobs were still in progress at time of last check.
  • Link to Devin run
  • Requested by @svarlamov
**Original Pull Request:** https://github.com/git-ai-project/git-ai/pull/569 **State:** closed **Merged:** Yes --- # fix: handle cross-repo checkpoints when CWD is a different git repo ## Summary When an AI agent working from `repos/repo-1` edits files in `repos/repo-2`, the checkpoint was only written to repo-1's working log. Files in repo-2 were silently filtered out by `path_is_in_workdir` in `checkpoint.rs`, so all changes showed as "human" when later committing in repo-2. **Root cause:** In `handle_checkpoint()`, when the CWD is itself a git repo, `needs_file_based_repo_detection` is `false` and the code falls to the single-repo path. The single-repo checkpoint naturally ignores files outside its workdir — but nothing ever processes those external files. **Fix:** After running the local repo checkpoint, detect any edited files outside the current repo's workdir, group them by their containing repository via `group_files_by_repository`, and run separate checkpoints for each external repo. Passes `None` as workspace boundary since external files are by definition outside the local workspace. ### Updates since initial revision - Applied Devin Review suggestion: use repo `workdir` (not CWD `repository_working_dir`) when resolving relative external paths to absolute, fixing an inconsistency where the containment check and absolute path generation used different base directories. - Fixed Rust 1.93.0 `rustfmt` formatting differences. - Collapsed nested `if` to satisfy `clippy::collapsible_if` lint. - **Removed `std::process::exit(0)` from the `Err` arm** of the local checkpoint match. Previously, a local checkpoint failure would immediately terminate the process, preventing cross-repo checkpoints from ever executing. Now the failure is tracked via `local_checkpoint_failed`, cross-repo checkpoints run regardless, and `exit(0)` is called afterward (preserving the existing behavior of not propagating checkpoint errors to callers). This mirrors the multi-repo workspace error handling at lines 692–701, which continues processing other repos on failure. - Moved `spawn_background_flush()` out of the `Ok` arm to after cross-repo processing, so metrics are flushed for cross-repo checkpoints too. ## Review & Testing Checklist for Human - [ ] **Manually verify with a real agent in a multi-repo workspace.** Tests use `mock_ai` which doesn't exercise the full agent preset pipeline. From `repos/repo-1`, have an AI (Claude Code, Cursor, etc.) edit a file in `repos/repo-2`, then commit in repo-2 and run `git-ai blame` to confirm AI attribution. - [ ] **Verify the `exit(0)` deferral is safe.** The local checkpoint `Err` arm no longer exits immediately — cross-repo checkpoints run first, then `exit(0)`. Confirm no callers depend on the process exiting before cross-repo side effects occur. - [ ] **Check `AgentRunResult` clone cost.** `agent_run_result.as_ref().cloned()` copies the full struct including transcript. For agents with large transcripts, this could be non-trivial memory. Consider whether only the needed fields should be extracted. - [ ] **Confirm `group_files_by_repository(&external_files, None)` with no workspace boundary is acceptable.** This walks up the filesystem unbounded looking for `.git` dirs. It only runs for files already identified as external, but verify no edge cases with symlinks or deeply nested paths cause issues. ### Notes - The three new tests were confirmed to **fail before the fix** and **pass after**. - CI passes on Ubuntu and macOS (all modes). Windows test jobs were still in progress at time of last check. - [Link to Devin run](https://app.devin.ai/sessions/3550851e623b46fbb98592c11468acfa) - Requested by @svarlamov
kerem 2026-03-02 04:14:01 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/git-ai#574
No description provided.