diff --git a/pkg/gui/controllers/helpers/fixup_helper.go b/pkg/gui/controllers/helpers/fixup_helper.go index 2e3b19e7780..2232470720e 100644 --- a/pkg/gui/controllers/helpers/fixup_helper.go +++ b/pkg/gui/controllers/helpers/fixup_helper.go @@ -104,12 +104,33 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error { } if len(hashGroups[NOT_MERGED]) == 0 { - // If all the commits are merged, show the "already on main branch" - // error. It isn't worth doing a detailed report of which commits we - // found. - return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch) - } + // The commit is already merged, but we attempt to show it anyway. + if len(hashGroups[MERGED]) > 1 { + // We found multiple merged commits. List them in error message + subjects := self.getHashesAndSubjects(commits, hashGroups[NOT_MERGED]) + message := self.c.Tr.MultipleBaseCommitsFoundMerged + return fmt.Errorf("%s\n\n%s", message, subjects) + } else if len(hashGroups[MERGED]) == 0 { + // This can not happen, as the commit has to be either in + // CANNOT_TELL, NOT_MERGED or MERGED state and we already established, + // that it is not in CANNOT_TELL or NOT_MERGED + return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView) + } + // At this point we know that the MERGED bucket has exactly one commit, + // and that's the one we want to select. + _, index, found := self.findCommit(commits, hashGroups[MERGED][0]) + if !found { + // However the commit is not in view, so we cannot select it. + return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView) + } + // We found the commit, so we show it with a warning message, that it is already merged. + return self.c.ConfirmIf(true, types.ConfirmOpts{ + Title: self.c.Tr.FindBaseCommitForFixup, + Prompt: self.c.Tr.BaseCommitIsAlreadyOnMainBranch, + HandleConfirm: self.getHandlerToStageAndSelectIndex(hasStagedChanges, index), + }) + } if len(hashGroups[NOT_MERGED]) > 1 { // If there are multiple commits that could be the base commit, list // them in the error message. But only the candidates from the current @@ -126,22 +147,26 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error { _, index, _ := self.findCommit(commits, hashGroups[NOT_MERGED][0]) return self.c.ConfirmIf(warnAboutAddedLines, types.ConfirmOpts{ - Title: self.c.Tr.FindBaseCommitForFixup, - Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning, - HandleConfirm: func() error { - if !hasStagedChanges { - if err := self.c.Git().WorkingTree.StageAll(true); err != nil { - return err - } - self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}}) + Title: self.c.Tr.FindBaseCommitForFixup, + Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning, + HandleConfirm: self.getHandlerToStageAndSelectIndex(hasStagedChanges, index), + }) +} + +func (self *FixupHelper) getHandlerToStageAndSelectIndex(hasStagedChanges bool, index int) func() error { + return func() error { + if !hasStagedChanges { + if err := self.c.Git().WorkingTree.StageAll(true); err != nil { + return err } + self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}}) + } - self.c.Contexts().LocalCommits.SetSelection(index) - self.c.Contexts().LocalCommits.FocusLine(true) - self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{}) - return nil - }, - }) + self.c.Contexts().LocalCommits.SetSelection(index) + self.c.Contexts().LocalCommits.FocusLine(true) + self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{}) + return nil + } } func (self *FixupHelper) getHashesAndSubjects(commits []*models.Commit, hashes []string) string { diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 970afd498be..5dda1308eb2 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -45,6 +45,7 @@ type TranslationSet struct { NoBaseCommitsFound string MultipleBaseCommitsFoundStaged string MultipleBaseCommitsFoundUnstaged string + MultipleBaseCommitsFoundMerged string BaseCommitIsAlreadyOnMainBranch string BaseCommitIsNotInCurrentView string HunksWithOnlyAddedLinesWarning string @@ -1140,6 +1141,7 @@ func EnglishTranslationSet() *TranslationSet { NoBaseCommitsFound: "No base commits found", MultipleBaseCommitsFoundStaged: "Multiple base commits found. (Try staging fewer changes at once)", MultipleBaseCommitsFoundUnstaged: "Multiple base commits found. (Try staging some of the changes)", + MultipleBaseCommitsFoundMerged: "Multiple base commits found, that are already on the main branch. (Try staging some of the changes)", BaseCommitIsAlreadyOnMainBranch: "The base commit for this change is already on the main branch", BaseCommitIsNotInCurrentView: "Base commit is not in current view", HunksWithOnlyAddedLinesWarning: "There are ranges of only added lines in the diff; be careful to check that these belong in the found base commit.\n\nProceed?", diff --git a/pkg/integration/tests/commit/find_base_commit_for_fixup_in_main_branch.go b/pkg/integration/tests/commit/find_base_commit_for_fixup_in_main_branch.go new file mode 100644 index 00000000000..e365d5a203d --- /dev/null +++ b/pkg/integration/tests/commit/find_base_commit_for_fixup_in_main_branch.go @@ -0,0 +1,51 @@ +package commit + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var FindBaseCommitForFixupInMainBranch = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Finds the base commit to create a fixup for when the commit is already merged into master", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell. + EmptyCommit("1st commit"). + CreateFileAndAdd("file1", "file1 content\n"). + Commit("2nd commit"). + NewBranch("mybranch"). + CreateFileAndAdd("file2", "file2 content\n"). + Commit("3rd commit"). + EmptyCommit("4th commit"). + UpdateFile("file1", "file1 changed content") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Lines( + Contains("4th commit").IsSelected(), + Contains("3rd commit"), + Contains("2nd commit"), + Contains("1st commit"), + ) + + t.Views().Files(). + Focus(). + Press(keys.Files.FindBaseCommitForFixup) + t.ExpectPopup(). + Confirmation(). + Title(Equals("Find base commit for fixup")). + Content(Contains("already on the main branch")). + Confirm() + + t.Views().Commits(). + IsFocused(). + Lines( + Contains("4th commit"), + Contains("3rd commit"), + Contains("2nd commit").IsSelected(), + Contains("1st commit"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 26d6d30305f..00a6d11d0be 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -131,6 +131,7 @@ var tests = []*components.IntegrationTest{ commit.FailHooksThenCommitNoHooks, commit.FindBaseCommitForFixup, commit.FindBaseCommitForFixupDisregardMainBranch, + commit.FindBaseCommitForFixupInMainBranch, commit.FindBaseCommitForFixupOnlyAddedLines, commit.FindBaseCommitForFixupWarningForAddedLines, commit.Highlight,