lazygit icon indicating copy to clipboard operation
lazygit copied to clipboard

Exclude file does not work inside submodules

Open cbebe opened this issue 2 years ago • 1 comments

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:

  1. Clone a repository with a submodule
  2. Open submodule in lazygit
  3. Try to exclude an untracked file by pressing i then e
  4. 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.

cbebe avatar Mar 24 '24 20:03 cbebe

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.

stefanhaller avatar Mar 25 '24 15:03 stefanhaller