1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-08-06 22:33:07 +02:00

Allow rewording or dropping commits in filtering mode (#4756)

- **PR Description**

Rewording or dropping commits was disabled when filtering commits by
path or author. This used to be necessary a long time ago for technical
reasons, but these reasons went away with the merge of #2552, so enable
them now.

Technically we could enable a few more, but I chose not to because some
might be surprising or confusing in filtering mode. For example,
creating a fixup commit would work (shift-F), but the newly created
commit might not show up if it doesn't match the filter. Similarly,
pressing `f` to fixup a commit into its parent would work, but that
parent commit might not be visible, so users might expect to be fixing
up into the next visible commit.

Fixes #2554.
This commit is contained in:
Stefan Haller
2025-07-27 12:50:24 +02:00
committed by GitHub
6 changed files with 130 additions and 39 deletions

View File

@ -55,10 +55,10 @@ func NewLocalCommitsController(
func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
editCommitKey := opts.Config.Universal.Edit editCommitKey := opts.Config.Universal.Edit
outsideFilterModeBindings := []*types.Binding{ bindings := []*types.Binding{
{ {
Key: opts.GetKey(opts.Config.Commits.SquashDown), Key: opts.GetKey(opts.Config.Commits.SquashDown),
Handler: self.withItemsRange(self.squashDown), Handler: opts.Guards.OutsideFilterMode(self.withItemsRange(self.squashDown)),
GetDisabledReason: self.require( GetDisabledReason: self.require(
self.itemRangeSelected( self.itemRangeSelected(
self.midRebaseCommandEnabled, self.midRebaseCommandEnabled,
@ -71,7 +71,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup), Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup),
Handler: self.withItemsRange(self.fixup), Handler: opts.Guards.OutsideFilterMode(self.withItemsRange(self.fixup)),
GetDisabledReason: self.require( GetDisabledReason: self.require(
self.itemRangeSelected( self.itemRangeSelected(
self.midRebaseCommandEnabled, self.midRebaseCommandEnabled,
@ -115,7 +115,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(editCommitKey), Key: opts.GetKey(editCommitKey),
Handler: self.withItemsRange(self.edit), Handler: opts.Guards.OutsideFilterMode(self.withItemsRange(self.edit)),
GetDisabledReason: self.require( GetDisabledReason: self.require(
self.itemRangeSelected(self.midRebaseCommandEnabled), self.itemRangeSelected(self.midRebaseCommandEnabled),
), ),
@ -129,7 +129,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
// we're calling it 'quick-start interactive rebase' to differentiate it from // we're calling it 'quick-start interactive rebase' to differentiate it from
// when you manually select the base commit. // when you manually select the base commit.
Key: opts.GetKey(opts.Config.Commits.StartInteractiveRebase), Key: opts.GetKey(opts.Config.Commits.StartInteractiveRebase),
Handler: self.quickStartInteractiveRebase, Handler: opts.Guards.OutsideFilterMode(self.quickStartInteractiveRebase),
GetDisabledReason: self.require(self.notMidRebase(self.c.Tr.AlreadyRebasing), self.canFindCommitForQuickStart), GetDisabledReason: self.require(self.notMidRebase(self.c.Tr.AlreadyRebasing), self.canFindCommitForQuickStart),
Description: self.c.Tr.QuickStartInteractiveRebase, Description: self.c.Tr.QuickStartInteractiveRebase,
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.QuickStartInteractiveRebaseTooltip, map[string]string{ Tooltip: utils.ResolvePlaceholderString(self.c.Tr.QuickStartInteractiveRebaseTooltip, map[string]string{
@ -138,7 +138,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.PickCommit), Key: opts.GetKey(opts.Config.Commits.PickCommit),
Handler: self.withItems(self.pick), Handler: opts.Guards.OutsideFilterMode(self.withItems(self.pick)),
GetDisabledReason: self.require( GetDisabledReason: self.require(
self.itemRangeSelected(self.pickEnabled), self.itemRangeSelected(self.pickEnabled),
), ),
@ -147,7 +147,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit), Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit),
Handler: self.withItem(self.createFixupCommit), Handler: opts.Guards.OutsideFilterMode(self.withItem(self.createFixupCommit)),
GetDisabledReason: self.require(self.singleItemSelected()), GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.CreateFixupCommit, Description: self.c.Tr.CreateFixupCommit,
Tooltip: utils.ResolvePlaceholderString( Tooltip: utils.ResolvePlaceholderString(
@ -159,7 +159,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits), Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
Handler: self.squashFixupCommits, Handler: opts.Guards.OutsideFilterMode(self.squashFixupCommits),
GetDisabledReason: self.require( GetDisabledReason: self.require(
self.notMidRebase(self.c.Tr.AlreadyRebasing), self.notMidRebase(self.c.Tr.AlreadyRebasing),
), ),
@ -169,7 +169,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.MoveDownCommit), Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
Handler: self.withItemsRange(self.moveDown), Handler: opts.Guards.OutsideFilterMode(self.withItemsRange(self.moveDown)),
GetDisabledReason: self.require(self.itemRangeSelected( GetDisabledReason: self.require(self.itemRangeSelected(
self.midRebaseMoveCommandEnabled, self.midRebaseMoveCommandEnabled,
self.canMoveDown, self.canMoveDown,
@ -178,7 +178,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.MoveUpCommit), Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
Handler: self.withItemsRange(self.moveUp), Handler: opts.Guards.OutsideFilterMode(self.withItemsRange(self.moveUp)),
GetDisabledReason: self.require(self.itemRangeSelected( GetDisabledReason: self.require(self.itemRangeSelected(
self.midRebaseMoveCommandEnabled, self.midRebaseMoveCommandEnabled,
self.canMoveUp, self.canMoveUp,
@ -187,25 +187,18 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.PasteCommits), Key: opts.GetKey(opts.Config.Commits.PasteCommits),
Handler: self.paste, Handler: opts.Guards.OutsideFilterMode(self.paste),
GetDisabledReason: self.require(self.canPaste), GetDisabledReason: self.require(self.canPaste),
Description: self.c.Tr.PasteCommits, Description: self.c.Tr.PasteCommits,
DisplayStyle: &style.FgCyan, DisplayStyle: &style.FgCyan,
}, },
{ {
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase), Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
Handler: self.withItem(self.markAsBaseCommit), Handler: opts.Guards.OutsideFilterMode(self.withItem(self.markAsBaseCommit)),
GetDisabledReason: self.require(self.singleItemSelected()), GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.MarkAsBaseCommit, Description: self.c.Tr.MarkAsBaseCommit,
Tooltip: self.c.Tr.MarkAsBaseCommitTooltip, Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
}, },
}
for _, binding := range outsideFilterModeBindings {
binding.Handler = opts.Guards.OutsideFilterMode(binding.Handler)
}
bindings := append(outsideFilterModeBindings, []*types.Binding{
// overriding this navigation keybinding because we might need to load // overriding this navigation keybinding because we might need to load
// more commits on demand // more commits on demand
{ {
@ -251,7 +244,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
Tooltip: self.c.Tr.OpenLogMenuTooltip, Tooltip: self.c.Tr.OpenLogMenuTooltip,
OpensMenu: true, OpensMenu: true,
}, },
}...) }
return bindings return bindings
} }

View File

@ -0,0 +1,43 @@
package filter_by_path
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var DropCommitInFilteringMode = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Filter commits by file path, then drop a commit",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
},
SetupRepo: func(shell *Shell) {
commonSetup(shell)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
filterByFilterFile(t, keys)
t.Views().Commits().
IsFocused().
Lines(
Contains(`both files`).IsSelected(),
Contains(`only filterFile`),
).
Press(keys.Universal.Remove).
Tap(func() {
t.ExpectPopup().Confirmation().
Title(Equals("Drop commit")).
Content(Equals("Are you sure you want to drop the selected commit(s)?")).
Confirm()
}).
Lines(
Contains(`only filterFile`).IsSelected(),
).
Press(keys.Universal.Return).
Lines(
Contains(`none of the two`),
Contains(`only otherFile`),
Contains(`only filterFile`).IsSelected(),
)
},
})

View File

@ -15,26 +15,10 @@ var KeepSameCommitSelectedOnExit = NewIntegrationTest(NewIntegrationTestArgs{
commonSetup(shell) commonSetup(shell)
}, },
Run: func(t *TestDriver, keys config.KeybindingConfig) { Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits(). filterByFilterFile(t, keys)
Focus().
Lines(
Contains(`none of the two`).IsSelected(),
Contains(`both files`),
Contains(`only otherFile`),
Contains(`only filterFile`),
).Press(keys.Universal.FilteringMenu).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Filtering")).
Select(Contains("Enter path to filter by")).
Confirm()
t.ExpectPopup().Prompt(). t.Views().Commits().
Title(Equals("Enter path:")). IsFocused().
Type("filterF").
SuggestionLines(Equals("filterFile")).
ConfirmFirstSuggestion()
}).
Lines( Lines(
Contains(`both files`).IsSelected(), Contains(`both files`).IsSelected(),
Contains(`only filterFile`), Contains(`only filterFile`),

View File

@ -0,0 +1,46 @@
package filter_by_path
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var RewordCommitInFilteringMode = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Filter commits by file path, then reword a commit",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
},
SetupRepo: func(shell *Shell) {
commonSetup(shell)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
filterByFilterFile(t, keys)
t.Views().Commits().
IsFocused().
Lines(
Contains(`both files`).IsSelected(),
Contains(`only filterFile`),
).
SelectNextItem().
Press(keys.Commits.RenameCommit).
Tap(func() {
t.ExpectPopup().CommitMessagePanel().
Clear().
Type("new message").
Confirm()
}).
Lines(
Contains(`both files`),
Contains(`new message`).IsSelected(),
).
Press(keys.Universal.Return).
Lines(
Contains(`none of the two`),
Contains(`both files`),
Contains(`only otherFile`),
Contains(`new message`).IsSelected(),
)
},
})

View File

@ -1,6 +1,7 @@
package filter_by_path package filter_by_path
import ( import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components" . "github.com/jesseduffield/lazygit/pkg/integration/components"
) )
@ -17,6 +18,28 @@ func commonSetup(shell *Shell) {
shell.EmptyCommit("none of the two") shell.EmptyCommit("none of the two")
} }
func filterByFilterFile(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains(`none of the two`).IsSelected(),
Contains(`both files`),
Contains(`only otherFile`),
Contains(`only filterFile`),
).
Press(keys.Universal.FilteringMenu)
t.ExpectPopup().Menu().
Title(Equals("Filtering")).
Select(Contains("Enter path to filter by")).
Confirm()
t.ExpectPopup().Prompt().
Title(Equals("Enter path:")).
Type("filterF").
SuggestionLines(Equals("filterFile")).
ConfirmFirstSuggestion()
}
func postFilterTest(t *TestDriver) { func postFilterTest(t *TestDriver) {
t.Views().Information().Content(Contains("Filtering by 'filterFile'")) t.Views().Information().Content(Contains("Filtering by 'filterFile'"))

View File

@ -233,7 +233,9 @@ var tests = []*components.IntegrationTest{
filter_by_author.SelectAuthor, filter_by_author.SelectAuthor,
filter_by_author.TypeAuthor, filter_by_author.TypeAuthor,
filter_by_path.CliArg, filter_by_path.CliArg,
filter_by_path.DropCommitInFilteringMode,
filter_by_path.KeepSameCommitSelectedOnExit, filter_by_path.KeepSameCommitSelectedOnExit,
filter_by_path.RewordCommitInFilteringMode,
filter_by_path.SelectFile, filter_by_path.SelectFile,
filter_by_path.ShowDiffsForRenamedFile, filter_by_path.ShowDiffsForRenamedFile,
filter_by_path.TypeFile, filter_by_path.TypeFile,