1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-11-24 08:52:21 +02:00

Add command to squash all fixups in the current branch

To do that, change the "Apply fixup commits" command to show a menu with the two
choices "in current branch" and "above the selected commit"; we make "in current
branch" the default, as it's the more useful one most of the time, even though
it is a breaking change for those who are used to "shift-S enter" meaning
"squash above selected".
This commit is contained in:
Stefan Haller 2024-01-23 17:03:44 +01:00
parent 24e79a057c
commit b133318b40
14 changed files with 133 additions and 31 deletions

View File

@ -89,7 +89,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
| `` F `` | Create fixup commit | Create 'fixup!' commit for the selected commit. Later on, you can press `S` on this same commit to apply all above fixup commits. |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits above selected commit (autosquash). |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
| `` <c-j> `` | Move commit down one | |
| `` <c-k> `` | Move commit up one | |
| `` V `` | Paste (cherry-pick) | |

View File

@ -106,7 +106,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
| `` F `` | Create fixup commit | このコミットに対するfixupコミットを作成 |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits above selected commit (autosquash). |
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
| `` <c-j> `` | コミットを1つ下に移動 | |
| `` <c-k> `` | コミットを1つ上に移動 | |
| `` V `` | コミットを貼り付け (cherry-pick) | |

View File

@ -167,13 +167,13 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
},
{
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
Handler: self.withItem(self.squashAllAboveFixupCommits),
Handler: self.squashFixupCommits,
GetDisabledReason: self.require(
self.notMidRebase(self.c.Tr.AlreadyRebasing),
self.singleItemSelected(),
),
Description: self.c.Tr.SquashAboveCommits,
Tooltip: self.c.Tr.SquashAboveCommitsTooltip,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
@ -816,25 +816,62 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
})
}
func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Commit) error {
prompt := utils.ResolvePlaceholderString(
self.c.Tr.SureSquashAboveCommits,
map[string]string{"commit": commit.Sha},
)
return self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.SquashAboveCommits,
Prompt: prompt,
HandleConfirm: func() error {
return self.c.WithWaitingStatus(self.c.Tr.SquashingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.SquashAllAboveFixupCommits)
err := self.c.Git().Rebase.SquashAllAboveFixupCommits(commit)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
})
func (self *LocalCommitsController) squashFixupCommits() error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.SquashAboveCommits,
Items: []*types.MenuItem{
{
Label: self.c.Tr.SquashCommitsInCurrentBranch,
OnPress: self.squashAllFixupsInCurrentBranch,
DisabledReason: self.canFindCommitForSquashFixupsInCurrentBranch(),
Key: 'b',
Tooltip: self.c.Tr.SquashCommitsInCurrentBranchTooltip,
},
{
Label: self.c.Tr.SquashCommitsAboveSelectedCommit,
OnPress: self.withItem(self.squashAllFixupsAboveSelectedCommit),
DisabledReason: self.singleItemSelected()(),
Key: 'a',
Tooltip: self.c.Tr.SquashCommitsAboveSelectedTooltip,
},
},
})
}
func (self *LocalCommitsController) squashAllFixupsAboveSelectedCommit(commit *models.Commit) error {
return self.c.WithWaitingStatus(self.c.Tr.SquashingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.SquashAllAboveFixupCommits)
err := self.c.Git().Rebase.SquashAllAboveFixupCommits(commit)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
})
}
func (self *LocalCommitsController) squashAllFixupsInCurrentBranch() error {
commit, err := self.findCommitForSquashFixupsInCurrentBranch()
if err != nil {
return self.c.Error(err)
}
return self.c.WithWaitingStatus(self.c.Tr.SquashingStatus, func(gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.SquashAllAboveFixupCommits)
err := self.c.Git().Rebase.SquashAllAboveFixupCommits(commit)
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
})
}
func (self *LocalCommitsController) findCommitForSquashFixupsInCurrentBranch() (*models.Commit, error) {
commits := self.c.Model().Commits
_, index, ok := lo.FindIndexOf(commits, func(c *models.Commit) bool {
return c.IsMerge() || c.Status == models.StatusMerged
})
if !ok || index == 0 {
return nil, errors.New(self.c.Tr.CannotSquashCommitsInCurrentBranch)
}
return commits[index-1], nil
}
func (self *LocalCommitsController) createTag(commit *models.Commit) error {
return self.c.Helpers().Tags.OpenCreateTagPrompt(commit.Sha, func() {})
}
@ -1019,6 +1056,14 @@ func (self *LocalCommitsController) canFindCommitForQuickStart() *types.Disabled
return nil
}
func (self *LocalCommitsController) canFindCommitForSquashFixupsInCurrentBranch() *types.DisabledReason {
if _, err := self.findCommitForSquashFixupsInCurrentBranch(); err != nil {
return &types.DisabledReason{Text: err.Error()}
}
return nil
}
func (self *LocalCommitsController) canSquashOrFixup(_selectedCommits []*models.Commit, startIdx int, endIdx int) *types.DisabledReason {
if endIdx >= len(self.c.Model().Commits)-1 {
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}

View File

@ -254,7 +254,6 @@ func chineseTranslationSet() TranslationSet {
ViewResetOptions: `查看重置选项`,
CreateFixupCommit: `为此提交创建修正`,
SquashAboveCommitsTooltip: `压缩在所选提交之上的所有“fixup!”提交(自动压缩)`,
SureSquashAboveCommits: `您确定要压缩在 {{.commit}} 之上的所有“fixup!”提交吗?`,
CreateFixupCommitTooltip: `创建修正提交`,
SureCreateFixupCommit: `您确定要对 {{.commit}} 创建修正提交吗?`,
ExecuteCustomCommand: "执行自定义命令",

View File

@ -217,7 +217,6 @@ func dutchTranslationSet() TranslationSet {
HardReset: "Harde reset",
CreateFixupCommit: `Creëer fixup commit voor deze commit`,
SquashAboveCommitsTooltip: `Squash bovenstaande commits`,
SureSquashAboveCommits: `Weet je zeker dat je alles wil squash/fixup! voor de bovenstaand commits {{.commit}}?`,
CreateFixupCommitTooltip: `Creëer fixup commit`,
SureCreateFixupCommit: `Weet je zeker dat je een fixup wil maken! commit voor commit {{.commit}}?`,
ExecuteCustomCommand: "Voer aangepaste commando uit",

View File

@ -386,8 +386,12 @@ type TranslationSet struct {
CreateFixupCommitDescription string
CreateFixupCommitTooltip string
SquashAboveCommitsTooltip string
SquashCommitsAboveSelectedTooltip string
SquashCommitsInCurrentBranchTooltip string
SquashAboveCommits string
SureSquashAboveCommits string
SquashCommitsInCurrentBranch string
SquashCommitsAboveSelectedCommit string
CannotSquashCommitsInCurrentBranch string
SureCreateFixupCommit string
ExecuteCustomCommand string
ExecuteCustomCommandTooltip string
@ -1322,8 +1326,12 @@ func EnglishTranslationSet() TranslationSet {
CreateFixupCommitDescription: `Create fixup commit`,
CreateFixupCommitTooltip: "Create 'fixup!' commit for the selected commit. Later on, you can press `{{.squashAbove}}` on this same commit to apply all above fixup commits.",
SquashAboveCommits: "Apply fixup commits",
SquashAboveCommitsTooltip: `Squash all 'fixup!' commits above selected commit (autosquash).`,
SureSquashAboveCommits: `Are you sure you want to squash all fixup! commits above {{.commit}}?`,
SquashAboveCommitsTooltip: `Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash).`,
SquashCommitsAboveSelectedTooltip: `Squash all 'fixup!' commits above the selected commit (autosquash).`,
SquashCommitsInCurrentBranchTooltip: `Squash all 'fixup!' commits in the current branch (autosquash).`,
SquashCommitsInCurrentBranch: "In current branch",
SquashCommitsAboveSelectedCommit: "Above the selected commit",
CannotSquashCommitsInCurrentBranch: "Cannot squash commits in current branch: the HEAD commit is a merge commit or is present on the main branch.",
CreateFixupCommit: `Create fixup commit`,
SureCreateFixupCommit: `Are you sure you want to create a fixup! commit for commit {{.commit}}?`,
ExecuteCustomCommand: "Execute custom command",

View File

@ -263,7 +263,6 @@ func japaneseTranslationSet() TranslationSet {
CreateFixupCommitTooltip: `このコミットに対するfixupコミットを作成`,
// LcSquashAboveCommits: `squash all 'fixup!' commits above selected commit (autosquash)`,
// SquashAboveCommits: `Squash all 'fixup!' commits above selected commit (autosquash)`,
SureSquashAboveCommits: `{{.commit}}に対するすべての fixup! コミットをsquashします。よろしいですか?`,
CreateFixupCommit: `Fixupコミットを作成`,
SureCreateFixupCommit: `{{.commit}} に対する fixup! コミットを作成します。よろしいですか?`,
ExecuteCustomCommand: "カスタムコマンドを実行",

View File

@ -258,7 +258,6 @@ func koreanTranslationSet() TranslationSet {
ViewResetOptions: `View reset options`,
CreateFixupCommitTooltip: `Create fixup commit for this commit`,
SquashAboveCommitsTooltip: `Squash all 'fixup!' commits above selected commit (autosquash)`,
SureSquashAboveCommits: `Are you sure you want to squash all fixup! commits above {{.commit}}?`,
CreateFixupCommit: `Create fixup commit`,
SureCreateFixupCommit: `Are you sure you want to create a fixup! commit for commit {{.commit}}?`,
ExecuteCustomCommand: "Execute custom command",

View File

@ -180,7 +180,6 @@ func polishTranslationSet() TranslationSet {
ViewResetOptions: "Wyświetl opcje resetu",
CreateFixupCommitTooltip: "Utwórz commit naprawczy dla tego commita",
SquashAboveCommitsTooltip: `Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)`,
SureSquashAboveCommits: `Na pewno chcesz spłaszczyć wszystkie commity naprawcze powyżej {{.commit}}?`,
CreateFixupCommit: `Utwóż commit naprawczy`,
SureCreateFixupCommit: `Na pewno utworzyć commit naprawczy dla commita {{.commit}}?`,
ExecuteCustomCommand: "Wykonaj własną komendę",

View File

@ -314,7 +314,6 @@ func RussianTranslationSet() TranslationSet {
ViewResetOptions: `Просмотреть параметры сброса`,
CreateFixupCommitTooltip: `Создать fixup коммит для этого коммита`,
SquashAboveCommitsTooltip: `Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение)`,
SureSquashAboveCommits: `Вы уверены, что хотите объединить все fixup! коммиты выше {{.commit}}?`,
CreateFixupCommit: `Создать fixup коммит`,
SureCreateFixupCommit: `Вы уверены, что хотите создать fixup! коммит для коммита {{.commit}}?`,
ExecuteCustomCommand: "Выполнить пользовательскую команду",

View File

@ -341,7 +341,6 @@ func traditionalChineseTranslationSet() TranslationSet {
ViewResetOptions: "檢視重設選項",
CreateFixupCommitTooltip: "為此提交建立修復提交",
SquashAboveCommitsTooltip: "壓縮上方所有的“fixup!”提交 (自動壓縮)",
SureSquashAboveCommits: "你確定要壓縮{{.commit}}上方所有的fixup!提交嗎?",
CreateFixupCommit: "建立修復提交",
SureCreateFixupCommit: "你確定要為提交{{.commit}}建立fixup!提交嗎?",
ExecuteCustomCommand: "執行自訂命令",

View File

@ -33,9 +33,9 @@ var SquashFixupsAboveFirstCommit = NewIntegrationTest(NewIntegrationTestArgs{
NavigateToLine(Contains("commit 01").DoesNotContain("fixup!")).
Press(keys.Commits.SquashAboveCommits).
Tap(func() {
t.ExpectPopup().Confirmation().
t.ExpectPopup().Menu().
Title(Equals("Apply fixup commits")).
Content(Contains("Are you sure you want to squash all fixup! commits above")).
Select(Contains("Above the selected commit")).
Confirm()
}).
Lines(

View File

@ -0,0 +1,55 @@
package interactive_rebase
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var SquashFixupsInCurrentBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Squashes all fixups in the current branch.",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
CreateFileAndAdd("file1", "file1").
Commit("master commit").
NewBranch("branch").
// Test the pathological case that the first commit of a branch is a
// fixup for the last master commit below it. We _don't_ want this to
// be squashed.
UpdateFileAndAdd("file1", "changed file1").
Commit("fixup! master commit").
CreateNCommits(2).
CreateFileAndAdd("fixup-file", "fixup content").
Commit("fixup! commit 01")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("fixup! commit 01"),
Contains("commit 02"),
Contains("commit 01"),
Contains("fixup! master commit"),
Contains("master commit"),
).
Press(keys.Commits.SquashAboveCommits).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Apply fixup commits")).
Select(Contains("In current branch")).
Confirm()
}).
Lines(
Contains("commit 02"),
Contains("commit 01"),
Contains("fixup! master commit"),
Contains("master commit"),
).
NavigateToLine(Contains("commit 01"))
t.Views().Main().
Content(Contains("fixup content"))
},
})

View File

@ -183,6 +183,7 @@ var tests = []*components.IntegrationTest{
interactive_rebase.SquashDownFirstCommit,
interactive_rebase.SquashDownSecondCommit,
interactive_rebase.SquashFixupsAboveFirstCommit,
interactive_rebase.SquashFixupsInCurrentBranch,
interactive_rebase.SwapInRebaseWithConflict,
interactive_rebase.SwapInRebaseWithConflictAndEdit,
interactive_rebase.SwapWithConflict,