Skip to content

bug: reject non-root directories before updating a Git repository #541

Description

@codeforester

Goal

Ensure base_git_update_repo updates only the repository root supplied by its caller.

Background and reproduction

Release review of a90aa1429647b6eb4820a01aabe37799ca55ad5e; reproduced on macOS arm64 with Bash 5.3.20 and a network-free local bare origin.

base_git_update_repo changes into the requested directory and checks only git rev-parse --is-inside-work-tree. Git searches ancestor directories, so a plain child directory is accepted and the enclosing repository is pulled instead.

Reproduction:

  1. Create a bare local origin on main and two ordinary clones, writer and consumer.
  2. Commit/push file data containing first in writer; bring consumer to that commit.
  3. Create an ordinary empty consumer/nested directory, without .git.
  4. Commit/push data containing second in writer, leaving consumer behind.
  5. Source std, call base_init with a fresh argument array, import git, then run base_git_update_repo "$consumer/nested" "" main.

Actual: status 0; consumer HEAD advances and consumer/data changes from first to second. The requested child directory is not a repository root. Expected: reject it before fetch/pull/submodule mutation, leaving the enclosing repository unchanged. This matters for workspace updaters and partially initialized nested checkouts: a wrong or missing child checkout must not select a different repository implicitly.

The existing Git tests cover dirty, missing-origin, unreachable-origin and non-fast-forward cases, but not ancestor discovery. The documented argument is a repository path, not an arbitrary location within a worktree.

Scope and acceptance criteria

  • Compare the canonical requested directory with the discovered worktree root before any update; reject plain descendants and non-repository directories explicitly.
  • Preserve supported genuine checkout/worktree roots, paths with spaces, and documented symlink behavior; avoid a blanket requirement for a .git directory that would reject legitimate .git files.
  • Add a local-origin regression that proves parent HEAD, refs, contents and submodule state are unchanged on rejection.
  • Retain cwd/directory-stack restoration, diagnostics and status contracts; clarify the root requirement in the Git README.

Validation

Run the two-clone reproduction, focused Git BATS, ShellCheck and tests/validate.sh. No network or changes to real workspaces are needed.

Non-goals

No release publication, unrelated API redesign, or changes to consumer workspaces.

Project fields

  • Status: Ready
  • Priority: P1
  • Area: Shell
  • Initiative: Adoption Polish
  • Size: S
  • Milestone: v2.2.0

Agent assignment

Assignee: @codeforester. Implement through the normal issue-backed worktree and reviewed PR workflow.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething is not working

Type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions