Skip to content

Conversation

sQVe
Copy link

@sQVe sQVe commented Jul 29, 2025

Summary

Enables lazygit to work with bare Git repositories that use worktrees, fixing crashes when running lazygit from directories containing bare repo + worktree setups. This resolves the "fatal: this operation must be run in a work tree" error that prevents lazygit from starting in these advanced Git workflow scenarios.

Problem solved: Previously, running lazygit in a directory like:

/project/
├── .bare/          # bare repository
├── main/           # worktree for main branch
└── .git            # points to .bare

Would crash with: fatal: this operation must be run in a work tree

Solution: lazygit now detects the bare repo setup and automatically opens in the appropriate worktree (e.g., main branch).

Changes

  • Bare repository detection: Added detection logic for common bare repo patterns (.bare, bare.git, .git)
  • Worktree selection: Implemented algorithm to automatically select the best worktree, prioritizing default branch, then main/master, then alphabetical order
  • Comprehensive test coverage: Added 218 lines of tests covering various bare repo + worktree scenarios including edge cases

Test Plan

For reviewers to verify:

  • Test with standard non-bare repositories (existing functionality unchanged)
  • Test bare repository with single worktree (should work automatically)
  • Test bare repository with multiple worktrees (should select main/master branch worktree)
  • Test bare repository with custom default branch (should select correctly)
  • Test error handling for invalid/missing bare repositories
  • Run existing test suite to ensure no regressions: go test ./pkg/commands/git_commands/
  • Test path traversal protection with malicious directory inputs

Enables lazygit to work with bare Git repositories that use worktrees, improving compatibility with advanced Git workflows.
@stefanhaller
Copy link
Collaborator

Sorry for the delay in looking at this.

I'm not experienced with either bare repos or worktrees (even in non-bare repos), so maybe these are stupid questions, but I don't understand why you can't simply cd into your worktree and run lazygit there. In my brief testing, this worked fine with a worktree that is attached to a bare repo. But I also don't understand what /project/.git is in your picture above, so maybe your setup is somehow different from what I thought is the usual one. Can you explain?

@sQVe
Copy link
Author

sQVe commented Aug 13, 2025

Sorry for the delay in looking at this.

No problem at all. I've been real busy also 😉

Can you explain?

Yes, of course!

There is a worktree structure that is considered best practice, and most common. This pattern is recommended because it:

  • Keeps all worktrees organized under a single project directory
  • Maintains a single source of truth for all branches and history
  • Allows for executing git commands from project/ directory.

You structure your project like this:

project/
 ├── .bare/          # The bare repository
 ├── feat-example/   # Worktree for feat-example branch
 ├── hotfix/         # Worktree for quick hotfixes
 ├── main/           # Worktree for main branch
 └── .git            # Optional: Git file with `gitdir: .bare` that makes regular git commands work from project root

This allows you to get a great overview of your worktrees, while keeping your version history at one place. You are essentially creating a pool of worktrees that you can move in and out of.

Current behavior (crashes):

cd /project
lazygit
# Error: fatal: this operation must be run in a work tree

Expected behavior (with this PR):

cd /project
lazygit
# Automatically detects bare repo setup and opens in main worktree

Why not just "cd into the worktree"?

You're absolutely right that users can cd into the worktree and run lazygit there. However:

  1. Project-level operations: My git information is housed within the .bare/ directory, which resides in the root of the project/ directory. As a user I would expect to be able to open lazygit from the project/ root.
  2. Awkward workflow: I find it very awkward to cd into one worktree to do things like:
    • Removing another worktree
    • Viewing the overall worktree status
    • Managing branches across all worktrees
    • These are project-level operations, not worktree-specific ones
  3. Workflow consistency: Other Git tools (like git itself) work from the project root when there's a .git file pointing to the bare repo. For example, git worktree list works from /project/.

I hope that clarifies why I created this PR. 🙏🏼

@stefanhaller
Copy link
Collaborator

Thanks for the explanation, makes a lot of sense. The setup sounds very useful, and I'm probably going to switch to that setup for my work repos.

However, I'm not convinced yet that being able to open lazygit from project/ is a good idea. This would make it seem like you can open the bare repo itself with lazygit, and work with it like you can with git CLI. This could be confusing; for example, if you cd into project/ and launch lazygit in order to create a new worktree, you might think that you should use a path like my-new-wt to create it under project/. However, you need to use ../my-new-wt, and that's very non-obvious I think. Having to explicitly cd into one of your worktrees and launch lazygit there makes this much clearer for me.

I feel that we shouldn't weaken the requirement that lazygit needs a worktree in order to work. Only work trees show up in the recent repos list; the project/ directory doesn't.

I'm still new to this workflow, so maybe I'm missing things here. Will play with this some more to get a better feeling for it.

@stefanhaller
Copy link
Collaborator

I switched my repos at work to this setup, and have been liking it a lot. (I omitted the project/.git gitdir file though because I don't need it; I almost never use git on the command line, and I don't expect to be able to work with the bare repo without a worktree.)

Working with this setup didn't change my mind from what I wrote above: I simply don't expect to be able to start lazygit in the project/ folder and have it auto-pick a suitable worktree for me to cd into. I prefer if the user needs to do this explicitly, as discussed above.

However, there are a few bugs around starting lazygit in a bare repo:

  • when starting lazygit from within .bare, and you haven't set the notARepository config, it prompts you whether you want to create a new repo here. This doesn't make sense, the prompt should either be a choice between "open most recent" and "quit", or it shouldn't prompt at all and behave as if you had set notARepository to skip. If it is set to create, it should error out I guess.
  • when starting in a directory that has a gitdir file pointing to a bare repo, you get an error ("fatal: this operation must be run in a work tree"). This should probably behave as if you had started from within the bare repo.

Once these are fixed, I could also imagine an improvement to how we pick the most recent repo to open: if you open lazygit in a bare repo, it could check for worktrees attached to that bare repo, and see if your recent repos list contains any of those. If so, pick the first (most recent) one, and otherwise open the first recent repo as normal. I suppose this would mostly give you the functionality that you were after with this PR, except for the very first time you open lazygit in project/.

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.

2 participants