Skip to content

fix(sync): strip .git/ from cloned repos to fix gitlink bug#720

Open
shashank-poola wants to merge 4 commits intogetnao:mainfrom
shashank-poola:main
Open

fix(sync): strip .git/ from cloned repos to fix gitlink bug#720
shashank-poola wants to merge 4 commits intogetnao:mainfrom
shashank-poola:main

Conversation

@shashank-poola
Copy link
Copy Markdown

Closes #716

Problem

When nao sync clones a git repo into repos/<name>/, it leaves a .git/ folder inside. Git sees this nested .git/ and treats the whole directory as a gitlink (mode 160000) instead of regular tracked files.

So when you commit and push the context repo, Git only stores a SHA pointer, not the actual file content. Anyone who clones that repo after you, a teammate, CI pipeline, or the deployed agent, gets an empty folder, silently, with no errors.

The files only ever exist on the machine that ran nao sync.

# Before this fix, git was storing a pointer, not files
$ git ls-tree -r HEAD repos/
160000 commit bf48ed0a...    repos/dbt

What We Changed

cli/nao_core/commands/sync/providers/repositories/provider.py

  • After a successful clone, we now call shutil.rmtree(repo_path / ".git") to strip the nested Git repo
  • repos/<name>/ becomes a plain folder, git add now commits actual file content, not a SHA pointer
  • Since .git/ no longer exists after first sync, git pull on re-sync is not possible, changed to always re-clone fresh (delete → clone → strip)

cli/nao_core/commands/sync/cleanup.py (bonus fix)

  • cleanup_stale_repos called base_path.iterdir() before repos/ existed on first sync
  • This crashed every first-time sync with [Errno 2] No such file or directory: 'repos'
  • Fixed with a simple early return: if not base_path.exists(): return

Proof

$ uv run nao sync
  Cloning dbt
  ✓ dbt

# .git/ is gone — no more gitlink
$ ls repos/dbt/.git
No such file or directory

# actual files are there and committable
$ ls repos/dbt/
Dockerfile  README.md  dbt_project.yml  models  seeds  profiles.yml ...

Screenshot attached below, shows sync success, .git/ stripped, and real files present in one run.

Screenshot 2026-05-05 010608

Impact

  • Fixes silent data loss for all teams using git repo context sources
  • Fixes first-time sync crash when repos/ doesn't exist yet
  • Files in repos/<name>/ are now portable: committable, pushable, and readable by the deployed agent

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

This PR was auto-closed. Only contributors approved with lgtm can open PRs. Open an issue first.

Maintainers review auto-closed issues daily. Issues that do not meet the quality bar in CONTRIBUTING.md will not be reopened or receive a reply.

If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

See CONTRIBUTING.md.

@github-actions github-actions Bot closed this May 4, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cli/nao_core/commands/sync/providers/repositories/provider.py">

<violation number="1" location="cli/nao_core/commands/sync/providers/repositories/provider.py:27">
P1: Unvalidated `repo.name` is used to build the deletion target, so `shutil.rmtree()` can delete outside the sync root via `../` or absolute paths.</violation>

<violation number="2" location="cli/nao_core/commands/sync/providers/repositories/provider.py:27">
P1: Non-atomic re-clone flow deletes existing repo before verifying clone succeeds, causing data loss on transient failures.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread cli/nao_core/commands/sync/providers/repositories/provider.py Outdated
Comment thread cli/nao_core/commands/sync/providers/repositories/provider.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

🚀 Preview Deployment

URL https://pr-720-26b52e8.preview.getnao.io
Commit 26b52e8

⚠️ No LLM API keys configured - you'll see the API key setup flow when trying to chat.


Preview will be automatically removed when this PR is closed.

@Bl3f Bl3f reopened this May 5, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cli/nao_core/commands/sync/providers/repositories/provider.py">

<violation number="1" location="cli/nao_core/commands/sync/providers/repositories/provider.py:25">
P2: Path resolution for the new traversal guard happens outside the function's existing error handling, so a resolve failure can abort the whole sync instead of failing just this repo.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread cli/nao_core/commands/sync/providers/repositories/provider.py Outdated
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.

[CRITICAL bug] nao sync clones git repos but agent cannot access their content

2 participants