Skip to content

feat: add git worktree support#651

Merged
jdx merged 1 commit intomainfrom
feat/git-worktree-support
Jan 31, 2026
Merged

feat: add git worktree support#651
jdx merged 1 commit intomainfrom
feat/git-worktree-support

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Jan 31, 2026

Summary

  • In git worktrees, .git is a file (not a directory) containing a gitdir: pointer. hk assumed .git is always a directory, causing hk install to fail with "Not a directory (os error 20)" and hooks not being found by git.
  • Added src/git_util.rs with helpers to resolve the actual git dir, common git dir (via commondir file), and hooks path — ensuring hooks are installed to the common .git/hooks/ directory where git actually looks for them, not the worktree-specific subdirectory.
  • Updated install and uninstall commands to use the resolved hooks directory.

Test plan

  • New test/worktree.bats with 6 tests:
    • hk install in a worktree
    • hk uninstall in a worktree
    • hk check in a worktree
    • hk fix in a worktree
    • Pre-commit hook fires via git commit in a worktree
    • hk run pre-commit in a worktree
  • Existing install_warn_hookspath.bats tests still pass
  • All tests pass with both libgit2 and nolibgit2 modes

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk because it changes how hk install/hk uninstall locate and modify git hooks, including new path resolution logic for worktrees; incorrect resolution could install/remove hooks in the wrong repo location.

Overview
hk install/hk uninstall now locate the repository’s hooks directory via a new git_util helper instead of assuming .git is a directory at ./.git/hooks, enabling correct behavior in git worktrees.

Adds src/git_util.rs to resolve .git when it is a gitdir: pointer file and to follow commondir so hooks are written to the common hooks directory. Includes a new test/worktree.bats suite covering install/uninstall, check/fix, and that hooks actually fire in a worktree.

Written by Cursor Bugbot for commit 2ea4640. This will update automatically on new commits. Configure here.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the hk tool by introducing robust support for Git worktrees. Previously, hk commands like install would fail in worktree environments because they incorrectly assumed the .git directory was always a physical directory, not a file pointing to the main repository's Git directory. The changes address this by providing a reliable mechanism to locate the correct Git and hooks directories, ensuring hk functions seamlessly across all Git repository configurations, including worktrees.

Highlights

  • Git Worktree Support: Added support for Git worktrees, resolving an issue where hk install failed due to incorrect assumptions about the .git directory structure.
  • New Git Utility Module: Introduced a new module src/git_util.rs with helper functions to correctly resolve the Git directory and hooks path, whether .git is a directory or a file (as in worktrees).
  • Updated Install/Uninstall Commands: Updated install and uninstall commands to leverage the new git_util functions for accurate hooks directory resolution.
  • New Worktree Tests: Included new Bats tests (test/worktree.bats) to ensure proper functionality of hk install, uninstall, and check within Git worktrees.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for git worktrees by adding a new git_util module to correctly resolve the git hooks directory, which is necessary because .git is a file in worktrees. The install and uninstall commands are updated to use this new utility, fixing failures in worktree environments. The changes are well-tested with a new worktree.bats test suite. My review includes a suggestion to improve the robustness of path resolution in an edge case and another to refactor duplicated code into a shared helper function for better maintainability. Overall, this is a valuable improvement to the tool.

Comment thread src/cli/uninstall.rs Outdated
Comment on lines +9 to +11
let cwd = std::env::current_dir()?;
let git_path = xx::file::find_up(&cwd, &[".git"])
.ok_or_else(|| eyre::eyre!("No .git found in this or any parent directory"))?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This logic to find the .git path is also present in src/cli/install.rs. To improve maintainability and reduce code duplication, consider extracting this logic into a new helper function within the git_util module.

For example, you could add this function to src/git_util.rs:

pub fn find_git_path_from_cwd() -> Result<PathBuf> {
    let cwd = std::env::current_dir()?;
    xx::file::find_up(&cwd, &[".git"])
        .ok_or_else(|| eyre::eyre!("No .git found in this or any parent directory"))
}

Then, both install.rs and uninstall.rs could simply call let git_path = git_util::find_git_path_from_cwd()?;.

Comment thread src/git_util.rs
Comment on lines +26 to +29
git_path
.parent()
.unwrap_or(Path::new("."))
.join(&gitdir_path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using unwrap_or with Path::new(".") could lead to incorrect behavior in the unlikely edge case where git_path.parent() returns None. This could happen if .git is at the filesystem root and the current working directory is different. It's more robust to return an error in this case. Consider using ok_or_else to handle the None case and provide a clear error message.

Suggested change
git_path
.parent()
.unwrap_or(Path::new("."))
.join(&gitdir_path)
git_path
.parent()
.ok_or_else(|| eyre!("could not determine parent directory of .git file: {}", git_path.display()))?
.join(&gitdir_path)

@jdx jdx changed the title feat(install): add git worktree support feat: add git worktree support Jan 31, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON, but a Cloud Agent failed to start.

Comment thread src/git_util.rs
@jdx jdx force-pushed the feat/git-worktree-support branch from d169c58 to c69890a Compare January 31, 2026 12:09
In git worktrees, .git is a file containing a gitdir pointer rather
than a directory. Resolve the actual git dir and hooks path by parsing
this file when needed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx force-pushed the feat/git-worktree-support branch from c69890a to 2ea4640 Compare January 31, 2026 12:20
@jdx jdx merged commit ed61254 into main Jan 31, 2026
18 checks passed
@jdx jdx deleted the feat/git-worktree-support branch January 31, 2026 12:33
@jdx jdx mentioned this pull request Jan 31, 2026
jdx added a commit that referenced this pull request Feb 1, 2026
### 🚀 Features

- **(init)** add auto-detection and interactive mode by
[@jdx](https://github.com/jdx) in
[#656](#656)
- **(stash)** use haiku names for stash patch backups by
[@jdx](https://github.com/jdx) in
[#655](#655)
- add git worktree support by [@jdx](https://github.com/jdx) in
[#651](#651)
- add "did you mean?" suggestions for typos by
[@jdx](https://github.com/jdx) in
[#654](#654)

### 🚜 Refactor

- use xx utilities and drop unused dependencies by
[@jdx](https://github.com/jdx) in
[#653](#653)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk release bookkeeping: mainly version string/package URL
updates and regenerated CLI docs, with no substantive runtime logic
changes.
> 
> **Overview**
> Releases **v1.35.0** by updating crate versions
(`Cargo.toml`/`Cargo.lock`) and adding the `1.35.0` entry to
`CHANGELOG.md`.
> 
> Regenerates documentation and examples to reference `v1.35.0` package
URLs and CLI version metadata, and updates `hk init` docs/usage to
include the new `--interactive` flag.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
46c426e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <123107610+mise-en-dev@users.noreply.github.com>
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.

1 participant