Skip to content

Commit ac7de7e

Browse files
authored
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 #4569
2 parents 36de219 + 706891e commit ac7de7e

11 files changed

+179
-14
lines changed

pkg/commands/git_commands/remote_loader.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,23 @@ func (self *RemoteLoader) getRemoteBranchesByRemoteName() (map[string][]*models.
9696

9797
cmdArgs := NewGitCmd("for-each-ref").
9898
Arg(fmt.Sprintf("--sort=%s", sortOrder)).
99-
Arg("--format=%(refname:short)").
99+
Arg("--format=%(refname)").
100100
Arg("refs/remotes").
101101
ToArgv()
102102

103103
err := self.cmd.New(cmdArgs).DontLog().RunAndProcessLines(func(line string) (bool, error) {
104104
line = strings.TrimSpace(line)
105105

106-
split := strings.SplitN(line, "/", 2)
107-
if len(split) != 2 {
106+
split := strings.SplitN(line, "/", 4)
107+
if len(split) != 4 {
108+
return false, nil
109+
}
110+
remoteName := split[2]
111+
name := split[3]
112+
113+
if name == "HEAD" {
108114
return false, nil
109115
}
110-
remoteName := split[0]
111-
name := split[1]
112116

113117
_, ok := remoteBranchesByRemoteName[remoteName]
114118
if !ok {

pkg/gui/controllers/basic_commits_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ func (self *BasicCommitsController) newBranch(commit *models.Commit) error {
361361
}
362362

363363
func (self *BasicCommitsController) createResetMenu(commit *models.Commit) error {
364-
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Hash())
364+
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Hash(), commit.Hash())
365365
}
366366

367367
func (self *BasicCommitsController) checkout(commit *models.Commit) error {

pkg/gui/controllers/branches_controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
326326
LabelColumns: []string{upstreamResetOptions},
327327
OpensMenu: true,
328328
OnPress: func() error {
329-
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
329+
// We only can invoke this when the remote branch is stored locally, so using the selectedBranch here is fine.
330+
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream, selectedBranch.FullUpstreamRefName())
330331
if err != nil {
331332
return err
332333
}
@@ -686,7 +687,7 @@ func (self *BranchesController) createSortMenu() error {
686687
}
687688

688689
func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error {
689-
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.Name)
690+
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.Name, selectedBranch.FullRefName())
690691
}
691692

692693
func (self *BranchesController) rename(branch *models.Branch) error {

pkg/gui/controllers/files_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ func (self *FilesController) stash() error {
11441144
}
11451145

11461146
func (self *FilesController) createResetToUpstreamMenu() error {
1147-
return self.c.Helpers().Refs.CreateGitResetMenu("@{upstream}")
1147+
return self.c.Helpers().Refs.CreateGitResetMenu("@{upstream}", "@{upstream}")
11481148
}
11491149

11501150
func (self *FilesController) handleToggleDirCollapsed() error {

pkg/gui/controllers/helpers/refs_helper.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func (self *RefsHelper) CreateSortOrderMenu(sortOptionsOrder []string, onSelecte
231231
})
232232
}
233233

234-
func (self *RefsHelper) CreateGitResetMenu(ref string) error {
234+
func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
235235
type strengthWithKey struct {
236236
strength string
237237
label string
@@ -249,7 +249,7 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
249249
return &types.MenuItem{
250250
LabelColumns: []string{
251251
row.label,
252-
style.FgRed.Sprintf("reset --%s %s", row.strength, ref),
252+
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
253253
},
254254
OnPress: func() error {
255255
self.c.LogAction("Reset")
@@ -261,7 +261,7 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
261261
})
262262

263263
return self.c.Menu(types.CreateMenuOptions{
264-
Title: fmt.Sprintf("%s %s", self.c.Tr.ResetTo, ref),
264+
Title: fmt.Sprintf("%s %s", self.c.Tr.ResetTo, name),
265265
Items: menuItems,
266266
})
267267
}

pkg/gui/controllers/remote_branches_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (self *RemoteBranchesController) createSortMenu() error {
158158
}
159159

160160
func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error {
161-
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName())
161+
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName(), selectedBranch.FullRefName())
162162
}
163163

164164
func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.RemoteBranch) error {

pkg/gui/controllers/tags_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ func (self *TagsController) push(tag *models.Tag) error {
302302
}
303303

304304
func (self *TagsController) createResetMenu(tag *models.Tag) error {
305-
return self.c.Helpers().Refs.CreateGitResetMenu(tag.Name)
305+
return self.c.Helpers().Refs.CreateGitResetMenu(tag.Name, tag.FullRefName())
306306
}
307307

308308
func (self *TagsController) create() error {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package branch
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var ResetToDuplicateNamedTag = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Hard reset to a branch when a tag shares the same name",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {},
13+
SetupRepo: func(shell *Shell) {
14+
shell.NewBranch("current-branch")
15+
16+
shell.EmptyCommit("other-branch-tag commit")
17+
shell.CreateLightweightTag("other-branch", "HEAD")
18+
19+
shell.EmptyCommit("other-branch commit")
20+
shell.NewBranch("other-branch")
21+
22+
shell.Checkout("current-branch")
23+
shell.EmptyCommit("current-branch commit")
24+
},
25+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
26+
t.Views().Commits().Lines(
27+
Contains("current-branch commit"),
28+
Contains("other-branch commit"),
29+
Contains("other-branch-tag commit"),
30+
)
31+
32+
t.Views().Branches().
33+
Focus().
34+
Lines(
35+
Contains("current-branch").IsSelected(),
36+
Contains("other-branch"),
37+
).
38+
SelectNextItem().
39+
Press(keys.Commits.ViewResetOptions)
40+
41+
t.ExpectPopup().Menu().
42+
Title(Contains("Reset to other-branch")).
43+
Select(Contains("Hard reset")).
44+
Confirm()
45+
46+
t.Views().Commits().
47+
Lines(
48+
Contains("other-branch commit"),
49+
Contains("other-branch-tag commit"),
50+
)
51+
},
52+
})
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package branch
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var ResetToDuplicateNamedUpstream = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Hard reset the current branch to an upstream branch when there is a competing tag name",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {},
13+
SetupRepo: func(shell *Shell) {
14+
shell.
15+
CloneIntoRemote("origin").
16+
NewBranch("foo").
17+
EmptyCommit("commit 1").
18+
PushBranchAndSetUpstream("origin", "foo").
19+
EmptyCommit("commit 2").
20+
CreateLightweightTag("origin/foo", "HEAD")
21+
},
22+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
23+
t.Views().Commits().Lines(
24+
Contains("commit 2"),
25+
Contains("commit 1"),
26+
)
27+
t.Views().Tags().Focus().Lines(Contains("origin/foo"))
28+
29+
t.Views().Remotes().Focus().
30+
Lines(Contains("origin")).
31+
PressEnter()
32+
t.Views().RemoteBranches().IsFocused().
33+
Lines(Contains("foo")).
34+
Press(keys.Commits.ViewResetOptions)
35+
t.ExpectPopup().Menu().
36+
Title(Contains("Reset to origin/foo")).
37+
Select(Contains("Hard reset")).
38+
Confirm()
39+
40+
t.Views().Commits().Lines(
41+
Contains("commit 1"),
42+
)
43+
44+
t.Views().Tags().Focus().
45+
Lines(Contains("origin/foo")).
46+
Press(keys.Commits.ViewResetOptions)
47+
t.ExpectPopup().Menu().
48+
Title(Contains("Reset to origin/foo")).
49+
Select(Contains("Hard reset")).
50+
Confirm()
51+
52+
t.Views().Commits().Lines(
53+
Contains("commit 2"),
54+
Contains("commit 1"),
55+
)
56+
},
57+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package tag
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var ResetToDuplicateNamedBranch = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Hard reset to a tag when a branch shares the same name",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {},
13+
SetupRepo: func(shell *Shell) {
14+
shell.NewBranch("current-branch")
15+
16+
shell.EmptyCommit("other-branch-tag commit")
17+
shell.CreateLightweightTag("other-branch", "HEAD")
18+
19+
shell.EmptyCommit("other-branch commit")
20+
shell.NewBranch("other-branch")
21+
22+
shell.Checkout("current-branch")
23+
shell.EmptyCommit("current-branch commit")
24+
},
25+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
26+
t.Views().Commits().Lines(
27+
Contains("current-branch commit"),
28+
Contains("other-branch commit"),
29+
Contains("other-branch-tag commit"),
30+
)
31+
32+
t.Views().Tags().
33+
Focus().
34+
Lines(
35+
Contains("other-branch").IsSelected(),
36+
).
37+
Press(keys.Commits.ViewResetOptions)
38+
39+
t.ExpectPopup().Menu().
40+
Title(Contains("Reset to other-branch")).
41+
Select(Contains("Hard reset")).
42+
Confirm()
43+
44+
t.Views().Commits().Lines(
45+
Contains("other-branch-tag commit"),
46+
)
47+
},
48+
})

0 commit comments

Comments
 (0)