diff --git a/docs/Config.md b/docs/Config.md
index 6a9be62e9..34ca5df4e 100644
--- a/docs/Config.md
+++ b/docs/Config.md
@@ -203,6 +203,7 @@ keybinding:
mergeIntoCurrentBranch: 'M'
viewGitFlowOptions: 'i'
fastForward: 'f' # fast-forward this branch from its upstream
+ createTag: 'T'
pushTag: 'P'
setUpstream: 'u' # set as upstream of checked-out branch
fetchRemote: 'f'
diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md
index 565698bf8..067ee61a3 100644
--- a/docs/keybindings/Keybindings_en.md
+++ b/docs/keybindings/Keybindings_en.md
@@ -131,6 +131,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: rebase checked-out branch onto this branch
M: merge into currently checked out branch
f: fast-forward this branch from its upstream
+ T: create tag
g: view reset options
R: rename branch
u: set/unset upstream
diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md
index e8de2ca3c..bbcd1eabe 100644
--- a/docs/keybindings/Keybindings_ja.md
+++ b/docs/keybindings/Keybindings_ja.md
@@ -191,6 +191,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: rebase checked-out branch onto this branch
M: 現在のブランチにマージ
f: fast-forward this branch from its upstream
+ T: タグを作成
g: view reset options
R: ブランチ名を変更
u: set/unset upstream
diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md
index 9eea1d343..325661e03 100644
--- a/docs/keybindings/Keybindings_ko.md
+++ b/docs/keybindings/Keybindings_ko.md
@@ -158,6 +158,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: 체크아웃된 브랜치를 이 브랜치에 리베이스
M: 현재 브랜치에 병합
f: fast-forward this branch from its upstream
+ T: 태그를 생성
g: view reset options
R: 브랜치 이름 변경
u: set/unset upstream
diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md
index b1e3a83b9..6c5360c05 100644
--- a/docs/keybindings/Keybindings_nl.md
+++ b/docs/keybindings/Keybindings_nl.md
@@ -84,6 +84,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: rebase branch
M: merge in met huidige checked out branch
f: fast-forward deze branch vanaf zijn upstream
+ T: creëer tag
g: bekijk reset opties
R: hernoem branch
u: set/unset upstream
diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md
index 232034173..0d2ac0be1 100644
--- a/docs/keybindings/Keybindings_pl.md
+++ b/docs/keybindings/Keybindings_pl.md
@@ -91,6 +91,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: zmiana bazy gałęzi
M: scal do obecnej gałęzi
f: fast-forward this branch from its upstream
+ T: create tag
g: wyświetl opcje resetu
R: rename branch
u: set/unset upstream
diff --git a/docs/keybindings/Keybindings_zh.md b/docs/keybindings/Keybindings_zh.md
index 029c82434..e6ae31bbd 100644
--- a/docs/keybindings/Keybindings_zh.md
+++ b/docs/keybindings/Keybindings_zh.md
@@ -73,6 +73,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
r: 将已检出的分支变基到该分支
M: 合并到当前检出的分支
f: 从上游快进此分支
+ T: 创建标签
g: 查看重置选项
R: 重命名分支
u: set/unset upstream
diff --git a/pkg/commands/git_commands/tag.go b/pkg/commands/git_commands/tag.go
index 5abad0dc5..8b5a69967 100644
--- a/pkg/commands/git_commands/tag.go
+++ b/pkg/commands/git_commands/tag.go
@@ -14,12 +14,20 @@ func NewTagCommands(gitCommon *GitCommon) *TagCommands {
}
}
-func (self *TagCommands) CreateLightweight(tagName string, commitSha string) error {
- return self.cmd.New(fmt.Sprintf("git tag -- %s %s", self.cmd.Quote(tagName), commitSha)).Run()
+func (self *TagCommands) CreateLightweight(tagName string, ref string) error {
+ if len(ref) > 0 {
+ return self.cmd.New(fmt.Sprintf("git tag -- %s %s", self.cmd.Quote(tagName), self.cmd.Quote(ref))).Run()
+ } else {
+ return self.cmd.New(fmt.Sprintf("git tag -- %s", self.cmd.Quote(tagName))).Run()
+ }
}
-func (self *TagCommands) CreateAnnotated(tagName, commitSha, msg string) error {
- return self.cmd.New(fmt.Sprintf("git tag %s %s -m %s", tagName, commitSha, self.cmd.Quote(msg))).Run()
+func (self *TagCommands) CreateAnnotated(tagName, ref, msg string) error {
+ if len(ref) > 0 {
+ return self.cmd.New(fmt.Sprintf("git tag %s %s -m %s", self.cmd.Quote(tagName), self.cmd.Quote(ref), self.cmd.Quote(msg))).Run()
+ } else {
+ return self.cmd.New(fmt.Sprintf("git tag %s -m %s", self.cmd.Quote(tagName), self.cmd.Quote(msg))).Run()
+ }
}
func (self *TagCommands) Delete(tagName string) error {
diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go
index 6aea0dc64..d9e736149 100644
--- a/pkg/config/user_config.go
+++ b/pkg/config/user_config.go
@@ -235,6 +235,7 @@ type KeybindingBranchesConfig struct {
MergeIntoCurrentBranch string `yaml:"mergeIntoCurrentBranch"`
ViewGitFlowOptions string `yaml:"viewGitFlowOptions"`
FastForward string `yaml:"fastForward"`
+ CreateTag string `yaml:"createTag"`
PushTag string `yaml:"pushTag"`
SetUpstream string `yaml:"setUpstream"`
FetchRemote string `yaml:"fetchRemote"`
@@ -521,6 +522,7 @@ func GetDefaultConfig() *UserConfig {
MergeIntoCurrentBranch: "M",
ViewGitFlowOptions: "i",
FastForward: "f",
+ CreateTag: "T",
PushTag: "P",
SetUpstream: "u",
FetchRemote: "f",
diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go
index 9222492d7..d5564ec95 100644
--- a/pkg/gui/controllers/branches_controller.go
+++ b/pkg/gui/controllers/branches_controller.go
@@ -86,6 +86,11 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
Handler: self.checkSelectedAndReal(self.fastForward),
Description: self.c.Tr.FastForward,
},
+ {
+ Key: opts.GetKey(opts.Config.Branches.CreateTag),
+ Handler: self.checkSelected(self.createTag),
+ Description: self.c.Tr.LcCreateTag,
+ },
{
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.checkSelected(self.createResetMenu),
@@ -363,6 +368,10 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
})
}
+func (self *BranchesController) createTag(branch *models.Branch) error {
+ return self.helpers.Tags.CreateTagMenu(branch.FullRefName(), func() {})
+}
+
func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error {
return self.helpers.Refs.CreateGitResetMenu(selectedBranch.Name)
}
diff --git a/pkg/gui/controllers/helpers/tags_helper.go b/pkg/gui/controllers/helpers/tags_helper.go
index 4683ffd0d..a2f2e9c77 100644
--- a/pkg/gui/controllers/helpers/tags_helper.go
+++ b/pkg/gui/controllers/helpers/tags_helper.go
@@ -21,20 +21,20 @@ func NewTagsHelper(c *types.HelperCommon, git *commands.GitCommand) *TagsHelper
}
}
-func (self *TagsHelper) CreateTagMenu(commitSha string, onCreate func()) error {
+func (self *TagsHelper) CreateTagMenu(ref string, onCreate func()) error {
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.TagMenuTitle,
Items: []*types.MenuItem{
{
Label: self.c.Tr.LcLightweightTag,
OnPress: func() error {
- return self.handleCreateLightweightTag(commitSha, onCreate)
+ return self.handleCreateLightweightTag(ref, onCreate)
},
},
{
Label: self.c.Tr.LcAnnotatedTag,
OnPress: func() error {
- return self.handleCreateAnnotatedTag(commitSha, onCreate)
+ return self.handleCreateAnnotatedTag(ref, onCreate)
},
},
},
@@ -48,7 +48,7 @@ func (self *TagsHelper) afterTagCreate(onCreate func()) error {
})
}
-func (self *TagsHelper) handleCreateAnnotatedTag(commitSha string, onCreate func()) error {
+func (self *TagsHelper) handleCreateAnnotatedTag(ref string, onCreate func()) error {
return self.c.Prompt(types.PromptOpts{
Title: self.c.Tr.TagNameTitle,
HandleConfirm: func(tagName string) error {
@@ -56,7 +56,7 @@ func (self *TagsHelper) handleCreateAnnotatedTag(commitSha string, onCreate func
Title: self.c.Tr.TagMessageTitle,
HandleConfirm: func(msg string) error {
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
- if err := self.git.Tag.CreateAnnotated(tagName, commitSha, msg); err != nil {
+ if err := self.git.Tag.CreateAnnotated(tagName, ref, msg); err != nil {
return self.c.Error(err)
}
return self.afterTagCreate(onCreate)
@@ -66,12 +66,12 @@ func (self *TagsHelper) handleCreateAnnotatedTag(commitSha string, onCreate func
})
}
-func (self *TagsHelper) handleCreateLightweightTag(commitSha string, onCreate func()) error {
+func (self *TagsHelper) handleCreateLightweightTag(ref string, onCreate func()) error {
return self.c.Prompt(types.PromptOpts{
Title: self.c.Tr.TagNameTitle,
HandleConfirm: func(tagName string) error {
self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag)
- if err := self.git.Tag.CreateLightweight(tagName, commitSha); err != nil {
+ if err := self.git.Tag.CreateLightweight(tagName, ref); err != nil {
return self.c.Error(err)
}
return self.afterTagCreate(onCreate)
diff --git a/pkg/integration/components/git.go b/pkg/integration/components/git.go
index b9b3dcc46..6f4d80f1a 100644
--- a/pkg/integration/components/git.go
+++ b/pkg/integration/components/git.go
@@ -14,6 +14,10 @@ func (self *Git) CurrentBranchName(expectedName string) *Git {
return self.assert("git rev-parse --abbrev-ref HEAD", expectedName)
}
+func (self *Git) TagNamesAt(ref string, expectedNames []string) *Git {
+ return self.assert(fmt.Sprintf(`git tag --sort=v:refname --points-at "%s"`, ref), strings.Join(expectedNames, "\n"))
+}
+
func (self *Git) assert(cmdStr string, expected string) *Git {
self.assertWithRetries(func() (bool, string) {
output, err := self.shell.runCommandWithOutput(cmdStr)
diff --git a/pkg/integration/tests/branch/create_tag.go b/pkg/integration/tests/branch/create_tag.go
new file mode 100644
index 000000000..6f4ec0baf
--- /dev/null
+++ b/pkg/integration/tests/branch/create_tag.go
@@ -0,0 +1,47 @@
+package branch
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var CreateTag = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Create a new tag on branch",
+ ExtraCmdArgs: "",
+ Skip: false,
+ SetupConfig: func(config *config.AppConfig) {},
+ SetupRepo: func(shell *Shell) {
+ shell.
+ CreateNCommits(10).
+ NewBranch("new-branch").
+ EmptyCommit("new commit")
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.Views().Branches().
+ Focus().
+ Lines(
+ MatchesRegexp(`\*\s*new-branch`).IsSelected(),
+ MatchesRegexp(`master`),
+ ).
+ SelectNextItem().
+ Press(keys.Branches.CreateTag)
+
+ t.ExpectPopup().Menu().
+ Title(Equals("Create tag")).
+ Confirm()
+
+ t.ExpectPopup().Prompt().
+ Title(Equals("Tag name:")).
+ Type("new-tag").
+ Confirm()
+
+ t.Views().Tags().Focus().
+ Lines(
+ MatchesRegexp(`new-tag`).IsSelected(),
+ )
+
+ t.Git().
+ TagNamesAt("HEAD", []string{}).
+ TagNamesAt("master", []string{"new-tag"})
+ },
+})
diff --git a/pkg/integration/tests/tests_gen.go b/pkg/integration/tests/tests_gen.go
index 2be0b902c..5d831900e 100644
--- a/pkg/integration/tests/tests_gen.go
+++ b/pkg/integration/tests/tests_gen.go
@@ -27,6 +27,7 @@ var tests = []*components.IntegrationTest{
bisect.Basic,
bisect.FromOtherBranch,
branch.CheckoutByName,
+ branch.CreateTag,
branch.Delete,
branch.DetachedHead,
branch.OpenWithCliArg,