1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-01 00:54:58 +02:00

Fix resetting to a branch when a tag shares the same name, or vice versa (#4571)

- **PR Description**

Allows the reset menu to have a different name that is displayed, and a
fully qualified name that git will unambiguously know what it refers
about. We could totally squash this back down to 1 input, and display to
the user the _precise_ full ref name that we are resetting to, but I
think the context they are in (branches tab versus tag tab), means that
we don't need to do that, and can continue to just show the branch name
and the tag name to the end users.

Fixes https://github.com/jesseduffield/lazygit/issues/4569
This commit is contained in:
Stefan Haller
2025-06-04 20:48:32 +02:00
committed by GitHub
11 changed files with 179 additions and 14 deletions

View File

@ -96,19 +96,23 @@ func (self *RemoteLoader) getRemoteBranchesByRemoteName() (map[string][]*models.
cmdArgs := NewGitCmd("for-each-ref").
Arg(fmt.Sprintf("--sort=%s", sortOrder)).
Arg("--format=%(refname:short)").
Arg("--format=%(refname)").
Arg("refs/remotes").
ToArgv()
err := self.cmd.New(cmdArgs).DontLog().RunAndProcessLines(func(line string) (bool, error) {
line = strings.TrimSpace(line)
split := strings.SplitN(line, "/", 2)
if len(split) != 2 {
split := strings.SplitN(line, "/", 4)
if len(split) != 4 {
return false, nil
}
remoteName := split[2]
name := split[3]
if name == "HEAD" {
return false, nil
}
remoteName := split[0]
name := split[1]
_, ok := remoteBranchesByRemoteName[remoteName]
if !ok {

View File

@ -361,7 +361,7 @@ func (self *BasicCommitsController) newBranch(commit *models.Commit) error {
}
func (self *BasicCommitsController) createResetMenu(commit *models.Commit) error {
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Hash())
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Hash(), commit.Hash())
}
func (self *BasicCommitsController) checkout(commit *models.Commit) error {

View File

@ -326,7 +326,8 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
LabelColumns: []string{upstreamResetOptions},
OpensMenu: true,
OnPress: func() error {
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
// We only can invoke this when the remote branch is stored locally, so using the selectedBranch here is fine.
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream, selectedBranch.FullUpstreamRefName())
if err != nil {
return err
}
@ -686,7 +687,7 @@ func (self *BranchesController) createSortMenu() error {
}
func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error {
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.Name)
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.Name, selectedBranch.FullRefName())
}
func (self *BranchesController) rename(branch *models.Branch) error {

View File

@ -1144,7 +1144,7 @@ func (self *FilesController) stash() error {
}
func (self *FilesController) createResetToUpstreamMenu() error {
return self.c.Helpers().Refs.CreateGitResetMenu("@{upstream}")
return self.c.Helpers().Refs.CreateGitResetMenu("@{upstream}", "@{upstream}")
}
func (self *FilesController) handleToggleDirCollapsed() error {

View File

@ -231,7 +231,7 @@ func (self *RefsHelper) CreateSortOrderMenu(sortOptionsOrder []string, onSelecte
})
}
func (self *RefsHelper) CreateGitResetMenu(ref string) error {
func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
type strengthWithKey struct {
strength string
label string
@ -249,7 +249,7 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
return &types.MenuItem{
LabelColumns: []string{
row.label,
style.FgRed.Sprintf("reset --%s %s", row.strength, ref),
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
},
OnPress: func() error {
self.c.LogAction("Reset")
@ -261,7 +261,7 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
})
return self.c.Menu(types.CreateMenuOptions{
Title: fmt.Sprintf("%s %s", self.c.Tr.ResetTo, ref),
Title: fmt.Sprintf("%s %s", self.c.Tr.ResetTo, name),
Items: menuItems,
})
}

View File

@ -158,7 +158,7 @@ func (self *RemoteBranchesController) createSortMenu() error {
}
func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName())
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName(), selectedBranch.FullRefName())
}
func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.RemoteBranch) error {

View File

@ -302,7 +302,7 @@ func (self *TagsController) push(tag *models.Tag) error {
}
func (self *TagsController) createResetMenu(tag *models.Tag) error {
return self.c.Helpers().Refs.CreateGitResetMenu(tag.Name)
return self.c.Helpers().Refs.CreateGitResetMenu(tag.Name, tag.FullRefName())
}
func (self *TagsController) create() error {

View File

@ -0,0 +1,52 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var ResetToDuplicateNamedTag = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Hard reset to a branch when a tag shares the same name",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("current-branch")
shell.EmptyCommit("other-branch-tag commit")
shell.CreateLightweightTag("other-branch", "HEAD")
shell.EmptyCommit("other-branch commit")
shell.NewBranch("other-branch")
shell.Checkout("current-branch")
shell.EmptyCommit("current-branch commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().Lines(
Contains("current-branch commit"),
Contains("other-branch commit"),
Contains("other-branch-tag commit"),
)
t.Views().Branches().
Focus().
Lines(
Contains("current-branch").IsSelected(),
Contains("other-branch"),
).
SelectNextItem().
Press(keys.Commits.ViewResetOptions)
t.ExpectPopup().Menu().
Title(Contains("Reset to other-branch")).
Select(Contains("Hard reset")).
Confirm()
t.Views().Commits().
Lines(
Contains("other-branch commit"),
Contains("other-branch-tag commit"),
)
},
})

View File

@ -0,0 +1,57 @@
package branch
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var ResetToDuplicateNamedUpstream = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Hard reset the current branch to an upstream branch when there is a competing tag name",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
CloneIntoRemote("origin").
NewBranch("foo").
EmptyCommit("commit 1").
PushBranchAndSetUpstream("origin", "foo").
EmptyCommit("commit 2").
CreateLightweightTag("origin/foo", "HEAD")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().Lines(
Contains("commit 2"),
Contains("commit 1"),
)
t.Views().Tags().Focus().Lines(Contains("origin/foo"))
t.Views().Remotes().Focus().
Lines(Contains("origin")).
PressEnter()
t.Views().RemoteBranches().IsFocused().
Lines(Contains("foo")).
Press(keys.Commits.ViewResetOptions)
t.ExpectPopup().Menu().
Title(Contains("Reset to origin/foo")).
Select(Contains("Hard reset")).
Confirm()
t.Views().Commits().Lines(
Contains("commit 1"),
)
t.Views().Tags().Focus().
Lines(Contains("origin/foo")).
Press(keys.Commits.ViewResetOptions)
t.ExpectPopup().Menu().
Title(Contains("Reset to origin/foo")).
Select(Contains("Hard reset")).
Confirm()
t.Views().Commits().Lines(
Contains("commit 2"),
Contains("commit 1"),
)
},
})

View File

@ -0,0 +1,48 @@
package tag
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var ResetToDuplicateNamedBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Hard reset to a tag when a branch shares the same name",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("current-branch")
shell.EmptyCommit("other-branch-tag commit")
shell.CreateLightweightTag("other-branch", "HEAD")
shell.EmptyCommit("other-branch commit")
shell.NewBranch("other-branch")
shell.Checkout("current-branch")
shell.EmptyCommit("current-branch commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().Lines(
Contains("current-branch commit"),
Contains("other-branch commit"),
Contains("other-branch-tag commit"),
)
t.Views().Tags().
Focus().
Lines(
Contains("other-branch").IsSelected(),
).
Press(keys.Commits.ViewResetOptions)
t.ExpectPopup().Menu().
Title(Contains("Reset to other-branch")).
Select(Contains("Hard reset")).
Confirm()
t.Views().Commits().Lines(
Contains("other-branch-tag commit"),
)
},
})

View File

@ -71,6 +71,8 @@ var tests = []*components.IntegrationTest{
branch.RebaseToUpstream,
branch.Rename,
branch.Reset,
branch.ResetToDuplicateNamedTag,
branch.ResetToDuplicateNamedUpstream,
branch.ResetToUpstream,
branch.SelectCommitsOfCurrentBranch,
branch.SetUpstream,
@ -406,6 +408,7 @@ var tests = []*components.IntegrationTest{
tag.ForceTagAnnotated,
tag.ForceTagLightweight,
tag.Reset,
tag.ResetToDuplicateNamedBranch,
ui.Accordion,
ui.DisableSwitchTabWithPanelJumpKeys,
ui.EmptyMenu,