Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions pkg/gui/controllers/commits_files_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,25 @@ func (self *CommitFilesController) openCopyMenu() error {
}

func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error {
self.c.LogAction(self.c.Tr.Actions.CheckoutFile)
_, to := self.context().GetFromAndToForDiff()
if err := self.c.Git().WorkingTree.CheckoutFile(to, node.GetPath()); err != nil {
return err
}
// Check if the file has uncommitted local changes
hasLocalChanges := lo.SomeBy(self.c.Model().Files, func(file *models.File) bool {
return file.GetPath() == node.GetPath() && (file.HasStagedChanges || file.HasUnstagedChanges)
})

self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
return nil
return self.c.ConfirmIf(hasLocalChanges, types.ConfirmOpts{
Title: self.c.Tr.CheckoutFileFromCommitTitle,
Prompt: self.c.Tr.CheckoutFileFromCommitPrompt,
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.CheckoutFile)
_, to := self.context().GetFromAndToForDiff()
if err := self.c.Git().WorkingTree.CheckoutFile(to, node.GetPath()); err != nil {
return err
}

self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
return nil
},
})
}

func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileNode) error {
Expand Down
4 changes: 4 additions & 0 deletions pkg/i18n/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ type TranslationSet struct {
ViewItemFiles string
CommitFilesTitle string
CheckoutCommitFileTooltip string
CheckoutFileFromCommitTitle string
CheckoutFileFromCommitPrompt string
CanOnlyDiscardFromLocalCommits string
Remove string
DiscardOldFileChangeTooltip string
Expand Down Expand Up @@ -1525,6 +1527,8 @@ func EnglishTranslationSet() *TranslationSet {
ViewItemFiles: "View files",
CommitFilesTitle: "Commit files",
CheckoutCommitFileTooltip: "Checkout file. This replaces the file in your working tree with the version from the selected commit.",
CheckoutFileFromCommitTitle: "Checkout file from commit",
CheckoutFileFromCommitPrompt: "Are you sure you want to checkout this file? Your uncommitted changes will be lost.",
CanOnlyDiscardFromLocalCommits: "Changes can only be discarded from local commits",
Remove: "Remove",
DiscardOldFileChangeTooltip: "Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package commit

import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)

var CheckoutFileFromCommitWithLocalChanges = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Checkout a file from a commit when there are local changes, showing a confirmation",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateFileAndAdd("file.txt", "one\n")
shell.Commit("one")
shell.CreateFileAndAdd("file.txt", "two\n")
shell.Commit("two")
shell.CreateFileAndAdd("file.txt", "three\n")
shell.Commit("three")
// Create local uncommitted changes
shell.UpdateFile("file.txt", "local changes\n")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("three").IsSelected(),
Contains("two"),
Contains("one"),
).
NavigateToLine(Contains("two")).
PressEnter()

t.Views().CommitFiles().
IsFocused().
Lines(
Equals("M file.txt"),
).
Press(keys.CommitFiles.CheckoutCommitFile)

// Should show confirmation dialog
t.ExpectPopup().Confirmation().
Title(Equals("Checkout file from commit")).
Content(Contains("Are you sure you want to checkout this file? Your uncommitted changes will be lost.")).
Confirm()

// After confirmation, file should be checked out
t.Views().Files().
Lines(
Equals("M file.txt"),
)

t.FileSystem().FileContent("file.txt", Equals("two\n"))
},
})
1 change: 1 addition & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ var tests = []*components.IntegrationTest{
commit.AutoWrapMessage,
commit.Checkout,
commit.CheckoutFileFromCommit,
commit.CheckoutFileFromCommitWithLocalChanges,
commit.CheckoutFileFromRangeSelectionOfCommits,
commit.Commit,
commit.CommitMultiline,
Expand Down