Commit graph

19 commits

Author SHA1 Message Date
Stefan Haller 80ad2db71a Recognize worktrees among the files from the worktrees model
Finding out which of the files are worktrees of ours had its own answer
to where this repo's worktrees are, walking the directory that git keeps
them in. The worktrees panel asks git itself, and that is the better
answer: it is the one git gives for the same question elsewhere in the
app, and it doesn't need to know where git records what.

The model that panel fills is all the files need, so mark them from it.
That takes the work out of the file loader, whose other two callers were
paying for it without wanting it, and it costs no git call at all: both
models are written on the UI thread, so whichever of the two refreshes
lands second marks the files against the other's fresh data.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 11:26:58 +02:00
Stefan Haller f141fcc570 Open the repo when lazygit is started in its .git dir
Running lazygit in a .git dir got you told you were in a bare repo,
which you weren't: the worktree was sitting right there, one directory
up. git's own convention is that a git dir called .git belongs to the
directory holding it — that's how `git worktree list` names the main
worktree — so ask that directory, and if it is a worktree, open the repo
we were really being asked about.

The git dirs that aren't called .git keep the answer they had. A linked
worktree's and a submodule's do have a worktree, but nothing we look at
says where, so we would be guessing; a bare repo's has none to find.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:15:01 +02:00
Stefan Haller d19af37ee7 Tell git where the repo is when it can't find it itself
git finds a repo by looking for a .git in the directory a command runs
in. Lazygit runs its commands in the work tree, so that normally works —
but not when the git dir lives somewhere else entirely, which is what
core.worktree and --work-tree are for. Lazygit chdir'd into such a work
tree and then ran commands that couldn't see any repo from there, so
opening a repo with core.worktree set panicked on startup. It only
worked with --git-dir because that leaves GIT_DIR in the environment for
every command to inherit.

Work out at startup whether git can find the repo from its work tree,
and when it can't, put GIT_DIR and GIT_WORK_TREE on every command the
repo's builder produces. As with the working directory the builder pins
(527124d0e0), these also go into the process env — subprocesses don't
come through the builder — but the commands don't read them from there,
because the process env belongs to whichever repo we have switched to
since.

Working out whether git can find the repo means asking git, rather than
reading the .git file, whose contents can spell the same directory
differently than git does. The extra query is skipped for a repo whose
git dir is simply its .git directory, which is nearly all of them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:15:01 +02:00
Stefan Haller 34d41b5d51 Don't let our repo answer for a different one
GIT_DIR and GIT_WORK_TREE tell git where our repo is, and every command
we run inherits them — including the ones we point at a submodule or
another worktree. git resolves those against our repo instead, and says
nothing about it: with GIT_DIR set, `git -C mysub log -1` reports the
superproject's commit. So opening lazygit with --git-dir/--work-tree
quietly broke resolving submodule conflicts, stashing and resetting a
submodule, and detaching another worktree; the worktree list came back
claiming every worktree shared our git dir.

Drop the two variables from the commands that address another repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:15:01 +02:00
Stefan Haller 0ce248d1bf Recognize a repo that has no work tree instead of bailing out
git makes `rev-parse --show-toplevel` fatal when there's no work tree,
so asking for it together with everything else meant we never got an
answer at all for a bare repo: GetRepoPaths returned an error, nobody
ever saw IsBareRepo() == true, and lazygit either died with a stack
trace or decided we weren't in a repository. That's what you got for
opening it in a directory holding a bare repo and a .git file pointing
at it, which is a normal way to keep a repo and its worktrees together.

Ask again without --show-toplevel when the first query fails: the other
queries work fine without a work tree, so if they now succeed we know
we're in a bare repo, and the existing prompt offering to open a recent
repo does its job. If they fail too we're not in a repo at all, and the
first error already says so.

--is-bare-repository is gone from the query: a work tree implies
core.bare is false, so it could only ever come back false there, and
what matters to us is whether there is a work tree to show, which is
what we now go by.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:15:01 +02:00
Stefan Haller e17ed2484c Use the work tree as the repo path when it is the main worktree
RepoPath() is meant to be the same as WorktreePath() when we're in the
main worktree, but we derived it from the git dir's location instead.
That is only the same thing when the git dir lives inside the work tree.
With core.worktree, --work-tree, or a .git file pointing at a repo dir
that isn't called .git, it lands on a directory that isn't a worktree at
all, and the repo name we show follows it there.

A worktree that has the repo's common git dir to itself is the main
worktree, so use its path. That subsumes the submodule case, whose git
dir lives under the superproject's .git/modules but is still the
submodule's own common dir; --show-superproject-working-tree is now only
needed for a linked worktree of a submodule.

The existing bare repo test asserted a git output that can't occur (a
work tree and --is-bare-repository=true at once), but the rest of it is
the shape of a repo opened with --git-dir/--work-tree, where the new
repo path is the correct one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:15:01 +02:00
Stefan Haller c739357eb9 Remove git version specific code for versions we no longer support 2025-07-09 12:18:58 +02:00
Stefan Haller ca05a2ccea Enable revive linter, and fix a bunch of warnings
I took the set of enabled checks from revive's recommended configuration [1],
and removed some that I didn't like. There might be other useful checks in
revive that we might want to enable, but this is a nice improvement already.

The bulk of the changes here are removing unnecessary else statements after
returns, but there are a few others too.

[1] https://github.com/mgechev/revive?tab=readme-ov-file#recommended-configuration
2025-06-30 19:13:20 +02:00
Stefan Haller 75a95865ff Use filepath instead of path for file path operations
In practice, using path seems to work too, since Windows seems to be capable of
dealing with a path like C:/x/y instead of C:\x\y; but it's cleaner to do this
properly.
2024-08-18 10:24:52 +02:00
John Whitley 7a670964cd Optimize number of early calls to GetRepoPaths
This change reduces the number of calls during application startup to
one, calling GetRepoPaths() earlier than previously and plumbing the
repoPaths struct around to achieve this end.
2024-07-06 12:09:48 -07:00
John Whitley 3d9f1e02e5 Refactor repo_paths.go to use git rev-parse
This changes GetRepoPaths() to pull information from `git rev-parse`
instead of effectively reimplementing git's logic for pathfinding. This
change fixes issues with bare repos, esp. versioned homedir use cases,
by aligning lazygit's path handling to what git itself does.

This change also enables lazygit to run from arbitrary subdirectories of
a repository, including correct handling of symlinks, including "deep"
symlinks into a repo, worktree, a repo's submodules, etc.

Integration tests are now resilient against unintended side effects from
the host's environment variables. Of necessity, $PATH and $TERM are the
only env vars allowed through now.
2024-01-24 08:40:01 +01:00
Cristian Betivu 7a4a0c85c4 Fix test 2023-08-19 19:12:36 +03:00
Cristian Betivu ee308a4994 Clean before convertion? 2023-08-19 18:36:57 +03:00
Cristian Betivu a2b2336173 Stylistic changes 2023-08-19 18:36:57 +03:00
Cristian Betivu d7b1deb465 Clean path 2023-08-19 18:36:57 +03:00
Cristian Betivu dd01639f57 Improve error message 2023-08-19 18:36:57 +03:00
Jesse Duffield 8e7958f78b Fix seg-fault when opening submodule in nested folder 2023-08-07 23:57:28 +10:00
Jesse Duffield 595e28d335 Support bare worktrees where worktree does not have its own .git file
This was on oversight on my part: I assumed that the --work-tree arg was
always intended for use with linked worktrees which have a .git file
pointing back to the repo.

I'm honestly confused now: seems like there are three kinds of worktrees:
* the main worktree of a non-bare repo
* a linked worktree (with its own gitdir in the repo's worktrees/ dir)
* a random folder which you specify as a worktree with the --work-tree arg

I'm pretty sure the --work-tree arg is only intended to be used with this
third kind or workree
2023-08-07 22:40:53 +10:00
Jesse Duffield f31e213edc rename files 2023-07-30 18:35:36 +10:00
Renamed from pkg/commands/git_commands/paths.go (Browse further)