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

Improve editing a commit (#4090)

This commit is contained in:
Stefan Haller
2024-12-01 11:08:44 +01:00
committed by GitHub
7 changed files with 225 additions and 21 deletions

View File

@@ -145,11 +145,11 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx
baseHashOrRoot := getBaseHashOrRoot(commits, baseIndex)
changes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) daemon.ChangeTodoAction {
changes := lo.FilterMap(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) (daemon.ChangeTodoAction, bool) {
return daemon.ChangeTodoAction{
Hash: commit.Hash,
NewAction: action,
}
}, !commit.IsMerge()
})
self.os.LogCommand(logTodoChanges(changes), false)

View File

@@ -9,6 +9,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style"
@@ -115,7 +116,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
},
{
Key: opts.GetKey(editCommitKey),
Handler: self.withItems(self.edit),
Handler: self.withItemsRange(self.edit),
GetDisabledReason: self.require(
self.itemRangeSelected(self.midRebaseCommandEnabled),
),
@@ -510,11 +511,25 @@ func (self *LocalCommitsController) drop(selectedCommits []*models.Commit, start
return nil
}
func (self *LocalCommitsController) edit(selectedCommits []*models.Commit) error {
func (self *LocalCommitsController) edit(selectedCommits []*models.Commit, startIdx int, endIdx int) error {
if self.isRebasing() {
return self.updateTodos(todo.Edit, selectedCommits)
}
commits := self.c.Model().Commits
if !commits[endIdx].IsMerge() {
selectionRangeAndMode := self.getSelectionRangeAndMode()
err := self.c.Git().Rebase.InteractiveRebase(commits, startIdx, endIdx, todo.Edit)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err,
types.RefreshOptions{
Mode: types.BLOCK_UI, Then: func() error {
self.restoreSelectionRangeAndMode(selectionRangeAndMode)
return nil
},
})
}
return self.startInteractiveRebaseWithEdit(selectedCommits)
}
@@ -532,10 +547,7 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
) error {
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.EditCommit)
selectedIdx, rangeStartIdx, rangeSelectMode := self.context().GetSelectionRangeAndMode()
commits := self.c.Model().Commits
selectedHash := commits[selectedIdx].Hash
rangeStartHash := commits[rangeStartIdx].Hash
selectionRangeAndMode := self.getSelectionRangeAndMode()
err := self.c.Git().Rebase.EditRebase(commitsToEdit[len(commitsToEdit)-1].Hash)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err,
@@ -554,23 +566,41 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
}
}
// We need to select the same commit range again because after starting a rebase,
// new lines can be added for update-ref commands in the TODO file, due to
// stacked branches. So the selected commits may be in different positions in the list.
_, newSelectedIdx, ok1 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.Hash == selectedHash
})
_, newRangeStartIdx, ok2 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.Hash == rangeStartHash
})
if ok1 && ok2 {
self.context().SetSelectionRangeAndMode(newSelectedIdx, newRangeStartIdx, rangeSelectMode)
}
self.restoreSelectionRangeAndMode(selectionRangeAndMode)
return nil
}})
})
}
type SelectionRangeAndMode struct {
selectedHash string
rangeStartHash string
mode traits.RangeSelectMode
}
func (self *LocalCommitsController) getSelectionRangeAndMode() SelectionRangeAndMode {
selectedIdx, rangeStartIdx, rangeSelectMode := self.context().GetSelectionRangeAndMode()
commits := self.c.Model().Commits
selectedHash := commits[selectedIdx].Hash
rangeStartHash := commits[rangeStartIdx].Hash
return SelectionRangeAndMode{selectedHash, rangeStartHash, rangeSelectMode}
}
func (self *LocalCommitsController) restoreSelectionRangeAndMode(selectionRangeAndMode SelectionRangeAndMode) {
// We need to select the same commit range again because after starting a rebase,
// new lines can be added for update-ref commands in the TODO file, due to
// stacked branches. So the selected commits may be in different positions in the list.
_, newSelectedIdx, ok1 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.Hash == selectionRangeAndMode.selectedHash
})
_, newRangeStartIdx, ok2 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.Hash == selectionRangeAndMode.rangeStartHash
})
if ok1 && ok2 {
self.context().SetSelectionRangeAndMode(newSelectedIdx, newRangeStartIdx, selectionRangeAndMode.mode)
}
}
func (self *LocalCommitsController) findCommitForQuickStartInteractiveRebase() (*models.Commit, error) {
commit, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.IsMerge() || c.Status == models.StatusMerged

View File

@@ -38,7 +38,6 @@ var DropTodoCommitWithUpdateRef = NewIntegrationTest(NewIntegrationTestArgs{
).
NavigateToLine(Contains("commit 02")).
Press(keys.Universal.Edit).
Focus().
Lines(
Contains("pick").Contains("CI commit 07"),
Contains("pick").Contains("CI commit 06"),

View File

@@ -0,0 +1,55 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var EditAndAutoAmend = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Edit a commit, make a change and stage it, then continue the rebase to auto-amend the commit",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
CreateNCommits(3)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("commit 03"),
Contains("commit 02"),
Contains("commit 01"),
).
NavigateToLine(Contains("commit 02")).
Press(keys.Universal.Edit).
Lines(
Contains("commit 03"),
MatchesRegexp("YOU ARE HERE.*commit 02").IsSelected(),
Contains("commit 01"),
)
t.Shell().CreateFile("fixup-file", "fixup content")
t.Views().Files().
Focus().
Press(keys.Files.RefreshFiles).
Lines(
Contains("??").Contains("fixup-file").IsSelected(),
).
PressPrimaryAction()
t.Common().ContinueRebase()
t.Views().Commits().
Focus().
Lines(
Contains("commit 03"),
Contains("commit 02").IsSelected(),
Contains("commit 01"),
)
t.Views().Main().
Content(Contains("fixup content"))
},
})

View File

@@ -0,0 +1,74 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var EditLastCommitOfStackedBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Edit and amend the last commit of a branch in a stack of branches, and ensure that it doesn't break the stack",
ExtraCmdArgs: []string{},
Skip: false,
GitVersion: AtLeast("2.38.0"),
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.MainBranches = []string{"master"}
config.GetAppState().GitLogShowGraph = "never"
},
SetupRepo: func(shell *Shell) {
shell.
CreateNCommits(1).
NewBranch("branch1").
CreateNCommitsStartingAt(2, 2).
NewBranch("branch2").
CreateNCommitsStartingAt(2, 4)
shell.SetConfig("rebase.updateRefs", "true")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("CI commit 05").IsSelected(),
Contains("CI commit 04"),
Contains("CI * commit 03"),
Contains("CI commit 02"),
Contains("CI commit 01"),
).
NavigateToLine(Contains("commit 03")).
Press(keys.Universal.Edit).
Lines(
Contains("pick").Contains("CI commit 05"),
Contains("pick").Contains("CI commit 04"),
Contains("update-ref").Contains("branch1"),
Contains("<-- YOU ARE HERE --- * commit 03").IsSelected(),
Contains("CI commit 02"),
Contains("CI commit 01"),
)
t.Shell().CreateFile("fixup-file", "fixup content")
t.Views().Files().
Focus().
Press(keys.Files.RefreshFiles).
Lines(
Contains("??").Contains("fixup-file").IsSelected(),
).
PressPrimaryAction().
Press(keys.Files.AmendLastCommit)
t.ExpectPopup().Confirmation().
Title(Equals("Amend last commit")).
Content(Contains("Are you sure you want to amend last commit?")).
Confirm()
t.Common().ContinueRebase()
t.Views().Commits().
Focus().
Lines(
Contains("CI commit 05"),
Contains("CI commit 04"),
Contains("CI * commit 03"),
Contains("CI commit 02"),
Contains("CI commit 01"),
)
},
})

View File

@@ -0,0 +1,43 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests/shared"
)
var EditRangeSelectDownToMergeOutsideRebase = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Select a range of commits (the last one being a merge commit) to edit outside of a rebase",
ExtraCmdArgs: []string{},
Skip: false,
GitVersion: AtLeast("2.22.0"), // first version that supports the --rebase-merges option
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shared.CreateMergeCommit(shell)
shell.CreateNCommits(2)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
TopLines(
Contains("CI ◯ commit 02").IsSelected(),
Contains("CI ◯ commit 01"),
Contains("Merge branch 'second-change-branch' into first-change-branch"),
).
Press(keys.Universal.RangeSelectDown).
Press(keys.Universal.RangeSelectDown).
Press(keys.Universal.Edit).
Lines(
Contains("edit CI commit 02").IsSelected(),
Contains("edit CI commit 01").IsSelected(),
Contains(" CI ⏣─╮ <-- YOU ARE HERE --- Merge branch 'second-change-branch' into first-change-branch").IsSelected(),
Contains(" CI │ ◯ * second-change-branch unrelated change"),
Contains(" CI │ ◯ second change"),
Contains(" CI ◯ │ first change"),
Contains(" CI ◯─╯ * original"),
Contains(" CI ◯ three"),
Contains(" CI ◯ two"),
Contains(" CI ◯ one"),
)
},
})

View File

@@ -210,8 +210,11 @@ var tests = []*components.IntegrationTest{
interactive_rebase.DropCommitInCopiedBranchWithUpdateRef,
interactive_rebase.DropTodoCommitWithUpdateRef,
interactive_rebase.DropWithCustomCommentChar,
interactive_rebase.EditAndAutoAmend,
interactive_rebase.EditFirstCommit,
interactive_rebase.EditLastCommitOfStackedBranch,
interactive_rebase.EditNonTodoCommitDuringRebase,
interactive_rebase.EditRangeSelectDownToMergeOutsideRebase,
interactive_rebase.EditRangeSelectOutsideRebase,
interactive_rebase.EditTheConflCommit,
interactive_rebase.FixupFirstCommit,