Offer to pull all branches in a stack when pulling the topmost one (#6070)

When somebody else rebases a stack of branches and force-pushes it,
pulling the topmost branch leaves the branches below it diverged. Since
#6067 they can be updated manually with `f`, but pushing the stack
offers to push the branches
below along with the current one, so pulling should be symmetric, and
this PR adds that.
This commit is contained in:
Stefan Haller authored and GitHub committed 2026-09-27 11:19:22 +02:00
commit 02e103c873
13 files changed
+368 -28

No files matched your search

+8
View File
@@ -41,3 +41,11 @@ this work.
whole stack and bring all of it back in sync at once. If any of the selected
branches can't be updated, none of them is, so that you don't end up with half
of the stack updated.
Alternatively, check out the topmost branch of the stack and pull it with `p`.
If branches below it can be updated this way, or are simply behind their
upstream, lazygit offers to update them along with it. Lazygit decides this
from the last fetch, so a branch whose changes on the remote haven't been
fetched yet isn't offered; with auto-fetch turned off, pull a second time after
the first pull has fetched them. Branches that are checked out in another
worktree are left alone. The topmost branch itself is pulled as usual.
+1 -1
View File
@@ -11,7 +11,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <pgdown>, J, <ctrl+d> (fn+down/shift+j) `` | Scroll down main window | |
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have commits to push, you are offered to push those too. |
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have changed on the remote, you are offered to update those too. |
| `` ) `` | Increase rename similarity threshold | Increase the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` ( `` | Decrease rename similarity threshold | Decrease the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view.<br><br>The default can be changed in the config file with the key 'git.diffContextSize'. |
+1 -1
View File
@@ -11,7 +11,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <pgdown>, J, <ctrl+d> (fn+down/shift+j) `` | 메인 패널을 아래로로 스크롤 | |
| `` @ `` | 명령어 로그 메뉴 열기 | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | 푸시 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have commits to push, you are offered to push those too. |
| `` p `` | 업데이트 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | 업데이트 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have changed on the remote, you are offered to update those too. |
| `` ) `` | Increase rename similarity threshold | Increase the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` ( `` | Decrease rename similarity threshold | Decrease the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` } `` | Diff 보기의 변경 사항 주위에 표시되는 컨텍스트의 크기를 늘리기 | Increase the amount of the context shown around changes in the diff view.<br><br>The default can be changed in the config file with the key 'git.diffContextSize'. |
+1 -1
View File
@@ -11,7 +11,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
| `` <pgdown>, J, <ctrl+d> (fn+down/shift+j) `` | Прокрутить вниз главную панель | |
| `` @ `` | Открыть меню журнала команд | View options for the command log e.g. show/hide the command log and focus the command log. |
| `` P `` | Отправить изменения | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have commits to push, you are offered to push those too. |
| `` p `` | Получить и слить изменения | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
| `` p `` | Получить и слить изменения | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have changed on the remote, you are offered to update those too. |
| `` ) `` | Increase rename similarity threshold | Increase the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` ( `` | Decrease rename similarity threshold | Decrease the similarity threshold for a deletion and addition pair to be treated as a rename.<br><br>The default can be changed in the config file with the key 'git.renameSimilarityThreshold'. |
| `` } `` | Увеличить размер контекста, отображаемого вокруг изменений в просмотрщике сравнении | Increase the amount of the context shown around changes in the diff view.<br><br>The default can be changed in the config file with the key 'git.diffContextSize'. |
+20 -9
View File
@@ -444,8 +444,18 @@ type branchToForward struct {
// diverged from it is reset to it, as long as it has no commits of its own. If
// any of the branches can't be updated, none of them is.
func (self *BranchesHelper) FastForwardBranches(branches []*models.Branch) error {
// The worktrees come from the model, so they have to be looked up here,
// before the work moves to a worker
fastForward, err := self.PrepareFastForward(branches)
if err != nil {
return err
}
return self.WithInlineStatusOnBranches(branches, types.ItemOperationFastForwarding, fastForward)
}
// Does the part of FastForwardBranches that looks at the model, and so has to
// run on the UI thread. Returns the rest, which is to be run on a worker; this
// lets other operations include the fast-forward in their own task.
func (self *BranchesHelper) PrepareFastForward(branches []*models.Branch) (func(gocui.Task) error, error) {
toForward := lo.Map(branches, func(branch *models.Branch, _ int) *branchToForward {
worktree, _ := self.worktreeForBranch(branch)
return &branchToForward{branch: branch, worktree: worktree}
@@ -456,14 +466,14 @@ func (self *BranchesHelper) FastForwardBranches(branches []*models.Branch) error
// rebase or bisect, and leave the branch alone
for _, f := range toForward {
if f.worktree != nil && f.worktree.IsRebasingOrBisecting {
return errors.New(utils.ResolvePlaceholderString(
return nil, errors.New(utils.ResolvePlaceholderString(
self.c.Tr.FwdBranchRebasingOrBisecting,
map[string]string{"branchName": f.branch.Name, "worktreeName": f.worktree.Name},
))
}
}
return self.withFastForwardingStatus(branches, func(task gocui.Task) error {
return func(task gocui.Task) error {
defer func() {
if anyCheckedOut {
// The files of those worktrees have changed as well
@@ -488,14 +498,15 @@ func (self *BranchesHelper) FastForwardBranches(branches []*models.Branch) error
}
return self.forwardBranches(self.c.Git(), toForward)
})
}, nil
}
// Runs f with all the given branches shown as being fast-forwarded
func (self *BranchesHelper) withFastForwardingStatus(branches []*models.Branch, f func(gocui.Task) error) error {
return self.c.WithInlineStatus(branches[0], types.ItemOperationFastForwarding, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
// Runs f on a worker with all the given branches shown as being in the given
// operation while it runs
func (self *BranchesHelper) WithInlineStatusOnBranches(branches []*models.Branch, operation types.ItemOperation, f func(gocui.Task) error) error {
return self.c.WithInlineStatus(branches[0], operation, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
for _, branch := range branches[1:] {
self.c.State().SetItemOperation(branch, types.ItemOperationFastForwarding)
self.c.State().SetItemOperation(branch, operation)
}
defer func() {
for _, branch := range branches[1:] {
+95 -15
View File
@@ -8,7 +8,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
@@ -241,7 +240,36 @@ func (self *SyncController) resolvePushOfCurrentBranch(currentBranch *models.Bra
}
func (self *SyncController) pull(currentBranch *models.Branch) error {
action := self.c.Tr.Actions.Pull
branchesBelow := self.updatableBranchesBelow(currentBranch)
if len(branchesBelow) == 0 {
return self.pullCurrentBranch(currentBranch, nil)
}
branchName := map[string]string{"branchName": currentBranch.Name}
return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.Pull,
Prompt: self.branchesBelowToUpdatePrompt(currentBranch, branchesBelow),
Items: []*types.MenuItem{
{
Label: utils.ResolvePlaceholderString(self.c.Tr.PullBranchAndBranchesBelow, branchName),
OnPress: func() error {
return self.pullCurrentBranch(currentBranch, branchesBelow)
},
},
{
Label: utils.ResolvePlaceholderString(self.c.Tr.PullOnlyCurrentBranch, branchName),
OnPress: func() error {
return self.pullCurrentBranch(currentBranch, nil)
},
},
},
})
}
// Pulls the current branch, after updating the given branches stacked below it
// to their upstream branches
func (self *SyncController) pullCurrentBranch(currentBranch *models.Branch, branchesBelow []*models.Branch) error {
opts := PullFilesOptions{Action: self.c.Tr.Actions.Pull, BranchesBelow: branchesBelow}
// if we have no upstream branch we need to set that first
if !currentBranch.IsTrackingRemote() {
@@ -250,11 +278,46 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
return err
}
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
return self.PullAux(currentBranch, opts)
})
}
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
return self.PullAux(currentBranch, opts)
}
// The branches stacked below the current one that can be updated to their
// upstream branches without losing anything: those that are behind them, and
// those that diverged from them only because they were rewritten
func (self *SyncController) updatableBranchesBelow(currentBranch *models.Branch) []*models.Branch {
branchesBelow := helpers.BranchesBelowInStack(
self.c.Model().Commits, self.c.Model().Branches, currentBranch, self.c.UserConfig().Git.MainBranches)
return lo.Filter(branchesBelow, func(branch *models.Branch, _ int) bool {
// Updating a branch that is checked out in another worktree changes
// the files there, which is more than pulling the current branch
// should do
if git_commands.CheckedOutByOtherWorktree(branch, self.c.Model().Worktrees) {
return false
}
return branch.IsBehindForPull() && (!branch.IsAheadForPull() || branch.UpstreamRewritten.Load())
})
}
func (self *SyncController) branchesBelowToUpdatePrompt(currentBranch *models.Branch, branchesBelow []*models.Branch) string {
intro := utils.ResolvePlaceholderString(
self.c.Tr.BranchesBelowHaveChangedOnRemote,
map[string]string{"branchName": currentBranch.Name},
)
lines := lo.Map(branchesBelow, func(branch *models.Branch, _ int) string {
divergence := "↓" + branch.BehindForPull
if branch.IsAheadForPull() {
divergence += "↑" + branch.AheadForPull
}
return fmt.Sprintf("%s %s", branch.Name, style.FgYellow.Sprint(divergence))
})
return intro + "\n\n " + strings.Join(lines, "\n ")
}
func (self *SyncController) setCurrentBranchUpstream(upstream string) error {
@@ -280,10 +343,35 @@ type PullFilesOptions struct {
UpstreamBranch string
FastForwardOnly bool
Action string
// Branches stacked below the current one, updated to their upstream
// branches before the current one is pulled
BranchesBelow []*models.Branch
}
func (self *SyncController) PullAux(currentBranch *models.Branch, opts PullFilesOptions) error {
return self.c.WithInlineStatus(currentBranch, types.ItemOperationPulling, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
var updateBranchesBelow func(gocui.Task) error
if len(opts.BranchesBelow) > 0 {
var err error
updateBranchesBelow, err = self.c.Helpers().BranchesHelper.PrepareFastForward(opts.BranchesBelow)
if err != nil {
return err
}
}
branches := append([]*models.Branch{currentBranch}, opts.BranchesBelow...)
return self.c.Helpers().BranchesHelper.WithInlineStatusOnBranches(branches, types.ItemOperationPulling, func(task gocui.Task) error {
// Update the branches below first. If one of them pointed into the
// commits that a rebasing pull rebases, the pull would move it when
// rebase.updateRefs is set, and updating it afterwards would fail. If
// updating them fails, the current branch isn't pulled either; the
// user can still choose to pull only the current branch.
if updateBranchesBelow != nil {
if err := updateBranchesBelow(task); err != nil {
return err
}
}
return self.pullWithLock(task, opts)
})
}
@@ -383,16 +471,8 @@ func (self *SyncController) pushBranchesAux(currentBranch *models.Branch, branch
// Runs f as a push of the current branch, showing it and the other branches
// as being pushed while it runs
func (self *SyncController) withPushingStatus(currentBranch *models.Branch, otherBranches []*models.Branch, f func(gocui.Task) error) error {
return self.c.WithInlineStatus(currentBranch, types.ItemOperationPushing, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
for _, branch := range otherBranches {
self.c.State().SetItemOperation(branch, types.ItemOperationPushing)
}
defer func() {
for _, branch := range otherBranches {
self.c.State().ClearItemOperation(branch)
}
}()
branches := append([]*models.Branch{currentBranch}, otherBranches...)
return self.c.Helpers().BranchesHelper.WithInlineStatusOnBranches(branches, types.ItemOperationPushing, func(task gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.Push)
return f(task)
})
+7 -1
View File
@@ -244,6 +244,9 @@ type TranslationSet struct {
BranchesBelowHaveCommitsToPush string
PushBranchAndBranchesBelow string
PushOnlyCurrentBranch string
BranchesBelowHaveChangedOnRemote string
PullBranchAndBranchesBelow string
PullOnlyCurrentBranch string
UpdatesRejected string
UpdatesRejectedAndForcePushDisabled string
CheckForUpdate string
@@ -1232,7 +1235,7 @@ func EnglishTranslationSet() *TranslationSet {
Push: "Push",
PushTooltip: "Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have commits to push, you are offered to push those too.",
Pull: "Pull",
PullTooltip: "Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch.",
PullTooltip: "Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. If other branches are stacked below the current one and have changed on the remote, you are offered to update those too.",
MergeConflictsTitle: "Merge conflicts",
MergeConflictDescription_DD: "Conflict: this file was moved or renamed both in the current and the incoming changes, but to different destinations. I don't know which ones, but they should both show up as conflicts too (marked 'AU' and 'UA', respectively). The most likely resolution is to delete this file, and pick one of the destinations and delete the other.",
MergeConflictDescription_AU: "Conflict: this file is the destination of a move or rename in the current changes, but was moved or renamed to a different destination in the incoming changes. That other destination should also show up as a conflict (marked 'UA'), as well as the file that both were renamed from (marked 'DD').",
@@ -1413,6 +1416,9 @@ func EnglishTranslationSet() *TranslationSet {
BranchesBelowHaveCommitsToPush: "The following branches stacked below '{{.branchName}}' also have commits to push:",
PushBranchAndBranchesBelow: "Push all these branches in addition to the current one",
PushOnlyCurrentBranch: "Push only '{{.branchName}}'",
BranchesBelowHaveChangedOnRemote: "The following branches stacked below '{{.branchName}}' have also changed on the remote:",
PullBranchAndBranchesBelow: "Pull all these branches in addition to the current one",
PullOnlyCurrentBranch: "Pull only '{{.branchName}}'",
UpdatesRejected: "Updates were rejected. Please fetch and examine the remote changes before pushing again.",
UpdatesRejectedAndForcePushDisabled: "Updates were rejected and you have disabled force pushing",
CheckForUpdate: "Check for update",
@@ -0,0 +1,56 @@
package sync
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var PullStackedBranches = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Pull a stack of branches that was rebased on the remote, updating the branches below the current one too",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical"
},
SetupRepo: func(shell *Shell) {
createStackRewrittenOnTheRemote(shell)
shell.Checkout("branch3")
shell.SetConfig("pull.rebase", "true")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Branches().
Lines(
Contains("branch3 ↓3↑3"),
Contains("branch1 ↓1↑1"),
Contains("branch2 ↓2↑2"),
Contains("master"),
)
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
t.ExpectPopup().Menu().
Title(Equals("Pull")).
ContainsLines(
Contains(" branch2 ↓2↑2"),
Contains(" branch1 ↓1↑1"),
).
Select(Contains("Pull all these branches in addition to the current one")).
Confirm()
t.Views().Branches().
Lines(
Contains("branch3 ✓"),
Contains("branch1 ✓"),
Contains("branch2 ✓"),
Contains("master"),
)
t.Views().Commits().
Lines(
Contains("three-rewritten"),
Contains("two-rewritten"),
Contains("one-rewritten"),
Contains("base"),
)
},
})
@@ -0,0 +1,47 @@
package sync
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var PullStackedBranchesCheckedOutInOtherWorktree = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Pull a stack that was rebased on the remote; a branch below the current one that is checked out in another worktree is not offered for updating",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical"
},
SetupRepo: func(shell *Shell) {
createStackRewrittenOnTheRemote(shell)
shell.Checkout("branch3")
shell.SetConfig("pull.rebase", "true")
shell.AddWorktreeCheckout("branch1", "../linked-worktree")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
t.ExpectPopup().Menu().
Title(Equals("Pull")).
Lines(
Contains("The following branches stacked below 'branch3' have also changed on the remote:"),
Equals(""),
Equals(" branch2 ↓2↑2"),
Equals(""),
Contains("Pull all these branches in addition to the current one"),
Contains("Pull only 'branch3'"),
Contains("Cancel"),
).
Select(Contains("Pull all these branches in addition to the current one")).
Confirm()
t.Views().Branches().
Lines(
Contains("branch3 ✓"),
Contains("branch1 (worktree linked-worktree) ↓1↑1"),
Contains("branch2 ✓"),
Contains("master"),
)
},
})
@@ -0,0 +1,36 @@
package sync
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var PullStackedBranchesOnlyCurrent = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Decline updating the branches below the current one in a stack that was rebased on the remote, pulling only the current branch",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical"
},
SetupRepo: func(shell *Shell) {
createStackRewrittenOnTheRemote(shell)
shell.Checkout("branch3")
shell.SetConfig("pull.rebase", "true")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
t.ExpectPopup().Menu().
Title(Equals("Pull")).
Select(Contains("Pull only 'branch3'")).
Confirm()
t.Views().Branches().
Lines(
Contains("branch3 ✓"),
Contains("branch1 ↓1↑1"),
Contains("branch2 ↓2↑2"),
Contains("master"),
)
},
})
@@ -0,0 +1,44 @@
package sync
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var PullStackedBranchesUpdateFails = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Pull a stack that was rebased on the remote, when updating the branches below the current one fails; the current branch is not pulled then",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical"
},
SetupRepo: func(shell *Shell) {
createStackRewrittenOnTheRemote(shell)
shell.Checkout("branch3")
shell.SetConfig("pull.rebase", "true")
// Somebody deleted branch1 on the remote, which we haven't fetched yet
shell.RunCommand([]string{"git", "-C", "../origin", "branch", "-D", "branch1"})
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
t.ExpectPopup().Menu().
Title(Equals("Pull")).
Select(Contains("Pull all these branches in addition to the current one")).
Confirm()
t.ExpectPopup().Alert().
Title(Equals("Error")).
Content(Contains("couldn't find remote ref")).
Confirm()
t.Views().Branches().
Lines(
Contains("branch3 ↓3↑3"),
Contains("branch1 ↓1↑1"),
Contains("branch2 ↓2↑2"),
Contains("master"),
)
},
})
@@ -0,0 +1,47 @@
package sync
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var PullStackedBranchesWithLocalCommits = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Pull a stack that was rebased on the remote; a branch below the current one that has a commit of its own is not offered for updating",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Git.LocalBranchSortOrder = "alphabetical"
},
SetupRepo: func(shell *Shell) {
createStackRewrittenOnTheRemote(shell)
shell.Checkout("branch2")
shell.EmptyCommit("mine")
shell.Checkout("branch3")
shell.RunCommand([]string{"git", "rebase", "--onto", "branch2", "branch2~1"})
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Branches().
Lines(
Contains("branch3 ↓3↑4"),
Contains("branch1 ↓1↑1"),
Contains("branch2 ↓2↑3"),
Contains("master"),
)
t.Views().Files().IsFocused().Press(keys.Universal.Pull)
t.ExpectPopup().Menu().
Title(Equals("Pull")).
Lines(
Contains("The following branches stacked below 'branch3' have also changed on the remote:"),
Equals(""),
Equals(" branch1 ↓1↑1"),
Equals(""),
Contains("Pull all these branches in addition to the current one"),
Contains("Pull only 'branch3'"),
Contains("Cancel"),
).
Cancel()
},
})
+5
View File
@@ -509,6 +509,11 @@ var tests = []*components.IntegrationTest{
sync.PullRebaseConflict,
sync.PullRebaseInteractiveConflict,
sync.PullRebaseInteractiveConflictDrop,
sync.PullStackedBranches,
sync.PullStackedBranchesCheckedOutInOtherWorktree,
sync.PullStackedBranchesOnlyCurrent,
sync.PullStackedBranchesUpdateFails,
sync.PullStackedBranchesWithLocalCommits,
sync.Push,
sync.PushAndAutoSetUpstream,
sync.PushAndSetUpstream,