Sort remote branches with the same committer date in stack order

Force-pushing a stack of branches puts the same commits on the remote,
so the remote branches panel shows the same alphabetical order for a
stack that the local branches panel did. Sort them by ancestry too,
which needs the tip hash and committer date of each remote branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-09-19 18:10:59 +02:00
co-authored by Claude Opus 5
parent b915850300
commit afb66f78a9
3 changed files with 79 additions and 10 deletions
+26 -10
View File
@@ -116,27 +116,32 @@ func (self *RemoteLoader) getRemoteBranchesByRemoteName() (map[string][]*models.
// Returns all remote branches, sorted the way the config asks for
func (self *RemoteLoader) getRemoteBranches() ([]*models.RemoteBranch, error) {
var sortOrder string
switch strings.ToLower(self.UserConfig().Git.RemoteBranchSortOrder) {
case "alphabetical":
sortOrder = "refname"
case "date":
sortByDate := strings.ToLower(self.UserConfig().Git.RemoteBranchSortOrder) == "date"
sortOrder := "refname"
if sortByDate {
sortOrder = "-committerdate"
default:
sortOrder = "refname"
}
// Asking for the tip of a branch makes git read its commit, so only do it
// when we are going to sort by ancestry below
format := "%(refname)"
if sortByDate {
format += "%00%(objectname)%00%(committerdate:unix)"
}
cmdArgs := NewGitCmd("for-each-ref").
Arg(fmt.Sprintf("--sort=%s", sortOrder)).
Arg("--format=%(refname)").
Arg(fmt.Sprintf("--format=%s", format)).
Arg("refs/remotes").
ToArgv()
remoteBranches := []*models.RemoteBranch{}
tips := map[string]refTip{}
err := self.cmd.New(cmdArgs).DontLog().RunAndProcessLines(func(line string) (bool, error) {
line = strings.TrimSpace(line)
fields := strings.Split(strings.TrimSpace(line), "\x00")
refName := fields[0]
split := strings.SplitN(line, "/", 4)
split := strings.SplitN(refName, "/", 4)
if len(split) != 4 {
return false, nil
}
@@ -152,11 +157,22 @@ func (self *RemoteLoader) getRemoteBranches() ([]*models.RemoteBranch, error) {
Name: name,
RemoteName: remoteName,
})
if len(fields) == 3 {
tips[refName] = refTip{hash: fields[1], committerDate: fields[2]}
}
return false, nil
})
if err != nil {
return nil, err
}
if sortByDate {
if err := sortRefsWithEqualDatesByAncestry(
self.cmd, self.version, remoteBranches, (*models.RemoteBranch).FullRefName, tips,
); err != nil {
self.Log.Errorf("Failed to sort remote branches by ancestry: %v", err)
}
}
return remoteBranches, nil
}
@@ -0,0 +1,52 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var SortRemoteBranchesInStackOrder = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Sort remote branches that share a committer date so that a branch comes before the ones it is based on",
ExtraCmdArgs: []string{},
Skip: false,
GitVersion: AtLeast("2.41.0"),
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.RemoteBranchSortOrder = "date"
},
SetupRepo: func(shell *Shell) {
// Rebasing a stack of branches gives every commit it creates the same
// committer date; give these commits one date for the same effect.
date := "2024-01-01 10:00:00"
shell.
EmptyCommitWithDate("base", date).
NewBranch("branch-c").
EmptyCommitWithDate("c", date).
NewBranch("branch-a").
EmptyCommitWithDate("a", date).
NewBranch("branch-b").
EmptyCommitWithDate("b", date).
NewBranchFrom("unrelated", "master").
EmptyCommitWithDate("unrelated", date).
Checkout("master").
CloneIntoRemote("origin")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Remotes().
Focus().
Lines(
Contains("origin").IsSelected(),
).
PressEnter()
t.Views().RemoteBranches().
IsFocused().
Lines(
Contains("branch-b").IsSelected(),
Contains("branch-a"),
Contains("branch-c"),
Contains("unrelated"),
Contains("master"),
)
},
})
+1
View File
@@ -88,6 +88,7 @@ var tests = []*components.IntegrationTest{
branch.SortLocalBranches,
branch.SortLocalBranchesInStackOrder,
branch.SortRemoteBranches,
branch.SortRemoteBranchesInStackOrder,
branch.SquashMerge,
branch.Suggestions,
branch.UnsetUpstream,