From 0864affc8fbd3357b85c4c21201f7cf1677a0561 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 26 Jan 2025 10:21:29 +0100 Subject: [PATCH] Fix checking out a different branch while pushing a branch for the first time When pushing a branch that didn't have an upstream yet, we use the command line git push --set-upstream origin HEAD:branch-name The HEAD: part of this is too unspecific; when checking out a different branch while the push is still running, then git will set the upstream branch on the newly checked out branch, not the branch that was being pushed. This might be considered a bug in git; you might expect that it resolves HEAD at the beginning of the operation, and uses the result at the end. But we can easily work around this by explicitly supplying the real branch name instead of HEAD. --- pkg/commands/git_commands/sync.go | 5 ++++- pkg/commands/git_commands/sync_test.go | 9 ++++++--- pkg/gui/controllers/sync_controller.go | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/commands/git_commands/sync.go b/pkg/commands/git_commands/sync.go index ab6942d05..4ac1a5c1f 100644 --- a/pkg/commands/git_commands/sync.go +++ b/pkg/commands/git_commands/sync.go @@ -1,6 +1,8 @@ package git_commands import ( + "fmt" + "github.com/go-errors/errors" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" @@ -20,6 +22,7 @@ func NewSyncCommands(gitCommon *GitCommon) *SyncCommands { type PushOpts struct { Force bool ForceWithLease bool + CurrentBranch string UpstreamRemote string UpstreamBranch string SetUpstream bool @@ -35,7 +38,7 @@ func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (oscommands ArgIf(opts.ForceWithLease, "--force-with-lease"). ArgIf(opts.SetUpstream, "--set-upstream"). ArgIf(opts.UpstreamRemote != "", opts.UpstreamRemote). - ArgIf(opts.UpstreamBranch != "", "HEAD:"+opts.UpstreamBranch). + ArgIf(opts.UpstreamBranch != "", fmt.Sprintf("refs/heads/%s:%s", opts.CurrentBranch, opts.UpstreamBranch)). ToArgv() cmdObj := self.cmd.New(cmdArgs).PromptOnCredentialRequest(task) diff --git a/pkg/commands/git_commands/sync_test.go b/pkg/commands/git_commands/sync_test.go index 183912c31..d22147627 100644 --- a/pkg/commands/git_commands/sync_test.go +++ b/pkg/commands/git_commands/sync_test.go @@ -44,11 +44,12 @@ func TestSyncPush(t *testing.T) { testName: "Push with force disabled, upstream supplied", opts: PushOpts{ ForceWithLease: false, + CurrentBranch: "master", UpstreamRemote: "origin", UpstreamBranch: "master", }, test: func(cmdObj oscommands.ICmdObj, err error) { - assert.Equal(t, cmdObj.Args(), []string{"git", "push", "origin", "HEAD:master"}) + assert.Equal(t, cmdObj.Args(), []string{"git", "push", "origin", "refs/heads/master:master"}) assert.NoError(t, err) }, }, @@ -56,12 +57,13 @@ func TestSyncPush(t *testing.T) { testName: "Push with force disabled, setting upstream", opts: PushOpts{ ForceWithLease: false, + CurrentBranch: "master-local", UpstreamRemote: "origin", UpstreamBranch: "master", SetUpstream: true, }, test: func(cmdObj oscommands.ICmdObj, err error) { - assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--set-upstream", "origin", "HEAD:master"}) + assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--set-upstream", "origin", "refs/heads/master-local:master"}) assert.NoError(t, err) }, }, @@ -69,12 +71,13 @@ func TestSyncPush(t *testing.T) { testName: "Push with force-with-lease enabled, setting upstream", opts: PushOpts{ ForceWithLease: true, + CurrentBranch: "master", UpstreamRemote: "origin", UpstreamBranch: "master", SetUpstream: true, }, test: func(cmdObj oscommands.ICmdObj, err error) { - assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease", "--set-upstream", "origin", "HEAD:master"}) + assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease", "--set-upstream", "origin", "refs/heads/master:master"}) assert.NoError(t, err) }, }, diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index a6140d9d0..66c480b93 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -200,6 +200,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts) git_commands.PushOpts{ Force: opts.force, ForceWithLease: opts.forceWithLease, + CurrentBranch: currentBranch.Name, UpstreamRemote: opts.upstreamRemote, UpstreamBranch: opts.upstreamBranch, SetUpstream: opts.setUpstream,