mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-01-10 04:07:18 +02:00
Allow cherry-picking commits during a rebase (#3013)
This commit is contained in:
commit
1aae1772ce
@ -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 {
|
||||
|
@ -25,19 +25,16 @@ func NewStatusCommands(
|
||||
// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase
|
||||
// and "interactive" for interactive rebase
|
||||
func (self *StatusCommands) RebaseMode() (enums.RebaseMode, error) {
|
||||
exists, err := self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply"))
|
||||
if err != nil {
|
||||
return enums.REBASE_MODE_NONE, err
|
||||
}
|
||||
if exists {
|
||||
ok, err := self.IsInNormalRebase()
|
||||
if err == nil && ok {
|
||||
return enums.REBASE_MODE_NORMAL, nil
|
||||
}
|
||||
exists, err = self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge"))
|
||||
if exists {
|
||||
ok, err = self.IsInInteractiveRebase()
|
||||
if err == nil && ok {
|
||||
return enums.REBASE_MODE_INTERACTIVE, err
|
||||
} else {
|
||||
return enums.REBASE_MODE_NONE, err
|
||||
}
|
||||
|
||||
return enums.REBASE_MODE_NONE, err
|
||||
}
|
||||
|
||||
func (self *StatusCommands) WorkingTreeState() enums.RebaseMode {
|
||||
@ -68,6 +65,14 @@ func IsBareRepo(osCommand *oscommands.OSCommand) (bool, error) {
|
||||
return strconv.ParseBool(strings.TrimSpace(res))
|
||||
}
|
||||
|
||||
func (self *StatusCommands) IsInNormalRebase() (bool, error) {
|
||||
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply"))
|
||||
}
|
||||
|
||||
func (self *StatusCommands) IsInInteractiveRebase() (bool, error) {
|
||||
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge"))
|
||||
}
|
||||
|
||||
// IsInMergeState states whether we are still mid-merge
|
||||
func (self *StatusCommands) IsInMergeState() (bool, error) {
|
||||
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "MERGE_HEAD"))
|
||||
|
@ -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)
|
||||
|
@ -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"),
|
||||
)
|
||||
},
|
||||
})
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user