diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2024-06-01 08:15:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-01 08:15:35 +0200 |
commit | c5baa5da3ad84e7892d6720e54a95460d2f85ebd (patch) | |
tree | eff53fd6a2cc9582e0c85c00a861949982ea01a5 /pkg | |
parent | ab797fe986e1fd3acedefde4ef286cddc5046b49 (diff) | |
parent | 3284d69886250576b0b1799a0e691fd7bfaba655 (diff) |
Fix pushing to branch when upstream not stored locally (#3619)
- **PR Description**
This fixes three different problems; two were recent regressions, one
has never worked.
1. For branches whose remote is not stored locally, don't ask to force
push right away. Try a normal push first. This broke with #3528.
2. For branches whose remote is not stored locally (but only for those),
if the server rejects the update, ask to force push. This broke with
#3387.
3. When force-pushing a branch whose remote is not stored locally, use
`--force` instead of `--force-with-lease`; otherwise the push would
always fail with a "stale info" error. This has never worked.
Fixes #3588.
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/commands/git_commands/sync.go | 4 | ||||
-rw-r--r-- | pkg/commands/git_commands/sync_test.go | 22 | ||||
-rw-r--r-- | pkg/commands/models/branch.go | 2 | ||||
-rw-r--r-- | pkg/gui/controllers/sync_controller.go | 34 | ||||
-rw-r--r-- | pkg/i18n/chinese.go | 635 | ||||
-rw-r--r-- | pkg/i18n/english.go | 2 | ||||
-rw-r--r-- | pkg/i18n/korean.go | 529 | ||||
-rw-r--r-- | pkg/i18n/polish.go | 1 | ||||
-rw-r--r-- | pkg/i18n/russian.go | 767 | ||||
-rw-r--r-- | pkg/i18n/traditional_chinese.go | 767 | ||||
-rw-r--r-- | pkg/integration/tests/sync/force_push_remote_branch_not_stored_locally.go | 81 | ||||
-rw-r--r-- | pkg/integration/tests/test_list.go | 1 |
12 files changed, 1485 insertions, 1360 deletions
diff --git a/pkg/commands/git_commands/sync.go b/pkg/commands/git_commands/sync.go index 4ab1f336b..1c93fc260 100644 --- a/pkg/commands/git_commands/sync.go +++ b/pkg/commands/git_commands/sync.go @@ -19,6 +19,7 @@ func NewSyncCommands(gitCommon *GitCommon) *SyncCommands { // Push pushes to a branch type PushOpts struct { Force bool + ForceWithLease bool UpstreamRemote string UpstreamBranch string SetUpstream bool @@ -30,7 +31,8 @@ func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (oscommands } cmdArgs := NewGitCmd("push"). - ArgIf(opts.Force, "--force-with-lease"). + ArgIf(opts.Force, "--force"). + ArgIf(opts.ForceWithLease, "--force-with-lease"). ArgIf(opts.SetUpstream, "--set-upstream"). ArgIf(opts.UpstreamRemote != "", opts.UpstreamRemote). ArgIf(opts.UpstreamBranch != "", opts.UpstreamBranch). diff --git a/pkg/commands/git_commands/sync_test.go b/pkg/commands/git_commands/sync_test.go index f5f281e14..6ff8da840 100644 --- a/pkg/commands/git_commands/sync_test.go +++ b/pkg/commands/git_commands/sync_test.go @@ -18,24 +18,32 @@ func TestSyncPush(t *testing.T) { scenarios := []scenario{ { testName: "Push with force disabled", - opts: PushOpts{Force: false}, + opts: PushOpts{ForceWithLease: false}, test: func(cmdObj oscommands.ICmdObj, err error) { assert.Equal(t, cmdObj.Args(), []string{"git", "push"}) assert.NoError(t, err) }, }, { + testName: "Push with force-with-lease enabled", + opts: PushOpts{ForceWithLease: true}, + test: func(cmdObj oscommands.ICmdObj, err error) { + assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease"}) + assert.NoError(t, err) + }, + }, + { testName: "Push with force enabled", opts: PushOpts{Force: true}, test: func(cmdObj oscommands.ICmdObj, err error) { - assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease"}) + assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force"}) assert.NoError(t, err) }, }, { testName: "Push with force disabled, upstream supplied", opts: PushOpts{ - Force: false, + ForceWithLease: false, UpstreamRemote: "origin", UpstreamBranch: "master", }, @@ -47,7 +55,7 @@ func TestSyncPush(t *testing.T) { { testName: "Push with force disabled, setting upstream", opts: PushOpts{ - Force: false, + ForceWithLease: false, UpstreamRemote: "origin", UpstreamBranch: "master", SetUpstream: true, @@ -58,9 +66,9 @@ func TestSyncPush(t *testing.T) { }, }, { - testName: "Push with force enabled, setting upstream", + testName: "Push with force-with-lease enabled, setting upstream", opts: PushOpts{ - Force: true, + ForceWithLease: true, UpstreamRemote: "origin", UpstreamBranch: "master", SetUpstream: true, @@ -73,7 +81,7 @@ func TestSyncPush(t *testing.T) { { testName: "Push with remote branch but no origin", opts: PushOpts{ - Force: true, + ForceWithLease: true, UpstreamRemote: "", UpstreamBranch: "master", SetUpstream: true, diff --git a/pkg/commands/models/branch.go b/pkg/commands/models/branch.go index 25d806fca..5a34ba5e8 100644 --- a/pkg/commands/models/branch.go +++ b/pkg/commands/models/branch.go @@ -104,7 +104,7 @@ func (b *Branch) IsBehindForPull() bool { } func (b *Branch) IsBehindForPush() bool { - return b.BehindForPush != "" && b.BehindForPush != "0" + return b.RemoteBranchStoredLocally() && b.BehindForPush != "0" } // for when we're in a detached head state diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index 7d7ca9eed..8c7334031 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -89,7 +89,7 @@ func (self *SyncController) branchCheckedOut(f func(*models.Branch) error) func( func (self *SyncController) push(currentBranch *models.Branch) error { // if we are behind our upstream branch we'll ask if the user wants to force push if currentBranch.IsTrackingRemote() { - opts := pushOpts{} + opts := pushOpts{remoteBranchStoredLocally: currentBranch.RemoteBranchStoredLocally()} if currentBranch.IsBehindForPush() { return self.requestToForcePush(currentBranch, opts) } else { @@ -180,9 +180,16 @@ func (self *SyncController) pullWithLock(task gocui.Task, opts PullFilesOptions) type pushOpts struct { force bool + forceWithLease bool upstreamRemote string upstreamBranch string setUpstream bool + + // If this is false, we can't tell ahead of time whether a force-push will + // be necessary, so we start with a normal push and offer to force-push if + // the server rejected. If this is true, we don't offer to force-push if the + // server rejected, but rather ask the user to fetch. + remoteBranchStoredLocally bool } func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts) error { @@ -192,13 +199,32 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts) task, git_commands.PushOpts{ Force: opts.force, + ForceWithLease: opts.forceWithLease, UpstreamRemote: opts.upstreamRemote, UpstreamBranch: opts.upstreamBranch, SetUpstream: opts.setUpstream, }) if err != nil { - if strings.Contains(err.Error(), "Updates were rejected") { - return errors.New(self.c.Tr.UpdatesRejected) + if !opts.force && !opts.forceWithLease && strings.Contains(err.Error(), "Updates were rejected") { + if opts.remoteBranchStoredLocally { + return errors.New(self.c.Tr.UpdatesRejected) + } + + forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing + if forcePushDisabled { + return errors.New(self.c.Tr.UpdatesRejectedAndForcePushDisabled) + } + _ = self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.ForcePush, + Prompt: self.forcePushPrompt(), + HandleConfirm: func() error { + newOpts := opts + newOpts.force = true + + return self.pushAux(currentBranch, newOpts) + }, + }) + return nil } return err } @@ -216,7 +242,7 @@ func (self *SyncController) requestToForcePush(currentBranch *models.Branch, opt Title: self.c.Tr.ForcePush, Prompt: self.forcePushPrompt(), HandleConfirm: func() error { - opts.force = true + opts.forceWithLease = true return self.pushAux(currentBranch, opts) }, }) diff --git a/pkg/i18n/chinese.go b/pkg/i18n/chinese.go index 002143b28..f8ec9720c 100644 --- a/pkg/i18n/chinese.go +++ b/pkg/i18n/chinese.go @@ -35,323 +35,324 @@ const chineseIntroPopupMessage = ` // exporting this so we can use it in tests func chineseTranslationSet() TranslationSet { return TranslationSet{ - NotEnoughSpace: "没有足够的空间来渲染面板", - DiffTitle: "差异", - FilesTitle: "文件", - BranchesTitle: "分支", - CommitsTitle: "提交", - StashTitle: "贮藏", - UnstagedChanges: `未暂存更改`, - StagedChanges: `已暂存更改`, - MainTitle: "主要", - StagingTitle: "正在暂存", - MergingTitle: "正在合并", - NormalTitle: "正常", - CommitSummary: "提交信息", - CredentialsUsername: "用户名", - CredentialsPassword: "密码", - CredentialsPassphrase: "输入 SSH 密钥的密码", - PassUnameWrong: "密码 和/或 用户名错误", - Commit: "提交更改", - AmendLastCommit: "修补最后一次提交", - AmendLastCommitTitle: "修补最后一次提交", - SureToAmend: "您确定要修补上一次提交吗?之后您可以从提交面板更改提交消息。", - NoCommitToAmend: "没有需要提交的修补。", - CommitChangesWithEditor: "提交更改(使用编辑器编辑提交信息)", - StatusTitle: "状态", - Menu: "菜单", - Execute: "执行", - Stage: "切换暂存状态", - ToggleStagedAll: "切换所有文件的暂存状态", - ToggleTreeView: "切换文件树视图", - OpenMergeTool: "打开外部合并工具 (git mergetool)", - Refresh: "刷新", - Push: "推送", - Pull: "拉取", - Scroll: "滚动", - MergeConflictsTitle: "合并冲突", - Checkout: "检出", - NoChangedFiles: "没有更改过文件", - SoftReset: "软重置", - AlreadyCheckedOutBranch: "您已经检出至此分支", - SureForceCheckout: "您确定要强制检出吗?您将丢失所有本地更改", - ForceCheckoutBranch: "强制检出分支", - BranchName: "分支名称", - NewBranchNameBranchOff: "新分支名称(基于 {{.branchName}})", - CantDeleteCheckOutBranch: "您不能删除已检出的分支!", - ForceDeleteBranchMessage: "{{.selectedBranchName}} 还没有被完全合并。您确定要删除它吗?", - RebaseBranch: "将已检出的分支变基到该分支", - CantRebaseOntoSelf: "您不能将分支变基到其自身", - CantMergeBranchIntoItself: "您不能将分支合并到其自身", - ForceCheckout: "强制检出", - CheckoutByName: "按名称检出", - NewBranch: "新分支", - NoBranchesThisRepo: "此仓库中没有分支", - CommitWithoutMessageErr: "您必须编写提交消息才能进行提交", - CloseCancel: "关闭", - Confirm: "确认", - Close: "关闭", - Quit: "退出", - NoCommitsThisBranch: "该分支没有提交", - CannotSquashOrFixupFirstCommit: "There's no commit below to squash into", - Fixup: "修正(fixup)", - SureFixupThisCommit: "您确定要“修正”此提交吗?它将合并到下面的提交中", - SureSquashThisCommit: "您确定要将这个提交压缩到下面的提交中吗?", - Squash: "压缩", - PickCommitTooltip: "选择提交(变基过程中)", - RevertCommit: "还原提交", - Reword: "改写提交", - DropCommit: "删除提交", - MoveDownCommit: "下移提交", - MoveUpCommit: "上移提交", - EditCommitTooltip: "编辑提交", - AmendCommitTooltip: "用已暂存的更改来修补提交", - RewordCommitEditor: "使用编辑器重命名提交", - Error: "错误", - PickHunk: "选中区块", - PickAllHunks: "选中所有区块", - Undo: "撤销", - UndoReflog: "(通过 reflog)撤销「实验功能」", - RedoReflog: "(通过 reflog)重做「实验功能」", - Pop: "应用并删除", - Drop: "删除", - Apply: "应用", - NoStashEntries: "没有贮藏条目", - StashDrop: "删除贮藏", - SureDropStashEntry: "您确定要删除此贮藏条目吗?", - StashPop: "应用并删除贮藏", - SurePopStashEntry: "您确定要应用并删除此贮藏条目吗?", - StashApply: "应用贮藏", - SureApplyStashEntry: "您确定要应用此贮藏条目?", - NoTrackedStagedFilesStash: "没有可以贮藏的已跟踪/暂存文件", - StashChanges: "贮藏更改", - RenameStash: "Rename stash", - RenameStashPrompt: "Rename stash: {{.stashName}}", - OpenConfig: "打开配置文件", - EditConfig: "编辑配置文件", - ForcePush: "强制推送", - ForcePushPrompt: "您的分支已与远程分支不同。按‘esc’取消,或‘enter’强制推送.", - ForcePushDisabled: "您的分支已与远程分支不同, 并且您已经禁用了强行推送", - CheckForUpdate: "检查更新", - CheckingForUpdates: "正在检查更新…", - OnLatestVersionErr: "已是最新版本", - MajorVersionErr: "新版本 ({{.newVersion}}) 与当前版本 ({{.currentVersion}}) 相比,具有非向后兼容的更改", - CouldNotFindBinaryErr: "在 {{.url}} 处找不到任何二进制文件", - MergeToolTitle: "合并工具", - MergeToolPrompt: "确定要打开 `git mergetool` 吗?", - IntroPopupMessage: chineseIntroPopupMessage, - GitconfigParseErr: `由于存在未加引号的'\'字符,因此 Gogit 无法解析您的 gitconfig 文件。删除它们应该可以解决问题。`, - EditFile: `编辑文件`, - OpenFile: `打开文件`, - IgnoreFile: `添加到 .gitignore`, - RefreshFiles: `刷新文件`, - Merge: `合并到当前检出的分支`, - ConfirmQuit: `您确定要退出吗?`, - SwitchRepo: `切换到最近的仓库`, - AllBranchesLogGraph: `显示所有分支的日志`, - UnsupportedGitService: `不支持的 git 服务`, - CreatePullRequest: `创建抓取请求`, - CopyPullRequestURL: `将抓取请求 URL 复制到剪贴板`, - NoBranchOnRemote: `该分支在远程上不存在. 您需要先将其推送到远程.`, - Fetch: `抓取`, - NoAutomaticGitFetchTitle: `无法自动进行 "git fetch"`, - NoAutomaticGitFetchBody: `Lazygit 不能在私人仓库中使用 "git fetch"; 请在文件面板中使用 'f' 手动运行 "git fetch"`, - FileEnter: `暂存单个 块/行 用于文件, 或 折叠/展开 目录`, - FileStagingRequirements: `只能暂存跟踪文件的单独行`, - StageSelectionTooltip: `切换行暂存状态`, - DiscardSelection: `取消变更 (git reset)`, - ToggleRangeSelect: `切换拖动选择`, - ToggleSelectHunk: `切换选择区块`, - ToggleSelectionForPatch: `添加/移除 行到补丁`, - ToggleStagingView: `切换到其他面板`, - ReturnToFilesPanel: `返回文件面板`, - FastForward: `从上游快进此分支`, - FastForwarding: "抓取并快进", - FoundConflictsTitle: "自动合并失败", - ViewMergeRebaseOptions: "查看 合并/变基 选项", - NotMergingOrRebasing: "您目前既不进行变基也不进行合并", - RecentRepos: "最近的仓库", - MergeOptionsTitle: "合并选项", - RebaseOptionsTitle: "变基选项", - CommitSummaryTitle: "提交讯息", - LocalBranchesTitle: "分支页面", - SearchTitle: "搜索", - TagsTitle: "标签页面", - MenuTitle: "菜单", - RemotesTitle: "远程页面", - RemoteBranchesTitle: "远程分支", - PatchBuildingTitle: "构建补丁中", - InformationTitle: "信息", - SecondaryTitle: "次要", - ReflogCommitsTitle: "Reflog 页面", - GlobalTitle: "全局键绑定", - ConflictsResolved: "已解决所有冲突。是否继续?", - ConfirmMerge: "您确定要将分支 {{.selectedBranch}} 合并到 {{.checkedOutBranch}} 吗?", - FwdNoUpstream: "此分支没有上游,无法快进", - FwdNoLocalUpstream: "此分支的远程未在本地注册,无法快进", - FwdCommitsToPush: "此分支带有尚未推送的提交,无法快进", - ErrorOccurred: "发生错误!请在以下位置创建 issue", - NoRoom: "空间不足", - YouAreHere: "您在这里", - RewordNotSupported: "当前不支持交互式重新基准化时的重新措词提交", - CherryPickCopy: "复制提交(拣选)", - PasteCommits: "粘贴提交(拣选)", - SureCherryPick: "您确定要将选中的提交进行拣选到这个分支吗?", - CherryPick: "拣选 (Cherry-Pick)", - Donate: "捐助", - AskQuestion: "提问咨询", - PrevLine: "选择上一行", - NextLine: "选择下一行", - PrevHunk: "选择上一个区块", - NextHunk: "选择下一个区块", - PrevConflict: "选择上一个冲突", - NextConflict: "选择下一个冲突", - SelectPrevHunk: "选择顶部块", - SelectNextHunk: "选择底部块", - ScrollDown: "向下滚动", - ScrollUp: "向上滚动", - ScrollUpMainWindow: "向上滚动主面板", - ScrollDownMainWindow: "向下滚动主面板", - AmendCommitTitle: "修改提交", - AmendCommitPrompt: "您确定要使用暂存文件来修改此提交吗?", - DropCommitTitle: "删除提交", - DropCommitPrompt: "您确定要删除此提交吗?", - PullingStatus: "正在拉取", - PushingStatus: "正在推送", - FetchingStatus: "正在抓取", - SquashingStatus: "正在压缩", - FixingStatus: "正在修正", - DeletingStatus: "正在删除", - MovingStatus: "正在移动", - RebasingStatus: "正在变基", - AmendingStatus: "正在修改", - CherryPickingStatus: "正在拣选", - UndoingStatus: "正在撤销", - RedoingStatus: "正在重做", - CheckingOutStatus: "长子检出", - CommittingStatus: "正在提交", - CommitFiles: "提交文件", - ViewItemFiles: "查看提交的文件", - CommitFilesTitle: "提交文件", - CheckoutCommitFileTooltip: "检出文件", - DiscardOldFileChangeTooltip: "放弃对此文件的提交更改", - DiscardFileChangesTitle: "放弃文件更改", - DiscardFileChangesPrompt: "您确定要舍弃此提交对该文件的更改吗?如果此文件是在此提交中创建的,它将被删除", - DisabledForGPG: "该功能不适用于使用 GPG 的用户", - CreateRepo: "当前目录不在 git 仓库中。是否在此目录创建一个新的 git 仓库?(y/n): ", - AutoStashTitle: "自动存储?", - AutoStashPrompt: "您必须隐藏并弹出更改以使更改生效。自动执行?(enter/esc)", - StashPrefix: "自动隐藏更改 ", - Discard: "查看'放弃更改'选项", - Cancel: "取消", - DiscardAllChanges: "放弃所有更改", - DiscardUnstagedChanges: "放弃未暂存的变更", - DiscardAllChangesToAllFiles: "清空工作区", - DiscardAnyUnstagedChanges: "丢弃未暂存的变更", - DiscardUntrackedFiles: "丢弃未跟踪的文件", - HardReset: "硬重置", - ViewResetOptions: `查看重置选项`, - CreateFixupCommit: `为此提交创建修正`, - SquashAboveCommitsTooltip: `压缩在所选提交之上的所有“fixup!”提交(自动压缩)`, - CreateFixupCommitTooltip: `创建修正提交`, - ExecuteCustomCommand: "执行自定义命令", - CustomCommand: "自定义命令:", - CommitChangesWithoutHook: "提交更改而无需预先提交钩子", - SkipHookPrefixNotConfigured: "您尚未配置用于跳过钩子的提交消息前缀。请在您的配置中设置 `git.skipHookPrefix ='WIP'`", - ResetTo: `重置为`, - PressEnterToReturn: "按下 Enter 键返回 lazygit", - ViewStashOptions: "查看贮藏选项", - StashAllChanges: "将所有更改加入贮藏", - StashAllChangesKeepIndex: "将已暂存的更改加入贮藏", - StashOptions: "贮藏选项", - NotARepository: "错误:必须在 git 仓库中运行", - Jump: "跳到面板", - ScrollLeftRight: "左右滚动", - ScrollLeft: "向左滚动", - ScrollRight: "向右滚动", - DiscardPatch: "丢弃补丁", - DiscardPatchConfirm: "您一次只能通过一个提交或贮藏条目构建补丁。需要放弃当前补丁吗?", - CantPatchWhileRebasingError: "处于合并或变基状态时,您无法构建修补程序或运行修补程序命令", - ToggleAddToPatch: "补丁中包含的切换文件", - ViewPatchOptions: "查看自定义补丁选项", - PatchOptionsTitle: "补丁选项", - NoPatchError: "尚未创建补丁。你可以在提交中的文件上按下“空格”或使用“回车”添加其中的特定行以开始构建补丁", - EnterCommitFile: "输入文件以将所选行添加到补丁中(或切换目录折叠)", - ExitCustomPatchBuilder: `退出逐行模式`, - EnterUpstream: `以这种格式输入上游:'<远程仓库> <分支名称>'`, - InvalidUpstream: "上游格式无效,格式应当为:'<remote> <branchname>'", - ReturnToRemotesList: `返回远程仓库列表`, - NewRemote: `添加新的远程仓库`, - NewRemoteName: `新远程仓库名称:`, - NewRemoteUrl: `新远程仓库 URL:`, - EditRemoteName: `输入远程仓库 {{.remoteName}} 的新名称:`, - EditRemoteUrl: `输入远程仓库 {{.remoteName}} 的新 URL:`, - RemoveRemote: `删除远程`, - RemoveRemotePrompt: "您确定要删除远程仓库吗?", - DeleteRemoteBranch: "删除远程分支", - DeleteRemoteBranchMessage: "您确定要删除远程分支吗?", - SetUpstream: "设置为检出分支的上游", - SetAsUpstreamTooltip: "设置为检出分支的上游", - SetUpstreamTitle: "设置上游分支", - SetUpstreamMessage: "您确定要将 {{.checkedOut}} 的上游分支设置为 {{.selected}} 吗?", - EditRemoteTooltip: "编辑远程仓库", - TagCommit: "标签提交", - TagMenuTitle: "创建标签", - TagNameTitle: "标签名称", - TagMessageTitle: "标签消息", - AnnotatedTag: "附注标签", - LightweightTag: "轻量标签", - PushTagTitle: "将 {{.tagName}} 推送到远程仓库:", - PushTag: "推送标签", - NewTag: "创建标签", - FetchRemoteTooltip: "抓取远程仓库", - FetchingRemoteStatus: "抓取远程仓库中", - CheckoutCommit: "检出提交", - SureCheckoutThisCommit: "您确定要检出此提交吗?", - GitFlowOptions: "显示 git-flow 选项", - NotAGitFlowBranch: "这似乎不是 git flow 分支", - NewGitFlowBranchPrompt: "新的 {{.branchType}} 名称:", - IgnoreTracked: "忽略跟踪文件", - IgnoreTrackedPrompt: "您确定要忽略已跟踪的文件吗?", - ViewResetToUpstreamOptions: "查看上游重置选项", - NextScreenMode: "下一屏模式(正常/半屏/全屏)", - PrevScreenMode: "上一屏模式", - StartSearch: "开始搜索", - Panel: "面板", - Keybindings: "按键绑定", - RenameBranch: "重命名分支", - NewBranchNamePrompt: "输入分支的新名称", - RenameBranchWarning: "该分支正在跟踪远程仓库。此操作将仅会重命名本地分支名称,而不会重命名远程分支的名称。确定继续?", - OpenKeybindingsMenu: "打开菜单", - ResetCherryPick: "重置已拣选(复制)的提交", - NextTab: "下一个标签", - PrevTab: "上一个标签", - CantUndoWhileRebasing: "进行基础调整时无法撤消", - CantRedoWhileRebasing: "变基时无法重做", - MustStashWarning: "将补丁拉出到索引中需要存储和取消存储所做的更改。如果出现问题,您将可以从存储中访问文件。继续?", - MustStashTitle: "必须保存进度", - ConfirmationTitle: "确认面板", - PrevPage: "上一页", - NextPage: "下一页", - GotoTop: "滚动到顶部", - GotoBottom: "滚动到底部", - FilteringBy: "过滤依据", - ResetInParentheses: "(重置)", - OpenFilteringMenu: "查看按路径过滤选项", - FilterBy: "过滤", - ExitFilterMode: "停止按路径过滤", - FilterPathOption: "输入要过滤的路径", - EnterFileName: "输入路径:", - FilteringMenuTitle: "正在过滤", - MustExitFilterModeTitle: "命令不可用", - MustExitFilterModePrompt: "命令在过滤模式下不可用。退出过滤模式?", - Diff: "差异", - EnterRefToDiff: "输入 ref 以 diff", - EnterRefName: "输入 ref:", - ExitDiffMode: "退出差异模式", - DiffingMenuTitle: "正在 diff", - SwapDiff: "反向 diff", - ViewDiffingOptions: "打开 diff 菜单", + NotEnoughSpace: "没有足够的空间来渲染面板", + DiffTitle: "差异", + FilesTitle: "文件", + BranchesTitle: "分支", + CommitsTitle: "提交", + StashTitle: "贮藏", + UnstagedChanges: `未暂存更改`, + StagedChanges: `已暂存更改`, + MainTitle: "主要", + StagingTitle: "正在暂存", + MergingTitle: "正在合并", + NormalTitle: "正常", + CommitSummary: "提交信息", + CredentialsUsername: "用户名", + CredentialsPassword: "密码", + CredentialsPassphrase: "输入 SSH 密钥的密码", + PassUnameWrong: "密码 和/或 用户名错误", + Commit: "提交更改", + AmendLastCommit: "修补最后一次提交", + AmendLastCommitTitle: "修补最后一次提交", + SureToAmend: "您确定要修补上一次提交吗?之后您可以从提交面板更改提交消息。", + NoCommitToAmend: "没有需要提交的修补。", + CommitChangesWithEditor: "提交更改(使用编辑器编辑提交信息)", + StatusTitle: "状态", + Menu: "菜单", + Execute: "执行", + Stage: "切换暂存状态", + ToggleStagedAll: "切换所有文件的暂存状态", + ToggleTreeView: "切换文件树视图", + OpenMergeTool: "打开外部合并工具 (git mergetool)", + Refresh: "刷新", + Push: "推送", + Pull: "拉取", + Scroll: "滚动", + MergeConflictsTitle: "合并冲突", + Checkout: "检出", + NoChangedFiles: "没有更改过文件", + SoftReset: "软重置", + AlreadyCheckedOutBranch: "您已经检出至此分支", + SureForceCheckout: "您确定要强制检出吗?您将丢失所有本地更改", + ForceCheckoutBranch: "强制检出分支", + BranchName: "分支名称", + NewBranchNameBranchOff: "新分支名称(基于 {{.branchName}})", + CantDeleteCheckOutBranch: "您不能删除已检出的分支!", + ForceDeleteBranchMessage: "{{.selectedBranchName}} 还没有被完全合并。您确定要删除它吗?", + RebaseBranch: "将已检出的分支变基到该分支", + CantRebaseOntoSelf: "您不能将分支变基到其自身", + CantMergeBranchIntoItself: "您不能将分支合并到其自身", + ForceCheckout: "强制检出", + CheckoutByName: "按名称检出", + NewBranch: "新分支", + NoBranchesThisRepo: "此仓库中没有分支", + CommitWithoutMessageErr: "您必须编写提交消息才能进行提交", + CloseCancel: "关闭", + Confirm: "确认", + Close: "关闭", + Quit: "退出", + NoCommitsThisBranch: "该分支没有提交", + CannotSquashOrFixupFirstCommit: "There's no commit below to squash into", + Fixup: "修正(fixup)", + SureFixupThisCommit: "您确定要“修正”此提交吗?它将合并到下面的提交中", + SureSquashThisCommit: "您确定要将这个提交压缩到下面的提交中吗?", + Squash: "压缩", + PickCommitTooltip: "选择提交(变基过程中)", + RevertCommit: "还原提交", + Reword: "改写提交", + DropCommit: "删除提交", + MoveDownCommit: "下移提交", + MoveUpCommit: "上移提交", + EditCommitTooltip: "编辑提交", + AmendCommitTooltip: "用已暂存的更改来修补提交", + RewordCommitEditor: "使用编辑器重命名提交", + Error: "错误", + PickHunk: "选中区块", + PickAllHunks: "选中所有区块", + Undo: "撤销", + UndoReflog: "(通过 reflog)撤销「实验功能」", + RedoReflog: "(通过 reflog)重做「实验功能」", + Pop: "应用并删除", + Drop: "删除", + Apply: "应用", + NoStashEntries: "没有贮藏条目", + StashDrop: "删除贮藏", + SureDropStashEntry: "您确定要删除此贮藏条目吗?", + StashPop: "应用并删除贮藏", + SurePopStashEntry: "您确定要应用并删除此贮藏条目吗?", + StashApply: "应用贮藏", + SureApplyStashEntry: "您确定要应用此贮藏条目?", + NoTrackedStagedFilesStash: "没有可以贮藏的已跟踪/暂存文件", + StashChanges: "贮藏更改", + RenameStash: "Rename stash", + RenameStashPrompt: "Rename stash: {{.stashName}}", + OpenConfig: |