diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index 66adee2af..2dd1ee886 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -457,6 +457,20 @@ func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error { }).Run() } +// CherryPickCommitsDuringRebase simply prepends the given commits to the existing git-rebase-todo file +func (self *RebaseCommands) CherryPickCommitsDuringRebase(commits []*models.Commit) error { + todoLines := lo.Map(commits, func(commit *models.Commit, _ int) daemon.TodoLine { + return daemon.TodoLine{ + Action: "pick", + Commit: commit, + } + }) + + todo := daemon.TodoLinesToString(todoLines) + filePath := filepath.Join(self.repoPaths.worktreeGitDirPath, "rebase-merge/git-rebase-todo") + return utils.PrependStrToTodoFile(filePath, []byte(todo)) +} + // we can't start an interactive rebase from the first commit without passing the // '--root' arg func getBaseShaOrRoot(commits []*models.Commit, index int) string { diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go index e27e469b6..4f455ca30 100644 --- a/pkg/gui/controllers/helpers/cherry_pick_helper.go +++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go @@ -76,6 +76,19 @@ func (self *CherryPickHelper) Paste() error { Title: self.c.Tr.CherryPick, Prompt: self.c.Tr.SureCherryPick, HandleConfirm: func() error { + isInRebase, err := self.c.Git().Status.IsInInteractiveRebase() + if err != nil { + return err + } + if isInRebase { + if err := self.c.Git().Rebase.CherryPickCommitsDuringRebase(self.getData().CherryPickedCommits); err != nil { + return err + } + return self.c.Refresh(types.RefreshOptions{ + Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS}, + }) + } + return self.c.WithWaitingStatus(self.c.Tr.CherryPickingStatus, func(gocui.Task) error { self.c.LogAction(self.c.Tr.Actions.CherryPick) err := self.c.Git().Rebase.CherryPickCommits(self.getData().CherryPickedCommits) diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go b/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go new file mode 100644 index 000000000..4cf32bad3 --- /dev/null +++ b/pkg/integration/tests/cherry_pick/cherry_pick_during_rebase.go @@ -0,0 +1,87 @@ +package cherry_pick + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var CherryPickDuringRebase = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Cherry pick commits from the subcommits view during a rebase", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell. + EmptyCommit("base"). + NewBranch("first-branch"). + NewBranch("second-branch"). + Checkout("first-branch"). + EmptyCommit("one"). + EmptyCommit("two"). + Checkout("second-branch"). + EmptyCommit("three"). + EmptyCommit("four"). + Checkout("first-branch") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Branches(). + Focus(). + Lines( + Contains("first-branch"), + Contains("second-branch"), + Contains("master"), + ). + SelectNextItem(). + PressEnter() + + t.Views().SubCommits(). + IsFocused(). + Lines( + Contains("four").IsSelected(), + Contains("three"), + Contains("base"), + ). + // copy commit 'three' + SelectNextItem(). + Press(keys.Commits.CherryPickCopy) + + t.Views().Information().Content(Contains("1 commit copied")) + + t.Views().Commits(). + Focus(). + Lines( + Contains("CI two").IsSelected(), + Contains("CI one"), + Contains("CI base"), + ). + SelectNextItem(). + Press(keys.Universal.Edit). + Lines( + Contains("pick CI two"), + Contains(" CI <-- YOU ARE HERE --- one").IsSelected(), + Contains(" CI base"), + ). + Press(keys.Commits.PasteCommits). + Tap(func() { + t.ExpectPopup().Alert(). + Title(Equals("Cherry-pick")). + Content(Contains("Are you sure you want to cherry-pick the copied commits onto this branch?")). + Confirm() + }). + Lines( + Contains("pick CI two"), + Contains("pick CI three"), + Contains(" CI <-- YOU ARE HERE --- one"), + Contains(" CI base"), + ). + Tap(func() { + t.Common().ContinueRebase() + }). + Lines( + Contains("CI two"), + Contains("CI three"), + Contains("CI one"), + Contains("CI base"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index b820555f2..d16da747d 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -55,6 +55,7 @@ var tests = []*components.IntegrationTest{ branch.Suggestions, cherry_pick.CherryPick, cherry_pick.CherryPickConflicts, + cherry_pick.CherryPickDuringRebase, commit.AddCoAuthor, commit.Amend, commit.Commit,