Skip to content

fix: support git worktrees in discoverGitdir (absolute gitdir paths)#2293

Merged
jcubic merged 2 commits into
isomorphic-git:mainfrom
liamhess:liam/worktree-support-326
Mar 12, 2026
Merged

fix: support git worktrees in discoverGitdir (absolute gitdir paths)#2293
jcubic merged 2 commits into
isomorphic-git:mainfrom
liamhess:liam/worktree-support-326

Conversation

@liamhess

@liamhess liamhess commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Motivation

Fixes #735 — "Unresolvable reference when .git is a file (git worktree support)"

Changes

  • src/utils/discoverGitdir.js: Add isAbsolute() check before join(). If the gitdir pointer is absolute (Unix / or Windows drive letter C:\), return it directly. Relative paths (submodules) continue through the existing join(dirname(dotgit), submoduleGitdir) path unchanged.
  • __tests__/__helpers__/FixtureFSWorktree.js: New test helper (following FixtureFSSubmodule.js pattern) that creates a worktree-style fixture with a .git file pointing to an absolute gitdir path.
  • __tests__/test-worktree.js: Integration tests verifying currentBranch and resolveRef work from a simulated worktree.
  • __tests__/test-discoverGitdir-worktree.js: Unit tests for discoverGitdir covering directory, relative path (submodule), and absolute path (worktree) cases.

Note: This PR is AI generated and not hand written. I had a look at the contributor docs and reviewed it myself. However note that I still don't have a lot of knowledge about this project, so I also understand if you don't have capacity to review this :)

Summary by CodeRabbit

  • New Features

    • Made the git-directory discovery utility available through an additional module export.
  • Bug Fixes

    • Improved gitdir resolution to correctly handle absolute vs. relative paths in submodule and worktree scenarios.
  • Tests

    • Added tests covering multiple gitdir discovery cases and worktree status behavior to validate resolution and status reporting.

@coderabbitai

coderabbitai Bot commented Mar 10, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 24067527-41ed-4ed8-954f-58d88e1e24a3

📥 Commits

Reviewing files that changed from the base of the PR and between 922b759 and 2378f7f.

📒 Files selected for processing (1)
  • __tests__/test-worktree.js

📝 Walkthrough

Walkthrough

discoverGitdir now distinguishes absolute vs. relative gitdir paths read from a .git file and returns either the absolute path directly or resolves relative paths against the .git file location. New tests cover directory .git, submodule-style relative gitdir, and worktree-style absolute gitdir. discoverGitdir is re-exported via internal-apis.

Changes

Cohort / File(s) Summary
Discover Gitdir Logic
src/utils/discoverGitdir.js
Added isAbsolute() helper and conditional handling: if gitdir read from a .git file is absolute, return it; otherwise resolve relative gitdir against the .git file directory. Updated header/comments.
Public Re-exports
src/internal-apis.js
Re-exported the discoverGitdir utility: export * from './utils/discoverGitdir.js'.
Tests — discoverGitdir & worktree
__tests__/test-discoverGitdir-worktree.js, __tests__/test-worktree.js
Added tests validating .git as directory, submodule-style relative gitdir resolution, absolute worktree gitdir handling, and statusMatrix behavior when .git contains an absolute gitdir. Uses temporary fixtures and a FileSystem wrapper.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I sniffed the .git with whiskers keen,
Found paths that wander, and paths that mean.
If absolute, I leap straight through,
If relative, I follow the view.
Hooray—each worktree knows what to do. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding support for git worktrees by handling absolute gitdir paths in discoverGitdir.
Linked Issues check ✅ Passed The PR fully addresses issue #735 by implementing absolute path detection in discoverGitdir, supporting worktree scenarios, and including integration tests using public APIs (statusMatrix, currentBranch, resolveRef).
Out of Scope Changes check ✅ Passed All changes are directly related to supporting git worktrees: the isAbsolute() helper, gitdir path resolution logic, test coverage for worktree scenarios, and public API export.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +28 to +33
function isAbsolute(filepath) {
return (
filepath.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(filepath)
)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure whether this would run only in node or also in browser? I sadly don't know enough about the project :/
If this is only run in node I would switch it to use node's path.isAbsolute()

@jcubic

jcubic commented Mar 11, 2026

Copy link
Copy Markdown
Member

Failed tests:

nps is executing `test.typecheck` : tsc -p tsconfig.json
src/errors/BaseError.js(12,18): error TS2339: Property 'code' does not exist on type 'BaseError'.
src/errors/BaseError.js(13,18): error TS2339: Property 'data' does not exist on type 'BaseError'.
src/errors/BaseError.js(22,7): error TS2339: Property 'code' does not exist on type 'BaseError'.
src/errors/BaseError.js(23,7): error TS2339: Property 'data' does not exist on type 'BaseError'.
The script called "test.typecheck" which runs "tsc -p tsconfig.json" failed with exit code 2 https://github.com/sezna/nps/blob/master/other/ERRORS_AND_WARNINGS.md#failed-with-exit-code
The script called "test" which runs "nps lint && nps build.test && nps test.typecheck && nps test.setup && nps test.node && nps test.chrome && nps test.teardown" failed with exit code 2 https://github.com/sezna/nps/blob/master/other/ERRORS_AND_WARNINGS.md#failed-with-exit-code

##[error]Bash exited with code '2'.

@liamhess

Copy link
Copy Markdown
Contributor Author

@jcubic I've opened #2294 and based this branch on top of that PR. Will rebase once that one is merged. But I'm not sure if maybe it's a policy of the project to not import from src in tests. If that is the case I will gladly try to write the repro test with public apis.
Shouldn't be a big issue. I just thought that like this the test is more focused. Happy to hear your thoughts though :)

@liamhess liamhess marked this pull request as ready for review March 11, 2026 13:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
__tests__/test-discoverGitdir-worktree.js (1)

73-73: Consider adding a Windows absolute path test case.

The hardcoded Unix-style absolute path /some/absolute/path/... validates Unix worktrees. For completeness, consider adding a test with a Windows-style path like C:\\repo\\.git\\worktrees\\branch to ensure the isAbsolute regex handles both formats correctly.

💡 Example additional test case
it('returns Windows absolute gitdir path directly', async () => {
  const fsp = new FileSystem(_fs)
  const worktreeDir = path.join(tmpDir, 'win-worktree')
  await _fs.promises.mkdir(worktreeDir)
  const dotgit = path.join(worktreeDir, '.git')

  const windowsAbsoluteGitdir = 'C:\\repo\\.git\\worktrees\\my-branch'
  await _fs.promises.writeFile(dotgit, `gitdir: ${windowsAbsoluteGitdir}\n`)

  const result = await discoverGitdir({ fsp, dotgit })
  expect(result).toEqual(windowsAbsoluteGitdir)
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/test-discoverGitdir-worktree.js` at line 73, Add a Windows-style
absolute path test to __tests__/test-discoverGitdir-worktree.js that mirrors the
existing Unix test: create a worktree dir, write a .git file containing a
Windows absolute gitdir string (e.g. windowsAbsoluteGitdir =
'C:\\repo\\.git\\worktrees\\my-branch'), call discoverGitdir({ fsp, dotgit })
and assert the result equals windowsAbsoluteGitdir; this ensures the isAbsolute
detection/regex in discoverGitdir handles Windows paths as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@__tests__/test-discoverGitdir-worktree.js`:
- Line 73: Add a Windows-style absolute path test to
__tests__/test-discoverGitdir-worktree.js that mirrors the existing Unix test:
create a worktree dir, write a .git file containing a Windows absolute gitdir
string (e.g. windowsAbsoluteGitdir = 'C:\\repo\\.git\\worktrees\\my-branch'),
call discoverGitdir({ fsp, dotgit }) and assert the result equals
windowsAbsoluteGitdir; this ensures the isAbsolute detection/regex in
discoverGitdir handles Windows paths as well.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1c7b6704-bc6d-4ca7-b632-4079f65503ff

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9af9f and e584722.

📒 Files selected for processing (6)
  • .all-contributorsrc
  • README.md
  • __tests__/test-BaseError.js
  • __tests__/test-discoverGitdir-worktree.js
  • src/errors/BaseError.js
  • src/utils/discoverGitdir.js

@jcubic

jcubic commented Mar 11, 2026

Copy link
Copy Markdown
Member

maybe it's a policy of the project to not import from src in tests

Just check what the other parts of the tests are doing.

@liamhess liamhess force-pushed the liam/worktree-support-326 branch from e584722 to a7712e5 Compare March 12, 2026 09:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
__tests__/test-discoverGitdir-worktree.js (1)

65-77: Consider adding Windows-style absolute path coverage.

This test validates Unix-style absolute paths (/some/absolute/...), but the isAbsolute helper in discoverGitdir.js also handles Windows drive letters (C:\...). Adding a test case for Windows-style paths would improve confidence in cross-platform behavior.

💡 Optional: Add Windows-style absolute path test
+  it('handles Windows-style absolute gitdir path', async () => {
+    const fsp = new FileSystem(_fs)
+    const worktreeDir = path.join(tmpDir, 'win-worktree')
+    await _fs.promises.mkdir(worktreeDir)
+    const dotgit = path.join(worktreeDir, '.git')
+
+    const windowsGitdir = 'C:\\Users\\dev\\repo\\.git\\worktrees\\feature'
+    await _fs.promises.writeFile(dotgit, `gitdir: ${windowsGitdir}\n`)
+
+    const result = await discoverGitdir({ fsp, dotgit })
+    expect(result).toEqual(windowsGitdir)
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/test-discoverGitdir-worktree.js` around lines 65 - 77, Add a
Windows-style absolute path case to the existing test for discoverGitdir: create
a test similar to "does not corrupt absolute paths by joining with dirname" that
writes a .git file containing a Windows drive-letter absolute path (e.g.
"C:\\some\\absolute\\path\\.git\\worktrees\\my-branch"), call discoverGitdir({
fsp, dotgit }) and assert the returned result equals that Windows path and does
not contain the worktreeDir; this verifies discoverGitdir and its isAbsolute
handling for Windows paths (remember to escape backslashes in the test string).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@__tests__/test-discoverGitdir-worktree.js`:
- Around line 65-77: Add a Windows-style absolute path case to the existing test
for discoverGitdir: create a test similar to "does not corrupt absolute paths by
joining with dirname" that writes a .git file containing a Windows drive-letter
absolute path (e.g. "C:\\some\\absolute\\path\\.git\\worktrees\\my-branch"),
call discoverGitdir({ fsp, dotgit }) and assert the returned result equals that
Windows path and does not contain the worktreeDir; this verifies discoverGitdir
and its isAbsolute handling for Windows paths (remember to escape backslashes in
the test string).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f76405d7-a9b3-4501-a46c-af55b5311ebd

📥 Commits

Reviewing files that changed from the base of the PR and between e584722 and a7712e5.

📒 Files selected for processing (3)
  • __tests__/test-discoverGitdir-worktree.js
  • src/internal-apis.js
  • src/utils/discoverGitdir.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/discoverGitdir.js

@liamhess

Copy link
Copy Markdown
Contributor Author

maybe it's a policy of the project to not import from src in tests

Just check what the other parts of the tests are doing.

Ahh so if I understand correctly we would not import from src but export and import via isomorphic-git/internal-apis?
Or am I missing something?
Anyway this makes this PR not depend on #2294 anymore as I wrote here #2294 (comment).

Let's wait for the pipelines to run through tho, locally tests executed fine but let's see👀

@jcubic

jcubic commented Mar 12, 2026

Copy link
Copy Markdown
Member

Can you test the public API on a real Git repository? Something that breaks before your change, and after your PR it works.

Right now I'm not sure exactly what you're testing. You've changed internals and confirmed that it works like you assume it should work.

@liamhess liamhess force-pushed the liam/worktree-support-326 branch from 922b759 to 2378f7f Compare March 12, 2026 10:30
@liamhess

Copy link
Copy Markdown
Contributor Author

Can you test the public API on a real Git repository? Something that breaks before your change, and after your PR it works.

Right now I'm not sure exactly what you're testing. You've changed internals and confirmed that it works like you assume it should work.

Hey, I added a test that uses the public api the exact way I came across the bug, which is with the statusMatrix function. Would you still want to keep the test-discoverGitdir-worktree.js or only keep test-worktree.js then?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@__tests__/test-worktree.js`:
- Line 4: The import statement currently imports an unused symbol "add" from
'isomorphic-git' alongside "statusMatrix"; remove "add" from the import so only
"statusMatrix" is imported (verify there are no usages of add in the test file
and update the import in the top-level import line that references statusMatrix
and add accordingly) to silence the no-unused-vars lint warning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 26f83c81-869b-4403-bd91-ea7db2db116a

📥 Commits

Reviewing files that changed from the base of the PR and between a7712e5 and 922b759.

📒 Files selected for processing (1)
  • __tests__/test-worktree.js

Comment thread __tests__/test-worktree.js Outdated
@jcubic jcubic merged commit b55bd5f into isomorphic-git:main Mar 12, 2026
4 checks passed
@isomorphic-git-bot

Copy link
Copy Markdown
Member

🎉 This PR is included in version 1.37.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unresolvable reference when .git is a file (git worktree support)

3 participants