diff --git a/pkg/commands/git_commands/branch.go b/pkg/commands/git_commands/branch.go index 99229b12b05..ba0fcf8c8b0 100644 --- a/pkg/commands/git_commands/branch.go +++ b/pkg/commands/git_commands/branch.go @@ -284,3 +284,12 @@ func (self *BranchCommands) IsBranchMerged(branch *models.Branch, mainBranches * return stdout == "", nil } + +// Creates a Subtree from the selected branch +func (self *BranchCommands) CreateSubtree(remoteName string, branch string) error { + cmdArgs := NewGitCmd("subtree"). + Arg("add", fmt.Sprintf("--prefix=%s", remoteName), remoteName, branch). + ToArgv() + + return self.cmd.New(cmdArgs).Run() +} diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index b02a959f531..112a4fd9c0d 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -465,6 +465,7 @@ type KeybindingBranchesConfig struct { SetUpstream string `yaml:"setUpstream"` FetchRemote string `yaml:"fetchRemote"` SortOrder string `yaml:"sortOrder"` + CreateSubtree string `yaml:"createSubtree"` } type KeybindingWorktreesConfig struct { @@ -904,6 +905,7 @@ func GetDefaultConfig() *UserConfig { SetUpstream: "u", FetchRemote: "f", SortOrder: "s", + CreateSubtree: "S", }, Worktrees: KeybindingWorktreesConfig{ ViewWorktreeOptions: "w", diff --git a/pkg/gui/controllers/remote_branches_controller.go b/pkg/gui/controllers/remote_branches_controller.go index 772baf4fa8c..c04a60090b6 100644 --- a/pkg/gui/controllers/remote_branches_controller.go +++ b/pkg/gui/controllers/remote_branches_controller.go @@ -102,6 +102,14 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts) GetDisabledReason: self.require(self.singleItemSelected()), Description: self.c.Tr.OpenDiffTool, }, + { + Key: opts.GetKey(opts.Config.Branches.CreateSubtree), + Handler: self.withItem(self.createSubtree), + GetDisabledReason: self.require(self.singleItemSelected()), + Description: self.c.Tr.Subtree, + Tooltip: self.c.Tr.SubtreeToolTip, + DisplayOnScreen: true, + }, } } @@ -198,3 +206,20 @@ func (self *RemoteBranchesController) newLocalBranch(selectedBranch *models.Remo func (self *RemoteBranchesController) checkoutBranch(selectedBranch *models.RemoteBranch) error { return self.c.Helpers().Refs.CheckoutRemoteBranch(selectedBranch.FullName(), selectedBranch.Name) } + +func (self *RemoteBranchesController) createSubtree(branch *models.RemoteBranch) error { + self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.Subtree, + Prompt: "Create subtree from" + " '" + branch.Name + "'?", + HandleConfirm: func() error { + self.c.LogAction(self.c.Tr.Actions.CreateSubtree) + if err := self.c.Git().Branch.CreateSubtree(branch.RemoteName, branch.Name); err != nil { + return err + } + + return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}}) + }, + }) + + return nil +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index fa28130a94a..b009e44b0db 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -248,6 +248,7 @@ type TranslationSet struct { CopyPullRequestURL string NoBranchOnRemote string Fetch string + Subtree string FetchTooltip string NoAutomaticGitFetchTitle string NoAutomaticGitFetchBody string @@ -515,6 +516,7 @@ type TranslationSet struct { ForceTag string ForceTagPrompt string FetchRemoteTooltip string + SubtreeToolTip string FetchingRemoteStatus string CheckoutCommit string CheckoutCommitTooltip string @@ -918,6 +920,7 @@ type Actions struct { SetBranchUpstream string AddRemote string RemoveRemote string + CreateSubtree string UpdateRemote string ApplyPatch string Stash string @@ -1232,6 +1235,7 @@ func EnglishTranslationSet() *TranslationSet { CopyPullRequestURL: `Copy pull request URL to clipboard`, NoBranchOnRemote: `This branch doesn't exist on remote. You need to push it to remote first.`, Fetch: `Fetch`, + Subtree: "Subtree", FetchTooltip: "Fetch changes from remote.", NoAutomaticGitFetchTitle: `No automatic git fetch`, NoAutomaticGitFetchBody: `Lazygit can't use "git fetch" in a private repo; use 'f' in the files panel to run "git fetch" manually`, @@ -1508,6 +1512,7 @@ func EnglishTranslationSet() *TranslationSet { ForceTag: "Force Tag", ForceTagPrompt: "The tag '{{.tagName}}' exists already. Press {{.cancelKey}} to cancel, or {{.confirmKey}} to overwrite.", FetchRemoteTooltip: "Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches.", + SubtreeToolTip: "Create a subtree from the selected branch.", FetchingRemoteStatus: "Fetching remote", CheckoutCommit: "Checkout commit", CheckoutCommitTooltip: "Checkout the selected commit as a detached HEAD.",