From 532cce4873737a5d32c68d48a83bab098b124cb4 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 21 May 2026 12:30:36 +0200 Subject: [PATCH] Add test for auto-forwarding a branch checked out in another worktree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the linked worktree's branch is changed externally — by another shell, by another tool, or by git running outside lazygit — lazygit's worktrees model goes stale. The next post-fetch auto-forward then doesn't realise the branch is now checked out elsewhere, and advances its ref behind the worktree's back. The worktree's HEAD then resolves to a commit its index/working tree haven't been updated to, and the user sees that diff as the inverse of what was fetched — files appearing as pending changes that they didn't make. The test sets up a linked worktree initially on a side branch, then externally checks out master in it before pressing fetch. Two EXPECTED/ACTUAL pairs capture the symptoms: the branches view shows master as `✓` rather than `↓1`, and switching to the linked worktree shows master's would-be incoming file as a pending deletion against HEAD. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...d_branches_worktree_added_after_startup.go | 68 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 2 files changed, 69 insertions(+) create mode 100644 pkg/integration/tests/sync/fetch_and_auto_forward_branches_worktree_added_after_startup.go diff --git a/pkg/integration/tests/sync/fetch_and_auto_forward_branches_worktree_added_after_startup.go b/pkg/integration/tests/sync/fetch_and_auto_forward_branches_worktree_added_after_startup.go new file mode 100644 index 000000000..61cb0fd9f --- /dev/null +++ b/pkg/integration/tests/sync/fetch_and_auto_forward_branches_worktree_added_after_startup.go @@ -0,0 +1,68 @@ +package sync + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var FetchAndAutoForwardBranchesWorktreeAddedAfterStartup = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Auto-forward skips a main branch that was externally checked out in a linked worktree after lazygit started", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Git.AutoForwardBranches = "onlyMainBranches" + config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical" + }, + SetupRepo: func(shell *Shell) { + shell.CreateNCommits(3) + shell.NewBranch("feature") + shell.NewBranch("wt-branch") + shell.CloneIntoRemote("origin") + shell.SetBranchUpstream("master", "origin/master") + shell.SetBranchUpstream("feature", "origin/feature") + shell.Checkout("master") + shell.HardReset("HEAD^") + shell.Checkout("feature") + shell.AddWorktreeCheckout("wt-branch", "../linked-worktree") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Branches(). + Lines( + Contains("feature").IsSelected(), + Contains("master ↓1").DoesNotContain("↑"), + Contains("wt-branch (worktree linked-worktree)"), + ) + + // Switch the linked worktree to master externally. + t.Shell().RunCommand([]string{"git", "-C", "../linked-worktree", "checkout", "master"}) + + t.Views().Files(). + IsFocused(). + Press(keys.Files.Fetch) + + t.Views().Branches(). + Lines( + Contains("feature").IsSelected(), + /* EXPECTED: + Contains("master (worktree linked-worktree) ↓1"), + Contains("wt-branch").DoesNotContain("worktree"), + ACTUAL: */ + Contains("master ✓"), + Contains("wt-branch (worktree linked-worktree)"), + ) + + t.Views().Worktrees(). + Focus(). + NavigateToLine(Contains("linked-worktree")). + PressPrimaryAction() + + t.Views().Files(). + Focus(). + /* EXPECTED: + IsEmpty() + ACTUAL: */ + Lines( + Equals("D file03.txt"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 4b96c4d42..fdccb08bf 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -428,6 +428,7 @@ var tests = []*components.IntegrationTest{ sync.FetchAndAutoForwardBranchesAllBranchesCheckedOutInOtherWorktree, sync.FetchAndAutoForwardBranchesNone, sync.FetchAndAutoForwardBranchesOnlyMainBranches, + sync.FetchAndAutoForwardBranchesWorktreeAddedAfterStartup, sync.FetchPrune, sync.FetchWhenSortedByDate, sync.ForcePush,