From 498a530ab7e465c476dbcaa691e34934e02ee231 Mon Sep 17 00:00:00 2001 From: Tom Amberson <53712733+TommyAmberson@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:41:40 -0600 Subject: [PATCH 1/3] Refactor determineMainBranches to return multiple refs per entry --- pkg/commands/git_commands/main_branches.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/commands/git_commands/main_branches.go b/pkg/commands/git_commands/main_branches.go index 109f9cfd8..a177984f7 100644 --- a/pkg/commands/git_commands/main_branches.go +++ b/pkg/commands/git_commands/main_branches.go @@ -77,10 +77,10 @@ func (self *MainBranches) GetMergeBase(refName string) string { } func (self *MainBranches) determineMainBranches(configuredMainBranches []string) []string { - var existingBranches []string + var matchedBranches [][]string var wg sync.WaitGroup - existingBranches = make([]string, len(configuredMainBranches)) + matchedBranches = make([][]string, len(configuredMainBranches)) for i, branchName := range configuredMainBranches { wg.Add(1) @@ -91,7 +91,7 @@ func (self *MainBranches) determineMainBranches(configuredMainBranches []string) if ref, err := self.cmd.New( NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(), ).DontLog().RunWithOutput(); err == nil { - existingBranches[i] = strings.TrimSpace(ref) + matchedBranches[i] = []string{strings.TrimSpace(ref)} return } @@ -101,7 +101,7 @@ func (self *MainBranches) determineMainBranches(configuredMainBranches []string) if err := self.cmd.New( NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(), ).DontLog().Run(); err == nil { - existingBranches[i] = ref + matchedBranches[i] = []string{ref} return } @@ -112,16 +112,15 @@ func (self *MainBranches) determineMainBranches(configuredMainBranches []string) if err := self.cmd.New( NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(), ).DontLog().Run(); err == nil { - existingBranches[i] = ref + matchedBranches[i] = []string{ref} + return } }) } wg.Wait() - existingBranches = lo.Filter(existingBranches, func(branch string, _ int) bool { - return branch != "" - }) + existingBranches := lo.Flatten(matchedBranches) return existingBranches } From f04b303f58e7cb2a9e47366e7cd6222bf6a950eb Mon Sep 17 00:00:00 2001 From: Tom Amberson <53712733+TommyAmberson@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:15:18 -0600 Subject: [PATCH 2/3] Support fnmatch patterns in mainBranches config Use `git for-each-ref` to resolve patterns containing *, ?, or [ against both local and origin remote branches. Exact branch names continue to use `git rev-parse` for fast lookups. --- pkg/commands/git_commands/main_branches.go | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pkg/commands/git_commands/main_branches.go b/pkg/commands/git_commands/main_branches.go index a177984f7..54a67ce0c 100644 --- a/pkg/commands/git_commands/main_branches.go +++ b/pkg/commands/git_commands/main_branches.go @@ -87,6 +87,31 @@ func (self *MainBranches) determineMainBranches(configuredMainBranches []string) go utils.Safe(func() { defer wg.Done() + // Check for glob patterns first + if strings.ContainsAny(branchName, "*?[") { + branchPattern := branchName + var refs []string + + // Check local branches + if output, err := self.cmd.New( + NewGitCmd("for-each-ref").Arg("--format=%(refname)", "refs/heads/"+branchPattern).ToArgv(), + ).DontLog().RunWithOutput(); err == nil { + refs = append(refs, strings.Fields(strings.TrimSpace(output))...) + } + + // Check remote branches on 'origin' + if output, err := self.cmd.New( + NewGitCmd("for-each-ref").Arg("--format=%(refname)", "refs/remotes/origin/"+branchPattern).ToArgv(), + ).DontLog().RunWithOutput(); err == nil { + refs = append(refs, strings.Fields(strings.TrimSpace(output))...) + } + + matchedBranches[i] = lo.Filter(refs, func(ref string, _ int) bool { + return ref != "" + }) + return + } + // Try to determine upstream of local main branch if ref, err := self.cmd.New( NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(), From 2e72dcb3a6f6d85781d6f4107ff986deabf1b46a Mon Sep 17 00:00:00 2001 From: Tom Amberson <53712733+TommyAmberson@users.noreply.github.com> Date: Fri, 20 Feb 2026 22:15:43 -0600 Subject: [PATCH 3/3] Add test for glob_main_branches --- .../tests/branch/glob_main_branches.go | 41 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 2 files changed, 42 insertions(+) create mode 100644 pkg/integration/tests/branch/glob_main_branches.go diff --git a/pkg/integration/tests/branch/glob_main_branches.go b/pkg/integration/tests/branch/glob_main_branches.go new file mode 100644 index 000000000..14ba4adff --- /dev/null +++ b/pkg/integration/tests/branch/glob_main_branches.go @@ -0,0 +1,41 @@ +package branch + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var GlobMainBranches = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Verify that glob patterns in mainBranches config match correctly", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.MainBranches = []string{"release/*"} + }, + SetupRepo: func(shell *Shell) { + shell. + EmptyCommit("initial"). + NewBranch("release/1"). + EmptyCommit("release 1 commit"). + NewBranchFrom("feature", "release/1"). + EmptyCommit("feature 1"). + EmptyCommit("feature 2") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("feature 2").IsSelected(), + Contains("feature 1"), + Contains("release 1 commit"), + Contains("initial"), + ). + Press(keys.Commits.SelectCommitsOfCurrentBranch). + Lines( + Contains("feature 2").IsSelected(), + Contains("feature 1").IsSelected(), + Contains("release 1 commit"), + Contains("initial"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 4d9edaa70..b817d1d87 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -50,6 +50,7 @@ var tests = []*components.IntegrationTest{ branch.DeleteRemoteBranchWithDifferentName, branch.DeleteWhileFiltering, branch.DetachedHead, + branch.GlobMainBranches, branch.MergeFastForward, branch.MergeNonFastForward, branch.MoveCommitsToNewBranchFromBaseBranch,