mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-11-12 15:53:33 -04:00
Use the squash merge message when committing a squash merge
After "Squash merge and leave uncommitted", the commit panel opens empty, or with the commit prefix of the branch. Users have to type a message for the squash merge themselves. "git commit" from the terminal suggests the message in SQUASH_MSG instead. Show the message in SQUASH_MSG in the commit panel, unless there is a preserved message. It takes precedence over the commit prefix, like the message of "Squash merge and commit" does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c7c514fa44
commit
09780de32e
@@ -73,6 +73,16 @@ func (self *StatusCommands) IsInSquashMerge() (bool, error) {
|
||||
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "SQUASH_MSG"))
|
||||
}
|
||||
|
||||
// SquashMergeMessage returns the message in SQUASH_MSG (see IsInSquashMerge), or
|
||||
// an empty string if there is no squash merge in progress
|
||||
func (self *StatusCommands) SquashMergeMessage() string {
|
||||
content, err := os.ReadFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "SQUASH_MSG"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(string(content))
|
||||
}
|
||||
|
||||
func (self *StatusCommands) IsInCherryPick() (bool, error) {
|
||||
hasCherryPickHead, err := self.hasCherryPickHead()
|
||||
if err != nil || hasCherryPickHead {
|
||||
|
||||
@@ -131,6 +131,10 @@ func (self *CommitMessageContext) GetInitialMessage() string {
|
||||
return self.viewModel.initialMessage
|
||||
}
|
||||
|
||||
func (self *CommitMessageContext) SetInitialMessage(message string) {
|
||||
self.viewModel.initialMessage = message
|
||||
}
|
||||
|
||||
func (self *CommitMessageContext) GetHistoryMessage() string {
|
||||
return self.viewModel.historyMessage
|
||||
}
|
||||
@@ -148,7 +152,6 @@ func (self *CommitMessageContext) SetPanelState(
|
||||
summaryTitle string,
|
||||
descriptionTitle string,
|
||||
preserveMessage bool,
|
||||
initialMessage string,
|
||||
onConfirm func(string, string) error,
|
||||
onSwitchToEditor func(string) error,
|
||||
forceSkipHooks bool,
|
||||
@@ -156,7 +159,6 @@ func (self *CommitMessageContext) SetPanelState(
|
||||
) {
|
||||
self.viewModel.selectedindex = index
|
||||
self.viewModel.preserveMessage = preserveMessage
|
||||
self.viewModel.initialMessage = initialMessage
|
||||
self.viewModel.onConfirm = onConfirm
|
||||
self.viewModel.onSwitchToEditor = onSwitchToEditor
|
||||
self.viewModel.forceSkipHooks = forceSkipHooks
|
||||
|
||||
@@ -143,10 +143,7 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp
|
||||
}
|
||||
|
||||
// When there's no explicit initial message but we're in a preservation
|
||||
// context, fall back to any previously preserved message. This is stored as
|
||||
// the "initial" value so the unchanged-message check on close still works
|
||||
// correctly (in particular, clearing the panel then escaping will notice
|
||||
// the difference and delete the preserved file).
|
||||
// context, fall back to any previously preserved message.
|
||||
initialMessage := opts.InitialMessage
|
||||
initialMessageIsPreserved := false
|
||||
if opts.PreserveMessage && initialMessage == "" {
|
||||
@@ -159,7 +156,6 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp
|
||||
opts.SummaryTitle,
|
||||
opts.DescriptionTitle,
|
||||
opts.PreserveMessage,
|
||||
initialMessage,
|
||||
onConfirm,
|
||||
opts.OnSwitchToEditor,
|
||||
opts.ForceSkipHooks,
|
||||
@@ -172,6 +168,14 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp
|
||||
self.SetMessageAndDescriptionInView(initialMessage)
|
||||
}
|
||||
|
||||
// PreserveCommitMessage compares the message in the panel with this when the
|
||||
// panel closes, so that it preserves the message only if the user changed it
|
||||
// (in particular, clearing the panel then escaping will notice the
|
||||
// difference and delete the preserved file). Take it from the panel, because
|
||||
// a message with a blank line after the summary comes out of the panel
|
||||
// without it.
|
||||
self.c.Contexts().CommitMessage.SetInitialMessage(self.JoinCommitMessageAndUnwrappedDescription())
|
||||
|
||||
self.c.Context().Push(self.c.Contexts().CommitMessage, types.OnFocusOpts{})
|
||||
}
|
||||
|
||||
|
||||
@@ -237,6 +237,9 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||
var initialMessage string
|
||||
preservedMessage := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()
|
||||
if preservedMessage == "" {
|
||||
initialMessage = self.c.Git().Status.SquashMergeMessage()
|
||||
}
|
||||
if preservedMessage == "" && initialMessage == "" {
|
||||
commitPrefixConfigs := self.commitPrefixConfigsForRepo()
|
||||
for _, commitPrefixConfig := range commitPrefixConfigs {
|
||||
prefixPattern := commitPrefixConfig.Pattern
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var CancelCommitDuringSquashMerge = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Open the commit panel during a squash merge started outside lazygit, and close it without changing git's message",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("one").
|
||||
NewBranch("feature-branch").
|
||||
CreateFileAndAdd("feature-file", "content").
|
||||
Commit("feature").
|
||||
Checkout("master").
|
||||
RunCommand([]string{"git", "merge", "--squash", "feature-branch"})
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
Lines(
|
||||
Equals("A feature-file"),
|
||||
).
|
||||
Press(keys.Files.CommitChanges)
|
||||
|
||||
t.ExpectPopup().CommitMessagePanel().
|
||||
InitialText(Equals("Squashed commit of the following:")).
|
||||
Cancel()
|
||||
|
||||
t.FileSystem().PathNotPresent(".git/LAZYGIT_PENDING_COMMIT")
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var CommitDuringSquashMerge = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit the changes of a squash merge that was left uncommitted, using the squash merge message",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Git.CommitPrefix = []config.CommitPrefixConfig{{Pattern: "^(\\w+)-branch$", Replace: "[$1] "}}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.NewBranch("original-branch").
|
||||
EmptyCommit("one").
|
||||
NewBranch("feature-branch").
|
||||
CreateFileAndAdd("feature-file", "content").
|
||||
Commit("feature").
|
||||
Checkout("original-branch")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("original-branch").IsSelected(),
|
||||
Contains("feature-branch"),
|
||||
).
|
||||
SelectNextItem().
|
||||
Press(keys.Branches.MergeIntoCurrentBranch)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Merge")).
|
||||
Select(Contains("Squash merge and leave uncommitted")).
|
||||
Confirm()
|
||||
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
Lines(
|
||||
Equals("A feature-file"),
|
||||
).
|
||||
Press(keys.Files.CommitChanges)
|
||||
|
||||
t.ExpectPopup().CommitMessagePanel().
|
||||
Title(Equals("Commit summary")).
|
||||
InitialText(Equals("Squash merge feature-branch into original-branch")).
|
||||
Confirm()
|
||||
|
||||
t.Views().Status().Content(Equals("repo → original-branch"))
|
||||
|
||||
t.Views().Commits().
|
||||
Lines(
|
||||
Contains("Squash merge feature-branch into original-branch"),
|
||||
Contains("one"),
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -137,12 +137,14 @@ var tests = []*components.IntegrationTest{
|
||||
commit.AmendWhenThereAreConflictsAndCancel,
|
||||
commit.AmendWhenThereAreConflictsAndContinue,
|
||||
commit.AutoWrapMessage,
|
||||
commit.CancelCommitDuringSquashMerge,
|
||||
commit.Checkout,
|
||||
commit.CheckoutFileFromCommit,
|
||||
commit.CheckoutFileFromRangeSelectionOfCommits,
|
||||
commit.CheckoutFileWithLocalModifications,
|
||||
commit.Commit,
|
||||
commit.CommitAllWithNestedRepository,
|
||||
commit.CommitDuringSquashMerge,
|
||||
commit.CommitMultiline,
|
||||
commit.CommitSkipHooks,
|
||||
commit.CommitSwitchToEditor,
|
||||
|
||||
Reference in New Issue
Block a user