Exclude file does not work inside submodules
Describe the bug
Appending the file name to the .git/info/exclude file does not work because .git might not be a directory.
To Reproduce Steps to reproduce the behavior:
- Clone a repository with a submodule
- Open submodule in
lazygit - Try to exclude an untracked file by pressing
ithene - See error
open .git/info/exclude: not a directory
Expected behavior
File gets added to exclude list and gets ignored by Git.
Screenshots If applicable, add screenshots to help explain your problem.
Version info:
commit=fb675b79f8a4a949294e8cab85ce72fed3883362, build date=2024-03-23T22:49:22Z, build source=unknown, version=fb675b79, os=linux, arch=amd64, git version=2.34.1
git version 2.34.1
Additional context
This most likely happens because .git is just a file that points to the actual .git directory when inside a submodule like so:
gitdir: ../../.git/modules/<SUBMODULE_NAME>
This can be solved by first checking if .git is a directory and resolving to the repo's actual exclude file.
diff --git a/pkg/commands/git_commands/working_tree.go b/pkg/commands/git_commands/working_tree.go
index 99665d7c..a5fa5993 100644
--- a/pkg/commands/git_commands/working_tree.go
+++ b/pkg/commands/git_commands/working_tree.go
@@ -3,6 +3,8 @@ package git_commands
import (
"fmt"
"os"
+ "path/filepath"
+ "strings"
"github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/commands/models"
@@ -232,7 +234,27 @@ func (self *WorkingTreeCommands) Ignore(filename string) error {
// Exclude adds a file to the .git/info/exclude for the repo
func (self *WorkingTreeCommands) Exclude(filename string) error {
- return self.os.AppendLineToFile(".git/info/exclude", filename)
+ // .git might not be a directory if repo is a submodule
+ gitDir := ".git"
+ fileInfo, err := os.Stat(gitDir)
+ if err != nil {
+ return err
+ }
+
+ if !fileInfo.IsDir() {
+ // Submodule, try to resolve gitdir
+ file, err := os.ReadFile(gitDir)
+ if err != nil {
+ return err
+ }
+ _, actualDirPath, ok := strings.Cut(string(file), "gitdir: ")
+ if !ok {
+ return fmt.Errorf("invalid gitdir file")
+ }
+ gitDir = actualDirPath
+ }
+
+ return self.os.AppendLineToFile(filepath.Join(gitDir, "info/exclude"), filename)
}
// WorktreeFileDiff returns the diff of a file
Note: please try updating to the latest version or manually building the latest master to see if the issue still occurs.
Thanks for the report, easy to reproduce.
Your proposed fix above is much more complicated than it needs to be though. Here's a much simpler fix: #3432.