jesseduffield.lazygit/pkg/integration/tests/submodule/resolve_conflict.go
Stefan Haller 050225ffe6 Show per-side commit logs for submodule conflicts in the main view
When a conflicted submodule is selected, the main view shows the commits
each side added relative to their common ancestor as two indented logs,
labelled current and incoming, so it's clear which commit each side would
resolve to.

The logs aren't truncated (the view scrolls). If a side added no commits
of its own (e.g. it was rewound to an ancestor of the other), its head
commit is shown instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 16:12:36 +02:00

83 lines
3 KiB
Go

package submodule
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var ResolveConflict = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Resolve a submodule conflict (both sides moved the gitlink) by picking one side's commit",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Gui.ShowFileTree = false
},
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("first commit")
shell.CloneIntoSubmodule("my_submodule_name", "my_submodule_path")
shell.GitAddAll()
shell.Commit("add submodule")
sub := "my_submodule_path"
// Two diverging commits in the submodule, so the gitlink can't be
// fast-forwarded and the merge genuinely conflicts.
shell.RunCommand([]string{"git", "-C", sub, "checkout", "-b", "left"})
shell.RunCommand([]string{"git", "-C", sub, "commit", "--allow-empty", "-m", "left"})
shell.RunCommand([]string{"git", "-C", sub, "checkout", "-b", "right", "HEAD~1"})
shell.RunCommand([]string{"git", "-C", sub, "commit", "--allow-empty", "-m", "right"})
// "ours" points the submodule at left, "theirs" at right.
shell.RunCommand([]string{"git", "checkout", "-b", "ours"})
shell.RunCommand([]string{"git", "-C", sub, "checkout", "left"})
shell.RunCommand([]string{"git", "add", sub})
shell.Commit("ours")
shell.RunCommand([]string{"git", "checkout", "-b", "theirs", "HEAD~1"})
shell.RunCommand([]string{"git", "-C", sub, "checkout", "right"})
shell.RunCommand([]string{"git", "add", sub})
shell.Commit("theirs")
shell.RunCommand([]string{"git", "checkout", "ours"})
shell.RunCommand([]string{"git", "-C", sub, "checkout", "left"})
shell.RunCommandExpectError([]string{"git", "merge", "theirs"})
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
Focus().
Lines(
Contains("UU my_submodule_path (submodule)").IsSelected(),
).
Tap(func() {
// The main view explains the conflict and shows each side's
// commits as separate "current" and "incoming" logs.
t.Views().Main().Content(
Contains("Conflict: the submodule").
Contains("Current changes:").Contains("left").
Contains("Incoming changes:").Contains("right"),
)
}).
// Enter opens the resolution menu instead of entering the submodule.
// The two candidate commits are shown with their summaries.
Press(keys.Universal.GoInto).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Merge conflicts")).
Select(Contains("Take current commit").Contains("left")).
Select(Contains("Take incoming commit").Contains("right")).
Cancel()
}).
// Space opens the same menu; take the incoming commit to resolve.
PressPrimaryAction().
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Merge conflicts")).
Select(Contains("Take incoming commit")).
Confirm()
}).
Lines(
Contains("M my_submodule_path (submodule)").IsSelected(),
)
},
})