diff --git a/docs-master/Config.md b/docs-master/Config.md index 21709da75..38887b3e2 100644 --- a/docs-master/Config.md +++ b/docs-master/Config.md @@ -713,6 +713,7 @@ keybinding: renameCommitWithEditor: R viewResetOptions: g markCommitAsFixup: f + setFixupMessage: c createFixupCommit: F squashAboveCommits: S moveDownCommit: diff --git a/docs-master/keybindings/Keybindings_en.md b/docs-master/keybindings/Keybindings_en.md index bbbd3e2e8..76b02512c 100644 --- a/docs-master/keybindings/Keybindings_en.md +++ b/docs-master/keybindings/Keybindings_en.md @@ -89,6 +89,7 @@ _Legend: `` means ctrl+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. | diff --git a/docs-master/keybindings/Keybindings_ja.md b/docs-master/keybindings/Keybindings_ja.md index 79cf196fe..39758d3ed 100644 --- a/docs-master/keybindings/Keybindings_ja.md +++ b/docs-master/keybindings/Keybindings_ja.md @@ -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 `` | 削除 | 選択したコミットを削除します。これはリベースを通じてブランチからコミットを削除します。コミットが後続のコミットが依存する変更を行っている場合、マージコンフリクトを解決する必要があるかもしれません。 | diff --git a/docs-master/keybindings/Keybindings_ko.md b/docs-master/keybindings/Keybindings_ko.md index 330c080ee..0860c8571 100644 --- a/docs-master/keybindings/Keybindings_ko.md +++ b/docs-master/keybindings/Keybindings_ko.md @@ -298,6 +298,7 @@ _Legend: `` means ctrl+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. | diff --git a/docs-master/keybindings/Keybindings_nl.md b/docs-master/keybindings/Keybindings_nl.md index f738be1b2..0bfffcb3d 100644 --- a/docs-master/keybindings/Keybindings_nl.md +++ b/docs-master/keybindings/Keybindings_nl.md @@ -160,6 +160,7 @@ _Legend: `` means ctrl+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. | diff --git a/docs-master/keybindings/Keybindings_pl.md b/docs-master/keybindings/Keybindings_pl.md index 7bf17f18b..656f16a76 100644 --- a/docs-master/keybindings/Keybindings_pl.md +++ b/docs-master/keybindings/Keybindings_pl.md @@ -62,6 +62,7 @@ _Legenda: `` oznacza ctrl+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. | diff --git a/docs-master/keybindings/Keybindings_pt.md b/docs-master/keybindings/Keybindings_pt.md index 54b1f1871..c9e5d3bf4 100644 --- a/docs-master/keybindings/Keybindings_pt.md +++ b/docs-master/keybindings/Keybindings_pt.md @@ -164,6 +164,7 @@ _Legend: `` means ctrl+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. | diff --git a/docs-master/keybindings/Keybindings_ru.md b/docs-master/keybindings/Keybindings_ru.md index cee2366b4..df0a4ce1f 100644 --- a/docs-master/keybindings/Keybindings_ru.md +++ b/docs-master/keybindings/Keybindings_ru.md @@ -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. | diff --git a/docs-master/keybindings/Keybindings_zh-CN.md b/docs-master/keybindings/Keybindings_zh-CN.md index 21b75ee29..37480d3c3 100644 --- a/docs-master/keybindings/Keybindings_zh-CN.md +++ b/docs-master/keybindings/Keybindings_zh-CN.md @@ -126,6 +126,7 @@ _图例:`` 意味着ctrl+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 `` | 删除提交 | 删除选中的提交。这将通过变基从分支中删除该提交,如果该提交修改的内容依赖于后续的提交,则需要解决合并冲突。 | diff --git a/docs-master/keybindings/Keybindings_zh-TW.md b/docs-master/keybindings/Keybindings_zh-TW.md index 59d6d74c9..107976c26 100644 --- a/docs-master/keybindings/Keybindings_zh-TW.md +++ b/docs-master/keybindings/Keybindings_zh-TW.md @@ -184,6 +184,7 @@ _說明:`` 表示 Ctrl+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. | diff --git a/pkg/app/daemon/daemon.go b/pkg/app/daemon/daemon.go index 6b29fd62d..df0e4bb49 100644 --- a/pkg/app/daemon/daemon.go +++ b/pkg/app/daemon/daemon.go @@ -199,6 +199,7 @@ func (self *ChangeTodoActionsInstruction) run(common *common.Common) error { return utils.TodoChange{ Hash: c.Hash, NewAction: c.NewAction, + Flag: c.Flag, } }) diff --git a/pkg/app/daemon/rebase.go b/pkg/app/daemon/rebase.go index e7cf1f57b..fdb58f23c 100644 --- a/pkg/app/daemon/rebase.go +++ b/pkg/app/daemon/rebase.go @@ -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 { diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index da4bcb7ff..8b79bd8cd 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -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) } @@ -371,10 +372,11 @@ func (self *CommitLoader) getRebasingCommits(hashPool *utils.StringPool, addConf continue } commits = utils.Prepend(commits, models.NewCommit(hashPool, models.NewCommitOpts{ - Hash: t.Commit, - Name: t.Msg, - Status: models.StatusRebasing, - Action: t.Command, + Hash: t.Commit, + Name: t.Msg, + Status: models.StatusRebasing, + Action: t.Command, + ActionFlag: t.Flag, })) } diff --git a/pkg/commands/git_commands/rebase.go b/pkg/commands/git_commands/rebase.go index 152c88bbc..97d48a1a0 100644 --- a/pkg/commands/git_commands/rebase.go +++ b/pkg/commands/git_commands/rebase.go @@ -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, } }) diff --git a/pkg/commands/models/commit.go b/pkg/commands/models/commit.go index 8dfec4d4b..137528ee6 100644 --- a/pkg/commands/models/commit.go +++ b/pkg/commands/models/commit.go @@ -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, diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index bcb5c2f6f..abf591801 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -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: "", diff --git a/pkg/gui/controllers/basic_commits_controller.go b/pkg/gui/controllers/basic_commits_controller.go index b3a5bf38c..be856a9e9 100644 --- a/pkg/gui/controllers/basic_commits_controller.go +++ b/pkg/gui/controllers/basic_commits_controller.go @@ -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()) diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 2c8932f33..42fb1135e 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -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{ - Title: self.c.Tr.Fixup, - Prompt: self.c.Tr.SureFixupThisCommit, - HandleConfirm: 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) - }) + return self.c.Menu(types.CreateMenuOptions{ + Title: self.c.Tr.Fixup, + 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 } diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go index a5799bcb3..67fa62ac8 100644 --- a/pkg/gui/presentation/commits.go +++ b/pkg/gui/presentation/commits.go @@ -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 := "" diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 970afd498..ce87693a2 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -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: \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", diff --git a/pkg/integration/tests/interactive_rebase/fixup_keep_message.go b/pkg/integration/tests/interactive_rebase/fixup_keep_message.go new file mode 100644 index 000000000..524066f92 --- /dev/null +++ b/pkg/integration/tests/interactive_rebase/fixup_keep_message.go @@ -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")) + }, +}) diff --git a/pkg/integration/tests/interactive_rebase/fixup_keep_message_rebase.go b/pkg/integration/tests/interactive_rebase/fixup_keep_message_rebase.go new file mode 100644 index 000000000..595968c17 --- /dev/null +++ b/pkg/integration/tests/interactive_rebase/fixup_keep_message_rebase.go @@ -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")) + }, +}) diff --git a/pkg/integration/tests/interactive_rebase/fixup_second_commit.go b/pkg/integration/tests/interactive_rebase/fixup_second_commit.go index c5eec4a82..33cc93215 100644 --- a/pkg/integration/tests/interactive_rebase/fixup_second_commit.go +++ b/pkg/integration/tests/interactive_rebase/fixup_second_commit.go @@ -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( diff --git a/pkg/integration/tests/interactive_rebase/outside_rebase_range_select.go b/pkg/integration/tests/interactive_rebase/outside_rebase_range_select.go index d30ae0d64..4aeb28b28 100644 --- a/pkg/integration/tests/interactive_rebase/outside_rebase_range_select.go +++ b/pkg/integration/tests/interactive_rebase/outside_rebase_range_select.go @@ -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( diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index faf35a601..4d9edaa70 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -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, diff --git a/pkg/utils/rebase_todo.go b/pkg/utils/rebase_todo.go index e2c9dc442..fe04cbc60 100644 --- a/pkg/utils/rebase_todo.go +++ b/pkg/utils/rebase_todo.go @@ -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 } } } diff --git a/schema-master/config.json b/schema-master/config.json index c371f14e9..0e880b066 100644 --- a/schema-master/config.json +++ b/schema-master/config.json @@ -946,6 +946,10 @@ "type": "string", "default": "f" }, + "setFixupMessage": { + "type": "string", + "default": "c" + }, "createFixupCommit": { "type": "string", "default": "F" diff --git a/schema/config.json b/schema/config.json index c371f14e9..0e880b066 100644 --- a/schema/config.json +++ b/schema/config.json @@ -946,6 +946,10 @@ "type": "string", "default": "f" }, + "setFixupMessage": { + "type": "string", + "default": "c" + }, "createFixupCommit": { "type": "string", "default": "F"