1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2026-06-20 01:19:23 +02:00

Support using the selected commit's message in a fixup (#5233)

### PR Description

I had a spare couple hours so figured I'd whip up a PR for a feature
I've wanted for a while.

I've optimised for muscle memory backwards compatibility here:
- Outside interactive rebase: press 'f' then instead of a confirmation
panel, a menu appears where you can choose to keep the selected commit's
message
- Inside interactive rebase: press 'f' then press 'c' to see the menu
for keeping the message, where if you press 'c' again it will retain the
current message. so 'fcc' is the chord to press.

We're also now showing the -C flag (which is what enables the behaviour)
against the todo.

I've picked the 'c' keybinding because 'C' was taken and it corresponds
to the flag. Previously that showed a warning about a change in
keybinding for cherry picking but it's been ages since we've made that
change so I'm happy to retire it.
This commit is contained in:
Stefan Haller
2026-01-28 10:31:47 +01:00
committed by GitHub
28 changed files with 270 additions and 45 deletions
+1
View File
@@ -713,6 +713,7 @@ keybinding:
renameCommitWithEditor: R
viewResetOptions: g
markCommitAsFixup: f
setFixupMessage: c
createFixupCommit: F
squashAboveCommits: S
moveDownCommit: <c-j>
@@ -89,6 +89,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Reword the selected commit's message. |
| `` R `` | Reword with editor | |
| `` d `` | Drop | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -69,6 +69,7 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
| `` b `` | bisectオプションを表示 | |
| `` s `` | スカッシュ | 選択したコミットをその下のコミットにスカッシュします。スカッシュとは複数のコミットを1つにまとめる操作です。選択したコミットのメッセージが下のコミットに追加されます。 |
| `` f `` | フィックスアップ | 選択したコミットをその下のコミットにマージします。フィックスアップはスカッシュと似ていますが、選択したコミットのメッセージは破棄され、下のコミットのメッセージのみが保持されます。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | メッセージ変更 | 選択したコミットのメッセージを変更します。 |
| `` R `` | エディタでメッセージ変更 | |
| `` d `` | 削除 | 選択したコミットを削除します。これはリベースを通じてブランチからコミットを削除します。コミットが後続のコミットが依存する変更を行っている場合、マージコンフリクトを解決する必要があるかもしれません。 |
@@ -298,6 +298,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` b `` | Bisect 옵션 보기 | |
| `` s `` | 스쿼시 | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 커밋메시지 변경 | Reword the selected commit's message. |
| `` R `` | 에디터에서 커밋메시지 수정 | |
| `` d `` | 커밋 삭제 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -160,6 +160,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Hernoem commit | Reword the selected commit's message. |
| `` R `` | Hernoem commit met editor | |
| `` d `` | Verwijder commit | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -62,6 +62,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
| `` b `` | Zobacz opcje bisect | |
| `` s `` | Scal | Scal wybrany commit z commitami poniżej. Wiadomość wybranego commita zostanie dołączona do commita poniżej. |
| `` f `` | Poprawka | Włącz wybrany commit do commita poniżej. Podobnie do fixup, ale wiadomość wybranego commita zostanie odrzucona. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Przeformułuj | Przeformułuj wiadomość wybranego commita. |
| `` R `` | Przeformułuj za pomocą edytora | |
| `` d `` | Usuń | Usuń wybrany commit. To usunie commit z gałęzi za pomocą rebazowania. Jeśli commit wprowadza zmiany, od których zależą późniejsze commity, być może będziesz musiał rozwiązać konflikty scalania. |
@@ -164,6 +164,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` b `` | View bisect options | |
| `` s `` | Squash | Squash o commit selecionado no commit abaixo dele. A mensagem do commit selecionado será anexada ao commit abaixo dele. |
| `` f `` | Fixup | Faça o commit selecionado no commit abaixo dele. Semelhante para o squash, mas a mensagem do commit selecionado será descartada. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Reword | Repetir a mensagem de submissão selecionada. |
| `` R `` | Republicar com o editor | |
| `` d `` | Descartar | Solte o commit selecionado. Isso irá remover o commit do branch através de uma rebase. Se o commit faz com que as alterações em commits posteriores dependem, você pode precisar resolver conflitos de merge. |
@@ -170,6 +170,7 @@ _Связки клавиш_
| `` b `` | Просмотреть параметры бинарного поиска | |
| `` s `` | Объединить коммиты (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | Объединить несколько коммитов в один отбросив сообщение коммита (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | Перефразировать коммит | Reword the selected commit's message. |
| `` R `` | Переписать коммит с помощью редактора | |
| `` d `` | Удалить коммит | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
@@ -126,6 +126,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
| `` b `` | 查看二分查找选项 | |
| `` s `` | 压缩(Squash) | 将已选提交压缩到该提交之下。这些选定的提交的消息会附加到该提交的消息之下。 |
| `` f `` | 修正 (fixup) | 将选定的提交合并到其下面的提交中。与压缩类似,但所选提交的消息将被丢弃。 |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改写提交 | 重写所选提交的消息。 |
| `` R `` | 使用编辑器重命名提交 | |
| `` d `` | 删除提交 | 删除选中的提交。这将通过变基从分支中删除该提交,如果该提交修改的内容依赖于后续的提交,则需要解决合并冲突。 |
@@ -184,6 +184,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
| `` b `` | 查看二分選項 | |
| `` s `` | 壓縮 (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
| `` f `` | 修復 (Fixup) | Meld the selected commit into the commit below it. Similar to squash, but the selected commit's message will be discarded. |
| `` c `` | Set fixup message | Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message. |
| `` r `` | 改寫提交 | 改寫選中的提交訊息 |
| `` R `` | 使用編輯器改寫提交 | |
| `` d `` | 刪除提交 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
+1
View File
@@ -199,6 +199,7 @@ func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
return utils.TodoChange{
Hash: c.Hash,
NewAction: c.NewAction,
Flag: c.Flag,
}
})
+1
View File
@@ -14,6 +14,7 @@ import (
type ChangeTodoAction struct {
Hash string
NewAction todo.TodoCommand
Flag string
}
func handleInteractiveRebase(common *common.Common, f func(path string) error) error {
@@ -325,6 +325,7 @@ func (self *CommitLoader) getHydratedTodoCommits(hashPool *utils.StringPool, tod
hydratedCommits = append(hydratedCommits, rebasingCommit)
} else if commit := findFullCommit(rebasingCommit.Hash()); commit != nil {
commit.Action = rebasingCommit.Action
commit.ActionFlag = rebasingCommit.ActionFlag
commit.Status = rebasingCommit.Status
hydratedCommits = append(hydratedCommits, commit)
}
@@ -375,6 +376,7 @@ func (self *CommitLoader) getRebasingCommits(hashPool *utils.StringPool, addConf
Name: t.Msg,
Status: models.StatusRebasing,
Action: t.Command,
ActionFlag: t.Flag,
}))
}
+4 -2
View File
@@ -139,7 +139,7 @@ func (self *RebaseCommands) MoveCommitsUp(commits []*models.Commit, startIdx int
}).Run()
}
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand) error {
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand, flag string) error {
baseIndex := endIdx + 1
if action == todo.Squash || action == todo.Fixup {
baseIndex++
@@ -151,6 +151,7 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx
return daemon.ChangeTodoAction{
Hash: commit.Hash(),
NewAction: action,
Flag: flag,
}, !commit.IsMerge()
})
@@ -334,11 +335,12 @@ func todoFromCommit(commit *models.Commit) utils.Todo {
}
// Sets the action for the given commits in the git-rebase-todo file
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand) error {
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand, flag string) error {
commitsWithAction := lo.Map(commits, func(commit *models.Commit, _ int) utils.TodoChange {
return utils.TodoChange{
Hash: commit.Hash(),
NewAction: action,
Flag: flag,
}
})
+3
View File
@@ -60,6 +60,7 @@ type Commit struct {
Status CommitStatus
Action todo.TodoCommand
ActionFlag string // e.g. "-C" for fixup -C
Divergence Divergence // set to DivergenceNone unless we are showing the divergence view
}
@@ -68,6 +69,7 @@ type NewCommitOpts struct {
Name string
Status CommitStatus
Action todo.TodoCommand
ActionFlag string
Tags []string
ExtraInfo string
AuthorName string
@@ -83,6 +85,7 @@ func NewCommit(hashPool *utils.StringPool, opts NewCommitOpts) *Commit {
Name: opts.Name,
Status: opts.Status,
Action: opts.Action,
ActionFlag: opts.ActionFlag,
Tags: opts.Tags,
ExtraInfo: opts.ExtraInfo,
AuthorName: opts.AuthorName,
+2
View File
@@ -551,6 +551,7 @@ type KeybindingCommitsConfig struct {
RenameCommitWithEditor string `yaml:"renameCommitWithEditor"`
ViewResetOptions string `yaml:"viewResetOptions"`
MarkCommitAsFixup string `yaml:"markCommitAsFixup"`
SetFixupMessage string `yaml:"setFixupMessage"`
CreateFixupCommit string `yaml:"createFixupCommit"`
SquashAboveCommits string `yaml:"squashAboveCommits"`
MoveDownCommit string `yaml:"moveDownCommit"`
@@ -1008,6 +1009,7 @@ func GetDefaultConfig() *UserConfig {
RenameCommitWithEditor: "R",
ViewResetOptions: "g",
MarkCommitAsFixup: "f",
SetFixupMessage: "c",
CreateFixupCommit: "F",
SquashAboveCommits: "S",
MoveDownCommit: "<c-j>",
@@ -1,7 +1,6 @@
package controllers
import (
"errors"
"fmt"
"strings"
@@ -130,14 +129,6 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
GetDisabledReason: self.require(self.canSelectCommitsOfCurrentBranch),
Description: self.c.Tr.SelectCommitsOfCurrentBranch,
},
// Putting this at the bottom of the list so that it has the lowest priority,
// meaning that if the user has configured another keybinding to the same key
// then that will take precedence.
{
// Hardcoding this key because it's not configurable
Key: opts.GetKey("c"),
Handler: self.handleOldCherryPickKey,
},
}
return bindings
@@ -382,16 +373,6 @@ func (self *BasicCommitsController) canCopyCommits(selectedCommits []*models.Com
return nil
}
func (self *BasicCommitsController) handleOldCherryPickKey() error {
msg := utils.ResolvePlaceholderString(self.c.Tr.OldCherryPickKeyWarning,
map[string]string{
"copy": keybindings.Label(self.c.UserConfig().Keybinding.Commits.CherryPickCopy),
"paste": keybindings.Label(self.c.UserConfig().Keybinding.Commits.PasteCommits),
})
return errors.New(msg)
}
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {
to := commit.RefName()
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(commit.ParentRefName())
@@ -82,6 +82,15 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
Tooltip: self.c.Tr.FixupTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Commits.SetFixupMessage),
Handler: self.withItem(self.setFixupMessage),
GetDisabledReason: self.require(
self.singleItemSelected(self.canSetFixupMessage),
),
Description: self.c.Tr.SetFixupMessage,
Tooltip: self.c.Tr.SetFixupMessageTooltip,
},
{
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
Handler: self.withItem(self.reword),
@@ -321,20 +330,71 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
return self.updateTodos(todo.Fixup, selectedCommits)
}
self.c.Confirm(types.ConfirmOpts{
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.Fixup,
Prompt: self.c.Tr.SureFixupThisCommit,
HandleConfirm: func() error {
Items: []*types.MenuItem{
{
Label: self.c.Tr.Fixup,
Key: 'f',
OnPress: func() error {
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.FixupCommit)
return self.interactiveRebase(todo.Fixup, startIdx, endIdx)
})
},
Tooltip: self.c.Tr.FixupTooltip,
},
{
Label: self.c.Tr.FixupKeepMessage,
Key: 'c',
OnPress: func() error {
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.FixupCommitKeepMessage)
return self.interactiveRebaseWithFlag(todo.Fixup, startIdx, endIdx, "-C")
})
},
Tooltip: self.c.Tr.FixupKeepMessageTooltip,
},
},
})
}
func (self *LocalCommitsController) canSetFixupMessage(commit *models.Commit) *types.DisabledReason {
if !self.isRebasing() {
return &types.DisabledReason{Text: self.c.Tr.NotMidRebase}
}
if commit.Action != todo.Fixup {
return &types.DisabledReason{Text: self.c.Tr.MustSelectFixupCommit}
}
return nil
}
func (self *LocalCommitsController) setFixupMessage(commit *models.Commit) error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.SetFixupMessage,
Items: []*types.MenuItem{
{
Label: self.c.Tr.FixupDiscardMessage,
Key: 'f',
OnPress: func() error {
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "")
},
Tooltip: self.c.Tr.FixupDiscardMessageTooltip,
},
{
Label: self.c.Tr.FixupKeepMessage,
Key: 'c',
OnPress: func() error {
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "-C")
},
Tooltip: self.c.Tr.FixupKeepMessageTooltip,
},
},
})
}
func (self *LocalCommitsController) reword(commit *models.Commit) error {
commitIdx := self.context().GetSelectedLineIdx()
if self.c.Git().Config.NeedsGpgSubprocessForCommit() && !self.isHeadCommit(commitIdx) {
@@ -505,7 +565,7 @@ func (self *LocalCommitsController) edit(selectedCommits []*models.Commit, start
commits := self.c.Model().Commits
if !commits[endIdx].IsMerge() {
selectionRangeAndMode := self.getSelectionRangeAndMode()
err := self.c.Git().Rebase.InteractiveRebase(commits, startIdx, endIdx, todo.Edit)
err := self.c.Git().Rebase.InteractiveRebase(commits, startIdx, endIdx, todo.Edit, "")
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
err,
types.RefreshOptions{
@@ -611,13 +671,17 @@ func (self *LocalCommitsController) pick(selectedCommits []*models.Commit) error
}
func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, startIdx int, endIdx int) error {
return self.interactiveRebaseWithFlag(action, startIdx, endIdx, "")
}
func (self *LocalCommitsController) interactiveRebaseWithFlag(action todo.TodoCommand, startIdx int, endIdx int, flag string) error {
// When performing an action that will remove the selected commits, we need to select the
// next commit down (which will end up at the start index after the action is performed)
if action == todo.Drop || action == todo.Fixup || action == todo.Squash {
self.context().SetSelection(startIdx)
}
err := self.c.Git().Rebase.InteractiveRebase(self.c.Model().Commits, startIdx, endIdx, action)
err := self.c.Git().Rebase.InteractiveRebase(self.c.Model().Commits, startIdx, endIdx, action, flag)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
}
@@ -626,7 +690,11 @@ func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, s
// commit meaning you are trying to edit the todo file rather than actually
// begin a rebase. It then updates the todo file with that action
func (self *LocalCommitsController) updateTodos(action todo.TodoCommand, selectedCommits []*models.Commit) error {
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action); err != nil {
return self.updateTodosWithFlag(action, selectedCommits, "")
}
func (self *LocalCommitsController) updateTodosWithFlag(action todo.TodoCommand, selectedCommits []*models.Commit, flag string) error {
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action, flag); err != nil {
return err
}
+6 -1
View File
@@ -385,7 +385,12 @@ func displayCommit(
actionString := ""
if commit.Action != models.ActionNone {
actionString = actionColorMap(commit.Action, commit.Status).Sprint(commit.Action.String())
actionStr := commit.Action.String()
// Only show the flag for fixup commands (where -C changes the meaning)
if commit.ActionFlag != "" && commit.Action == todo.Fixup {
actionStr += " " + commit.ActionFlag
}
actionString = actionColorMap(commit.Action, commit.Status).Sprint(actionStr)
}
tagString := ""
+18 -4
View File
@@ -164,7 +164,12 @@ type TranslationSet struct {
CannotSquashOrFixupMergeCommit string
Fixup string
FixupTooltip string
SureFixupThisCommit string
FixupKeepMessage string
FixupKeepMessageTooltip string
SetFixupMessage string
SetFixupMessageTooltip string
FixupDiscardMessage string
FixupDiscardMessageTooltip string
SureSquashThisCommit string
Squash string
PickCommitTooltip string
@@ -316,6 +321,8 @@ type TranslationSet struct {
ViewRevertOptions string
NotMergingOrRebasing string
AlreadyRebasing string
NotMidRebase string
MustSelectFixupCommit string
RecentRepos string
MergeOptionsTitle string
RebaseOptionsTitle string
@@ -897,7 +904,6 @@ type TranslationSet struct {
SelectedItemIsNotABranch string
SelectedItemDoesNotHaveFiles string
MultiSelectNotSupportedForSubmodules string
OldCherryPickKeyWarning string
CommandDoesNotSupportOpeningInEditor string
CustomCommands string
NoApplicableCommandsInThisContext string
@@ -966,6 +972,7 @@ type Actions struct {
CheckoutFile string
SquashCommitDown string
FixupCommit string
FixupCommitKeepMessage string
RewordCommit string
DropCommit string
EditCommit string
@@ -1260,7 +1267,12 @@ func EnglishTranslationSet() *TranslationSet {
CannotSquashOrFixupFirstCommit: "There's no commit below to squash into",
CannotSquashOrFixupMergeCommit: "Cannot squash or fixup a merge commit",
Fixup: "Fixup",
SureFixupThisCommit: "Are you sure you want to 'fixup' the selected commit(s) into the commit below?",
FixupKeepMessage: "Fixup and use this commit's message",
FixupKeepMessageTooltip: "Squash the selected commit into the commit below, using this commit's message, discarding the message of the commit below.",
SetFixupMessage: "Set fixup message",
SetFixupMessageTooltip: "Set the message option for the fixup commit. The -C option means to use this commit's message instead of the target commit's message.",
FixupDiscardMessage: "Fixup and discard this commit's message",
FixupDiscardMessageTooltip: "Squash the selected commit into the commit below, discarding this commit's message.",
SureSquashThisCommit: "Are you sure you want to squash the selected commit(s) into the commit below?",
Squash: "Squash",
PickCommitTooltip: "Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase.",
@@ -1412,6 +1424,8 @@ func EnglishTranslationSet() *TranslationSet {
ViewRevertOptions: "View revert options",
NotMergingOrRebasing: "You are currently neither rebasing nor merging",
AlreadyRebasing: "Can't perform this action during a rebase",
NotMidRebase: "This action only works during an interactive rebase",
MustSelectFixupCommit: "This action only works on fixup commits",
RecentRepos: "Recent repositories",
MergeOptionsTitle: "Merge options",
RebaseOptionsTitle: "Rebase options",
@@ -1993,7 +2007,6 @@ func EnglishTranslationSet() *TranslationSet {
SelectedItemIsNotABranch: "Selected item is not a branch",
SelectedItemDoesNotHaveFiles: "Selected item does not have files to view",
MultiSelectNotSupportedForSubmodules: "Multiselection not supported for submodules",
OldCherryPickKeyWarning: "The 'c' key is no longer the default key for copying commits to cherry pick. Please use `{{.copy}}` instead (and `{{.paste}}` to paste). The reason for this change is that the 'v' key for selecting a range of lines when staging is now also used for selecting a range of lines in any list view, meaning that we needed to find a new key for pasting commits, and if we're going to now use `{{.paste}}` for pasting commits, we may as well use `{{.copy}}` for copying them. If you want to configure the keybindings to get the old behaviour, set the following in your config:\n\nkeybinding:\n universal:\n toggleRangeSelect: <something other than v>\n commits:\n cherryPickCopy: 'c'\n pasteCommits: 'v'",
CommandDoesNotSupportOpeningInEditor: "This command doesn't support switching to the editor",
CustomCommands: "Custom commands",
NoApplicableCommandsInThisContext: "(No applicable commands in this context)",
@@ -2025,6 +2038,7 @@ func EnglishTranslationSet() *TranslationSet {
CheckoutFile: "Checkout file",
SquashCommitDown: "Squash commit down",
FixupCommit: "Fixup commit",
FixupCommitKeepMessage: "Fixup commit (keep message)",
RewordCommit: "Reword commit",
DropCommit: "Drop commit",
EditCommit: "Edit commit",
@@ -0,0 +1,48 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FixupKeepMessage = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Fixup a commit, keeping its commit message",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
CreateFileAndAdd("file1.txt", "File1 Content\n").Commit("First Commit").
CreateFileAndAdd("file2.txt", "File2 Content\n").Commit("Second Commit").
CreateFileAndAdd("file3.txt", "File3 Content\n").Commit("Third Commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("Third Commit"),
Contains("Second Commit"),
Contains("First Commit"),
).
NavigateToLine(Contains("Second Commit")).
Press(keys.Commits.MarkCommitAsFixup).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Fixup")).
Select(Contains("use this commit's message")).
Confirm()
}).
Lines(
Contains("Third Commit"),
Contains("Second Commit").IsSelected(),
)
t.Views().Main().
// The resulting commit should have the message from the fixup commit,
// not the target commit
Content(Contains("Second Commit")).
Content(DoesNotContain("First Commit")).
Content(Contains("+File1 Content")).
Content(Contains("+File2 Content"))
},
})
@@ -0,0 +1,78 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FixupKeepMessageRebase = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Set fixup -C flag on a fixup commit during interactive rebase",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
CreateFileAndAdd("file1.txt", "File1 Content\n").Commit("First Commit").
CreateFileAndAdd("file2.txt", "File2 Content\n").Commit("Second Commit").
CreateFileAndAdd("file3.txt", "File3 Content\n").Commit("Third Commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("Third Commit"),
Contains("Second Commit"),
Contains("First Commit"),
).
// Start interactive rebase from the first commit
NavigateToLine(Contains("First Commit")).
Press(keys.Universal.Edit).
Lines(
Contains("--- Pending rebase todos ---"),
Contains("pick CI Third Commit"),
Contains("pick CI Second Commit"),
Contains("--- Commits ---"),
Contains("First Commit").IsSelected(),
).
// Mark second commit as fixup
NavigateToLine(Contains("Second Commit")).
Press(keys.Commits.MarkCommitAsFixup).
Lines(
Contains("--- Pending rebase todos ---"),
Contains("pick CI Third Commit"),
Contains("fixup CI Second Commit").IsSelected(),
Contains("--- Commits ---"),
Contains("First Commit"),
).
// Now set the -C flag using the SetFixupMessage keybinding
Press(keys.Commits.SetFixupMessage).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Set fixup message")).
Select(Contains("use this commit's message")).
Confirm()
}).
Lines(
Contains("--- Pending rebase todos ---"),
Contains("pick CI Third Commit"),
Contains("fixup -C CI Second Commit").IsSelected(),
Contains("--- Commits ---"),
Contains("First Commit"),
).
// Continue the rebase
Tap(func() {
t.Common().ContinueRebase()
}).
Lines(
Contains("Third Commit"),
Contains("Second Commit").IsSelected(),
)
t.Views().Main().
// The resulting commit should have the message from the fixup commit
Content(Contains("Second Commit")).
Content(DoesNotContain("First Commit")).
Content(Contains("+File1 Content")).
Content(Contains("+File2 Content"))
},
})
@@ -27,9 +27,8 @@ var FixupSecondCommit = NewIntegrationTest(NewIntegrationTestArgs{
NavigateToLine(Contains("Fixup Commit Message")).
Press(keys.Commits.MarkCommitAsFixup).
Tap(func() {
t.ExpectPopup().Confirmation().
t.ExpectPopup().Menu().
Title(Equals("Fixup")).
Content(Equals("Are you sure you want to 'fixup' the selected commit(s) into the commit below?")).
Confirm()
}).
Lines(
@@ -77,9 +77,8 @@ var OutsideRebaseRangeSelect = NewIntegrationTest(NewIntegrationTestArgs{
).
Press(keys.Commits.MarkCommitAsFixup).
Tap(func() {
t.ExpectPopup().Confirmation().
t.ExpectPopup().Menu().
Title(Equals("Fixup")).
Content(Contains("Are you sure you want to 'fixup' the selected commit(s) into the commit below?")).
Confirm()
}).
TopLines(
+2
View File
@@ -279,6 +279,8 @@ var tests = []*components.IntegrationTest{
interactive_rebase.EditRangeSelectOutsideRebase,
interactive_rebase.EditTheConflCommit,
interactive_rebase.FixupFirstCommit,
interactive_rebase.FixupKeepMessage,
interactive_rebase.FixupKeepMessageRebase,
interactive_rebase.FixupSecondCommit,
interactive_rebase.InteractiveRebaseOfCopiedBranch,
interactive_rebase.InteractiveRebaseWithConflictForEditCommand,
+2
View File
@@ -19,6 +19,7 @@ type Todo struct {
type TodoChange struct {
Hash string
NewAction todo.TodoCommand
Flag string
}
// Read a git-rebase-todo file, change the actions for the given commits,
@@ -37,6 +38,7 @@ func EditRebaseTodo(filePath string, changes []TodoChange, commentChar byte) err
if equalHash(t.Commit, change.Hash) {
matchCount++
t.Command = change.NewAction
t.Flag = change.Flag
}
}
}
+4
View File
@@ -946,6 +946,10 @@
"type": "string",
"default": "f"
},
"setFixupMessage": {
"type": "string",
"default": "c"
},
"createFixupCommit": {
"type": "string",
"default": "F"
+4
View File
@@ -946,6 +946,10 @@
"type": "string",
"default": "f"
},
"setFixupMessage": {
"type": "string",
"default": "c"
},
"createFixupCommit": {
"type": "string",
"default": "F"