From 703256e92d7eb12d49d92f58ffadda13b4a26c42 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 7 Jul 2025 15:37:05 +0200 Subject: [PATCH] Move LocalBranchSortOrder and RemoteBranchSortOrder to user config At the same time, we change the defaults for both of them to "date" (they were "recency" and "alphabetical", respectively, before). This is the reason we need to touch so many integration tests. For some of them I decided to adapt the test assertions to the changed sort order; for others, I added a SetupConfig step to set the order back to "recency" so that I don't have to change what the test does (e.g. how many SelectNextItem() calls are needed to get to a certain branch). --- docs/Config.md | 10 +++++++ pkg/commands/git_commands/branch_loader.go | 6 ++--- pkg/commands/git_commands/remote_loader.go | 2 +- pkg/config/app_config.go | 18 +++++-------- pkg/config/user_config.go | 10 +++++++ pkg/config/user_config_validation.go | 8 ++++++ pkg/config/user_config_validation_test.go | 26 +++++++++++++++++++ pkg/gui/controllers/branches_controller.go | 7 +++-- pkg/gui/controllers/helpers/refresh_helper.go | 4 +-- .../controllers/remote_branches_controller.go | 7 +++-- .../tests/branch/checkout_by_name.go | 2 +- pkg/integration/tests/branch/delete.go | 4 ++- .../tests/branch/delete_multiple.go | 3 ++- .../tests/branch/delete_while_filtering.go | 2 +- pkg/integration/tests/branch/rebase.go | 4 ++- .../tests/branch/rebase_abort_on_conflict.go | 4 ++- .../tests/branch/rebase_and_drop.go | 4 ++- .../tests/branch/rebase_cancel_on_conflict.go | 4 ++- .../rebase_conflicts_fix_build_errors.go | 4 ++- .../tests/branch/rebase_from_marked_base.go | 4 ++- .../tests/branch/reset_to_upstream.go | 4 ++- .../tests/branch/sort_local_branches.go | 16 ++++++------ .../tests/branch/sort_remote_branches.go | 16 ++++++------ .../tests/cherry_pick/cherry_pick.go | 4 ++- .../cherry_pick/cherry_pick_conflicts.go | 4 ++- .../cherry_pick/cherry_pick_during_rebase.go | 1 + .../tests/cherry_pick/cherry_pick_merge.go | 4 ++- .../tests/cherry_pick/cherry_pick_range.go | 4 ++- pkg/integration/tests/commit/checkout.go | 4 +-- .../custom_commands/check_for_conflicts.go | 2 ++ .../custom_commands/suggestions_command.go | 4 +-- .../custom_commands/suggestions_preset.go | 4 +-- .../filter_updates_when_model_changes.go | 4 +-- .../tests/filter_and_search/nested_filter.go | 4 +-- schema/config.json | 19 ++++++++++++++ 35 files changed, 161 insertions(+), 66 deletions(-) diff --git a/docs/Config.md b/docs/Config.md index 25f9fcbd3..6be09a383 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -399,6 +399,16 @@ git: # displays the whole git graph by default in the commits view (equivalent to passing the `--all` argument to `git log`) showWholeGraph: false + # How branches are sorted in the local branches view. + # One of: 'date' (default) | 'recency' | 'alphabetical' + # Can be changed from within Lazygit with the Sort Order menu (`s`) in the branches panel. + localBranchSortOrder: date + + # How branches are sorted in the remote branches view. + # One of: 'date' (default) | 'alphabetical' + # Can be changed from within Lazygit with the Sort Order menu (`s`) in the remote branches panel. + remoteBranchSortOrder: date + # When copying commit hashes to the clipboard, truncate them to this # length. Set to 40 to disable truncation. truncateCopiedCommitHashesTo: 12 diff --git a/pkg/commands/git_commands/branch_loader.go b/pkg/commands/git_commands/branch_loader.go index 73127ae63..a4e41b756 100644 --- a/pkg/commands/git_commands/branch_loader.go +++ b/pkg/commands/git_commands/branch_loader.go @@ -74,7 +74,7 @@ func (self *BranchLoader) Load(reflogCommits []*models.Commit, ) ([]*models.Branch, error) { branches := self.obtainBranches() - if self.AppState.LocalBranchSortOrder == "recency" { + if self.UserConfig().Git.LocalBranchSortOrder == "recency" { reflogBranches := self.obtainReflogBranches(reflogCommits) // loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches branchesWithRecency := make([]*models.Branch, 0) @@ -254,7 +254,7 @@ func (self *BranchLoader) obtainBranches() []*models.Branch { return nil, false } - storeCommitDateAsRecency := self.AppState.LocalBranchSortOrder != "recency" + storeCommitDateAsRecency := self.UserConfig().Git.LocalBranchSortOrder != "recency" return obtainBranch(split, storeCommitDateAsRecency), true }) } @@ -268,7 +268,7 @@ func (self *BranchLoader) getRawBranches() (string, error) { ) var sortOrder string - switch strings.ToLower(self.AppState.LocalBranchSortOrder) { + switch strings.ToLower(self.UserConfig().Git.LocalBranchSortOrder) { case "recency", "date": sortOrder = "-committerdate" case "alphabetical": diff --git a/pkg/commands/git_commands/remote_loader.go b/pkg/commands/git_commands/remote_loader.go index 1b2e33682..2e632def4 100644 --- a/pkg/commands/git_commands/remote_loader.go +++ b/pkg/commands/git_commands/remote_loader.go @@ -85,7 +85,7 @@ func (self *RemoteLoader) getRemoteBranchesByRemoteName() (map[string][]*models. remoteBranchesByRemoteName := make(map[string][]*models.RemoteBranch) var sortOrder string - switch strings.ToLower(self.AppState.RemoteBranchSortOrder) { + switch strings.ToLower(self.UserConfig().Git.RemoteBranchSortOrder) { case "alphabetical": sortOrder = "refname" case "date": diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index aaaf7adb3..184d8e07a 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -676,9 +676,7 @@ type AppState struct { // For backwards compatibility we keep the old name in yaml files. ShellCommandsHistory []string `yaml:"customcommandshistory"` - HideCommandLog bool - LocalBranchSortOrder string - RemoteBranchSortOrder string + HideCommandLog bool // One of: 'date-order' | 'author-date-order' | 'topo-order' | 'default' // 'topo-order' makes it easier to read the git log graph, but commits may not @@ -692,14 +690,12 @@ type AppState struct { func getDefaultAppState() *AppState { return &AppState{ - LastUpdateCheck: 0, - RecentRepos: []string{}, - StartupPopupVersion: 0, - LastVersion: "", - LocalBranchSortOrder: "recency", - RemoteBranchSortOrder: "alphabetical", - GitLogOrder: "", // should be "topo-order" eventually - GitLogShowGraph: "", // should be "always" eventually + LastUpdateCheck: 0, + RecentRepos: []string{}, + StartupPopupVersion: 0, + LastVersion: "", + GitLogOrder: "", // should be "topo-order" eventually + GitLogShowGraph: "", // should be "always" eventually } } diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index 39c67bc4b..5d619231e 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -285,6 +285,14 @@ type GitConfig struct { ParseEmoji bool `yaml:"parseEmoji"` // Config for showing the log in the commits view Log LogConfig `yaml:"log"` + // How branches are sorted in the local branches view. + // One of: 'date' (default) | 'recency' | 'alphabetical' + // Can be changed from within Lazygit with the Sort Order menu (`s`) in the branches panel. + LocalBranchSortOrder string `yaml:"localBranchSortOrder" jsonschema:"enum=date,enum=recency,enum=alphabetical"` + // How branches are sorted in the remote branches view. + // One of: 'date' (default) | 'alphabetical' + // Can be changed from within Lazygit with the Sort Order menu (`s`) in the remote branches panel. + RemoteBranchSortOrder string `yaml:"remoteBranchSortOrder" jsonschema:"enum=date,enum=alphabetical"` // When copying commit hashes to the clipboard, truncate them to this // length. Set to 40 to disable truncation. TruncateCopiedCommitHashesTo int `yaml:"truncateCopiedCommitHashesTo"` @@ -805,6 +813,8 @@ func GetDefaultConfig() *UserConfig { ShowGraph: "always", ShowWholeGraph: false, }, + LocalBranchSortOrder: "date", + RemoteBranchSortOrder: "date", SkipHookPrefix: "WIP", MainBranches: []string{"master", "main"}, AutoFetch: true, diff --git a/pkg/config/user_config_validation.go b/pkg/config/user_config_validation.go index f46dfca9a..5d43c4a28 100644 --- a/pkg/config/user_config_validation.go +++ b/pkg/config/user_config_validation.go @@ -23,6 +23,14 @@ func (config *UserConfig) Validate() error { []string{"none", "onlyMainBranches", "allBranches"}); err != nil { return err } + if err := validateEnum("git.localBranchSortOrder", config.Git.LocalBranchSortOrder, + []string{"date", "recency", "alphabetical"}); err != nil { + return err + } + if err := validateEnum("git.remoteBranchSortOrder", config.Git.RemoteBranchSortOrder, + []string{"date", "alphabetical"}); err != nil { + return err + } if err := validateKeybindings(config.Keybinding); err != nil { return err } diff --git a/pkg/config/user_config_validation_test.go b/pkg/config/user_config_validation_test.go index f98431713..67ff16991 100644 --- a/pkg/config/user_config_validation_test.go +++ b/pkg/config/user_config_validation_test.go @@ -56,6 +56,32 @@ func TestUserConfigValidate_enums(t *testing.T) { {value: "invalid_value", valid: false}, }, }, + { + name: "Git.LocalBranchSortOrder", + setup: func(config *UserConfig, value string) { + config.Git.LocalBranchSortOrder = value + }, + testCases: []testCase{ + {value: "date", valid: true}, + {value: "recency", valid: true}, + {value: "alphabetical", valid: true}, + {value: "", valid: false}, + {value: "invalid_value", valid: false}, + }, + }, + { + name: "Git.RemoteBranchSortOrder", + setup: func(config *UserConfig, value string) { + config.Git.RemoteBranchSortOrder = value + }, + testCases: []testCase{ + {value: "date", valid: true}, + {value: "recency", valid: false}, + {value: "alphabetical", valid: true}, + {value: "", valid: false}, + {value: "invalid_value", valid: false}, + }, + }, { name: "Keybindings", setup: func(config *UserConfig, value string) { diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index 454216df7..b49a5f6f3 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -674,16 +674,15 @@ func (self *BranchesController) createTag(branch *models.Branch) error { func (self *BranchesController) createSortMenu() error { return self.c.Helpers().Refs.CreateSortOrderMenu([]string{"recency", "alphabetical", "date"}, func(sortOrder string) error { - if self.c.GetAppState().LocalBranchSortOrder != sortOrder { - self.c.GetAppState().LocalBranchSortOrder = sortOrder - self.c.SaveAppStateAndLogError() + if self.c.UserConfig().Git.LocalBranchSortOrder != sortOrder { + self.c.UserConfig().Git.LocalBranchSortOrder = sortOrder self.c.Contexts().Branches.SetSelection(0) self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) return nil } return nil }, - self.c.GetAppState().LocalBranchSortOrder) + self.c.UserConfig().Git.LocalBranchSortOrder) } func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error { diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index e377cfdf9..2682d8296 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -125,7 +125,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) { refresh("commits and commit files", self.refreshCommitsAndCommitFiles) includeWorktreesWithBranches = scopeSet.Includes(types.WORKTREES) - if self.c.AppState.LocalBranchSortOrder == "recency" { + if self.c.UserConfig().Git.LocalBranchSortOrder == "recency" { refresh("reflog and branches", func() { self.refreshReflogAndBranches(includeWorktreesWithBranches, options.KeepBranchSelectionIndex) }) } else { refresh("branches", func() { self.refreshBranches(includeWorktreesWithBranches, options.KeepBranchSelectionIndex, true) }) @@ -446,7 +446,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele defer self.c.Mutexes().RefreshingBranchesMutex.Unlock() reflogCommits := self.c.Model().FilteredReflogCommits - if self.c.Modes().Filtering.Active() && self.c.AppState.LocalBranchSortOrder == "recency" { + if self.c.Modes().Filtering.Active() && self.c.UserConfig().Git.LocalBranchSortOrder == "recency" { // in filter mode we filter our reflog commits to just those containing the path // however we need all the reflog entries to populate the recencies of our branches // which allows us to order them correctly. So if we're filtering we'll just diff --git a/pkg/gui/controllers/remote_branches_controller.go b/pkg/gui/controllers/remote_branches_controller.go index 629bbbaa3..3bb99380a 100644 --- a/pkg/gui/controllers/remote_branches_controller.go +++ b/pkg/gui/controllers/remote_branches_controller.go @@ -146,15 +146,14 @@ func (self *RemoteBranchesController) rebase(selectedBranch *models.RemoteBranch func (self *RemoteBranchesController) createSortMenu() error { return self.c.Helpers().Refs.CreateSortOrderMenu([]string{"alphabetical", "date"}, func(sortOrder string) error { - if self.c.GetAppState().RemoteBranchSortOrder != sortOrder { - self.c.GetAppState().RemoteBranchSortOrder = sortOrder - self.c.SaveAppStateAndLogError() + if self.c.UserConfig().Git.RemoteBranchSortOrder != sortOrder { + self.c.UserConfig().Git.RemoteBranchSortOrder = sortOrder self.c.Contexts().RemoteBranches.SetSelection(0) self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.REMOTES}}) } return nil }, - self.c.GetAppState().RemoteBranchSortOrder) + self.c.UserConfig().Git.RemoteBranchSortOrder) } func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error { diff --git a/pkg/integration/tests/branch/checkout_by_name.go b/pkg/integration/tests/branch/checkout_by_name.go index 127ea10dd..af06162a7 100644 --- a/pkg/integration/tests/branch/checkout_by_name.go +++ b/pkg/integration/tests/branch/checkout_by_name.go @@ -33,8 +33,8 @@ var CheckoutByName = NewIntegrationTest(NewIntegrationTestArgs{ }). Lines( MatchesRegexp(`\*.*new-branch`).IsSelected(), - Contains("master"), Contains("@"), + Contains("master"), ) }, }) diff --git a/pkg/integration/tests/branch/delete.go b/pkg/integration/tests/branch/delete.go index ae29a679c..5da844622 100644 --- a/pkg/integration/tests/branch/delete.go +++ b/pkg/integration/tests/branch/delete.go @@ -9,7 +9,9 @@ var Delete = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Try all combination of local and remote branch deletions", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. CloneIntoRemote("origin"). diff --git a/pkg/integration/tests/branch/delete_multiple.go b/pkg/integration/tests/branch/delete_multiple.go index a03a822f6..0bba33b9d 100644 --- a/pkg/integration/tests/branch/delete_multiple.go +++ b/pkg/integration/tests/branch/delete_multiple.go @@ -10,7 +10,8 @@ var DeleteMultiple = NewIntegrationTest(NewIntegrationTestArgs{ ExtraCmdArgs: []string{}, Skip: false, SetupConfig: func(config *config.AppConfig) { - config.GetAppState().LocalBranchSortOrder = "alphabetic" + config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical" + config.GetUserConfig().Git.RemoteBranchSortOrder = "alphabetical" }, SetupRepo: func(shell *Shell) { shell. diff --git a/pkg/integration/tests/branch/delete_while_filtering.go b/pkg/integration/tests/branch/delete_while_filtering.go index d967ff40f..2b2039d67 100644 --- a/pkg/integration/tests/branch/delete_while_filtering.go +++ b/pkg/integration/tests/branch/delete_while_filtering.go @@ -12,7 +12,7 @@ var DeleteWhileFiltering = NewIntegrationTest(NewIntegrationTestArgs{ ExtraCmdArgs: []string{}, Skip: false, SetupConfig: func(config *config.AppConfig) { - config.GetAppState().LocalBranchSortOrder = "alphabetic" + config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical" }, SetupRepo: func(shell *Shell) { shell.EmptyCommit("one") diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index 6bc2083c4..3c86ddffc 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -10,7 +10,9 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch, deal with the conflicts.", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) }, diff --git a/pkg/integration/tests/branch/rebase_abort_on_conflict.go b/pkg/integration/tests/branch/rebase_abort_on_conflict.go index 47f59d3d1..79ceba510 100644 --- a/pkg/integration/tests/branch/rebase_abort_on_conflict.go +++ b/pkg/integration/tests/branch/rebase_abort_on_conflict.go @@ -10,7 +10,9 @@ var RebaseAbortOnConflict = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch, abort when there are conflicts.", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) }, diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 896d27068..ff17d6417 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -10,7 +10,9 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch, deal with the conflicts. Also mark a commit to be dropped before continuing.", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) // adding a couple additional commits so that we can drop one diff --git a/pkg/integration/tests/branch/rebase_cancel_on_conflict.go b/pkg/integration/tests/branch/rebase_cancel_on_conflict.go index 03923c81d..be69f9753 100644 --- a/pkg/integration/tests/branch/rebase_cancel_on_conflict.go +++ b/pkg/integration/tests/branch/rebase_cancel_on_conflict.go @@ -10,7 +10,9 @@ var RebaseCancelOnConflict = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch, cancel when there are conflicts.", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) }, diff --git a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go index 2ae75dafb..3690f8f2e 100644 --- a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go +++ b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go @@ -10,7 +10,9 @@ var RebaseConflictsFixBuildErrors = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch, deal with the conflicts. While continue prompt is showing, fix build errors; get another prompt when continuing.", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) }, diff --git a/pkg/integration/tests/branch/rebase_from_marked_base.go b/pkg/integration/tests/branch/rebase_from_marked_base.go index c26dce9a3..3dd60184b 100644 --- a/pkg/integration/tests/branch/rebase_from_marked_base.go +++ b/pkg/integration/tests/branch/rebase_from_marked_base.go @@ -9,7 +9,9 @@ var RebaseFromMarkedBase = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Rebase onto another branch from a marked base commit", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. NewBranch("base-branch"). diff --git a/pkg/integration/tests/branch/reset_to_upstream.go b/pkg/integration/tests/branch/reset_to_upstream.go index e5503f127..9a5ea498e 100644 --- a/pkg/integration/tests/branch/reset_to_upstream.go +++ b/pkg/integration/tests/branch/reset_to_upstream.go @@ -9,7 +9,9 @@ var ResetToUpstream = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Hard reset the current branch to the selected branch upstream", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. CloneIntoRemote("origin"). diff --git a/pkg/integration/tests/branch/sort_local_branches.go b/pkg/integration/tests/branch/sort_local_branches.go index ceff654be..9c29e17bf 100644 --- a/pkg/integration/tests/branch/sort_local_branches.go +++ b/pkg/integration/tests/branch/sort_local_branches.go @@ -22,13 +22,13 @@ var SortLocalBranches = NewIntegrationTest(NewIntegrationTestArgs{ Checkout("master") }, Run: func(t *TestDriver, keys config.KeybindingConfig) { - // sorted by recency by default + // sorted by date by default t.Views().Branches(). Focus(). Lines( Contains("master").IsSelected(), - Contains("third"), Contains("second"), + Contains("third"), Contains("first"), ). SelectNextItem() // to test that the selection jumps back to the top when sorting @@ -38,20 +38,20 @@ var SortLocalBranches = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Menu().Title(Equals("Sort order")). Lines( - Contains("r (•) Recency").IsSelected(), + Contains("r ( ) Recency").IsSelected(), Contains("a ( ) Alphabetical"), - Contains("d ( ) Date"), + Contains("d (•) Date"), Contains(" Cancel"), ). - Select(Contains("-committerdate")). + Select(Contains("Recency")). Confirm() t.Views().Branches(). IsFocused(). Lines( Contains("master").IsSelected(), - Contains("second"), Contains("third"), + Contains("second"), Contains("first"), ) @@ -60,9 +60,9 @@ var SortLocalBranches = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Menu().Title(Equals("Sort order")). Lines( - Contains("r ( ) Recency").IsSelected(), + Contains("r (•) Recency").IsSelected(), Contains("a ( ) Alphabetical"), - Contains("d (•) Date"), + Contains("d ( ) Date"), Contains(" Cancel"), ). Select(Contains("refname")). diff --git a/pkg/integration/tests/branch/sort_remote_branches.go b/pkg/integration/tests/branch/sort_remote_branches.go index 2cbbdb31d..90c787f41 100644 --- a/pkg/integration/tests/branch/sort_remote_branches.go +++ b/pkg/integration/tests/branch/sort_remote_branches.go @@ -27,13 +27,13 @@ var SortRemoteBranches = NewIntegrationTest(NewIntegrationTestArgs{ ). PressEnter() - // sorted alphabetically by default + // sorted by date by default t.Views().RemoteBranches(). IsFocused(). Lines( - Contains("first").IsSelected(), - Contains("second"), + Contains("second").IsSelected(), Contains("third"), + Contains("first"), ). SelectNextItem() // to test that the selection jumps back to the first when sorting @@ -42,19 +42,19 @@ var SortRemoteBranches = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Menu().Title(Equals("Sort order")). Lines( - Contains("a (•) Alphabetical").IsSelected(), - Contains("d ( ) Date"), + Contains("a ( ) Alphabetical").IsSelected(), + Contains("d (•) Date"), Contains(" Cancel"), ). - Select(Contains("-committerdate")). + Select(Contains("Alphabetical")). Confirm() t.Views().RemoteBranches(). IsFocused(). Lines( - Contains("second").IsSelected(), + Contains("first").IsSelected(), + Contains("second"), Contains("third"), - Contains("first"), ) }, }) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick.go b/pkg/integration/tests/cherry_pick/cherry_pick.go index ccdb606f8..a278a5639 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick.go @@ -9,7 +9,9 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Cherry pick commits from the subcommits view, without conflicts", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. EmptyCommit("base"). diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index f3d5eca82..b135bfd7f 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -10,7 +10,9 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Cherry pick commits from the subcommits view, with conflicts", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shared.MergeConflictsSetup(shell) }, diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go b/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go index af4e8b9d2..45811fad7 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go @@ -11,6 +11,7 @@ var CherryPickDuringRebase = NewIntegrationTest(NewIntegrationTestArgs{ Skip: false, SetupConfig: func(config *config.AppConfig) { config.GetAppState().GitLogShowGraph = "never" + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" }, SetupRepo: func(shell *Shell) { shell. diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_merge.go b/pkg/integration/tests/cherry_pick/cherry_pick_merge.go index 7c68ce8eb..6c883cfa4 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_merge.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_merge.go @@ -9,7 +9,9 @@ var CherryPickMerge = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Cherry pick a merge commit", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. EmptyCommit("base"). diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_range.go b/pkg/integration/tests/cherry_pick/cherry_pick_range.go index 329ef1e9c..dfebeae2e 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_range.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_range.go @@ -9,7 +9,9 @@ var CherryPickRange = NewIntegrationTest(NewIntegrationTestArgs{ Description: "Cherry pick range of commits from the subcommits view, without conflicts", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.LocalBranchSortOrder = "recency" + }, SetupRepo: func(shell *Shell) { shell. EmptyCommit("base"). diff --git a/pkg/integration/tests/commit/checkout.go b/pkg/integration/tests/commit/checkout.go index 7815e89de..7f2f4e0d9 100644 --- a/pkg/integration/tests/commit/checkout.go +++ b/pkg/integration/tests/commit/checkout.go @@ -42,8 +42,8 @@ var Checkout = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() t.Views().Branches().Lines( Contains("* (HEAD detached at"), - Contains("branch2"), Contains("branch1"), + Contains("branch2"), Contains("master"), ) @@ -63,8 +63,8 @@ var Checkout = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() t.Views().Branches().Lines( Contains("master"), - Contains("branch2"), Contains("branch1"), + Contains("branch2"), ) }, }) diff --git a/pkg/integration/tests/custom_commands/check_for_conflicts.go b/pkg/integration/tests/custom_commands/check_for_conflicts.go index 25f1d2097..d3376b456 100644 --- a/pkg/integration/tests/custom_commands/check_for_conflicts.go +++ b/pkg/integration/tests/custom_commands/check_for_conflicts.go @@ -24,6 +24,8 @@ var CheckForConflicts = NewIntegrationTest(NewIntegrationTestArgs{ }, }, } + + cfg.GetUserConfig().Git.LocalBranchSortOrder = "recency" }, Run: func(t *TestDriver, keys config.KeybindingConfig) { t.Views().Branches(). diff --git a/pkg/integration/tests/custom_commands/suggestions_command.go b/pkg/integration/tests/custom_commands/suggestions_command.go index 4b6aa0f4e..0710a7698 100644 --- a/pkg/integration/tests/custom_commands/suggestions_command.go +++ b/pkg/integration/tests/custom_commands/suggestions_command.go @@ -43,9 +43,9 @@ var SuggestionsCommand = NewIntegrationTest(NewIntegrationTestArgs{ Focus(). Lines( Contains("branch-four").IsSelected(), + Contains("branch-one"), Contains("branch-three"), Contains("branch-two"), - Contains("branch-one"), ). Press("a") @@ -59,8 +59,8 @@ var SuggestionsCommand = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Contains("branch-three"), Contains("branch-four").IsSelected(), - Contains("branch-two"), Contains("branch-one"), + Contains("branch-two"), ) }, }) diff --git a/pkg/integration/tests/custom_commands/suggestions_preset.go b/pkg/integration/tests/custom_commands/suggestions_preset.go index aa599946f..41a16e271 100644 --- a/pkg/integration/tests/custom_commands/suggestions_preset.go +++ b/pkg/integration/tests/custom_commands/suggestions_preset.go @@ -43,9 +43,9 @@ var SuggestionsPreset = NewIntegrationTest(NewIntegrationTestArgs{ Focus(). Lines( Contains("branch-four").IsSelected(), + Contains("branch-one"), Contains("branch-three"), Contains("branch-two"), - Contains("branch-one"), ). Press("a") @@ -59,8 +59,8 @@ var SuggestionsPreset = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Contains("branch-three"), Contains("branch-four").IsSelected(), - Contains("branch-two"), Contains("branch-one"), + Contains("branch-two"), ) }, }) diff --git a/pkg/integration/tests/filter_and_search/filter_updates_when_model_changes.go b/pkg/integration/tests/filter_and_search/filter_updates_when_model_changes.go index 1907a7159..5def8bfe5 100644 --- a/pkg/integration/tests/filter_and_search/filter_updates_when_model_changes.go +++ b/pkg/integration/tests/filter_and_search/filter_updates_when_model_changes.go @@ -21,9 +21,9 @@ var FilterUpdatesWhenModelChanges = NewIntegrationTest(NewIntegrationTestArgs{ Focus(). Lines( Contains("checked-out-branch").IsSelected(), - Contains("other"), Contains("branch-to-delete"), Contains("master"), + Contains("other"), ). FilterOrSearch("branch"). Lines( @@ -65,9 +65,9 @@ var FilterUpdatesWhenModelChanges = NewIntegrationTest(NewIntegrationTestArgs{ PressEscape(). Lines( Contains("checked-out-branch").IsSelected(), - Contains("other"), Contains("master"), Contains("new-branch"), + Contains("other"), ) }, }) diff --git a/pkg/integration/tests/filter_and_search/nested_filter.go b/pkg/integration/tests/filter_and_search/nested_filter.go index db20dd5b5..b94f8990f 100644 --- a/pkg/integration/tests/filter_and_search/nested_filter.go +++ b/pkg/integration/tests/filter_and_search/nested_filter.go @@ -35,8 +35,8 @@ var NestedFilter = NewIntegrationTest(NewIntegrationTestArgs{ Focus(). Lines( Contains(`branch-bronze`).IsSelected(), - Contains(`branch-silver`), Contains(`branch-gold`), + Contains(`branch-silver`), ). FilterOrSearch("sil"). Lines( @@ -148,8 +148,8 @@ var NestedFilter = NewIntegrationTest(NewIntegrationTestArgs{ }). Lines( Contains(`branch-bronze`), - Contains(`branch-silver`).IsSelected(), Contains(`branch-gold`), + Contains(`branch-silver`).IsSelected(), ) }, }) diff --git a/schema/config.json b/schema/config.json index 9da832b4e..a98076ecb 100644 --- a/schema/config.json +++ b/schema/config.json @@ -416,6 +416,25 @@ "$ref": "#/$defs/LogConfig", "description": "Config for showing the log in the commits view" }, + "localBranchSortOrder": { + "type": "string", + "enum": [ + "date", + "recency", + "alphabetical" + ], + "description": "How branches are sorted in the local branches view.\nOne of: 'date' (default) | 'recency' | 'alphabetical'\nCan be changed from within Lazygit with the Sort Order menu (`s`) in the branches panel.", + "default": "date" + }, + "remoteBranchSortOrder": { + "type": "string", + "enum": [ + "date", + "alphabetical" + ], + "description": "How branches are sorted in the remote branches view.\nOne of: 'date' (default) | 'alphabetical'\nCan be changed from within Lazygit with the Sort Order menu (`s`) in the remote branches panel.", + "default": "date" + }, "truncateCopiedCommitHashesTo": { "type": "integer", "description": "When copying commit hashes to the clipboard, truncate them to this\nlength. Set to 40 to disable truncation.",