1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-08-08 22:36:49 +02:00

Improve "Find base commit for fixup" command when there are changes for master commits (#3645)

- **PR Description**

If exactly one candidate from inside the current branch is found, we
return that one even if there are also hunks belonging to master
commits; we disregard those in this case.

- **Please check if the PR fulfills these requirements**

* [x] Cheatsheets are up-to-date (run `go generate ./...`)
* [x] Code has been formatted (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
* [x] Tests have been added/updated (see
[here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md)
for the integration test guide)
* [ ] Text is internationalised (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
* [ ] Docs have been updated if necessary
* [x] You've read through your own file changes for silly mistakes etc
This commit is contained in:
Stefan Haller
2024-06-10 12:03:22 +02:00
committed by GitHub
3 changed files with 102 additions and 23 deletions

View File

@ -50,6 +50,8 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
deletedLineHunks, addedLineHunks := parseDiff(diff) deletedLineHunks, addedLineHunks := parseDiff(diff)
commits := self.c.Model().Commits
var hashes []string var hashes []string
warnAboutAddedLines := false warnAboutAddedLines := false
@ -57,7 +59,7 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
hashes, err = self.blameDeletedLines(deletedLineHunks) hashes, err = self.blameDeletedLines(deletedLineHunks)
warnAboutAddedLines = len(addedLineHunks) > 0 warnAboutAddedLines = len(addedLineHunks) > 0
} else if len(addedLineHunks) > 0 { } else if len(addedLineHunks) > 0 {
hashes, err = self.blameAddedLines(addedLineHunks) hashes, err = self.blameAddedLines(commits, addedLineHunks)
} else { } else {
return errors.New(self.c.Tr.NoChangedFiles) return errors.New(self.c.Tr.NoChangedFiles)
} }
@ -70,8 +72,49 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
// This should never happen // This should never happen
return errors.New(self.c.Tr.NoBaseCommitsFound) return errors.New(self.c.Tr.NoBaseCommitsFound)
} }
if len(hashes) > 1 {
subjects, err := self.c.Git().Commit.GetHashesAndCommitMessagesFirstLine(hashes) // If a commit can't be found, and the last known commit is already merged,
// we know that the commit we're looking for is also merged. Otherwise we
// can't tell.
notFoundMeansMerged := len(commits) > 0 && commits[len(commits)-1].Status == models.StatusMerged
const (
MERGED int = iota
NOT_MERGED
CANNOT_TELL
)
// Group the hashes into buckets by merged status
hashGroups := lo.GroupBy(hashes, func(hash string) int {
commit, _, ok := self.findCommit(commits, hash)
if ok {
return lo.Ternary(commit.Status == models.StatusMerged, MERGED, NOT_MERGED)
}
return lo.Ternary(notFoundMeansMerged, MERGED, CANNOT_TELL)
})
if len(hashGroups[CANNOT_TELL]) > 0 {
// If we have any commits that we can't tell if they're merged, just
// show the generic "not in current view" error. This can only happen if
// a feature branch has more than 300 commits, or there is no main
// branch. Both are so unlikely that we don't bother returning a more
// detailed error message (e.g. we could say something about the commits
// that *are* in the current branch, but it's not worth it).
return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView)
}
if len(hashGroups[NOT_MERGED]) == 0 {
// If all the commits are merged, show the "already on main branch"
// error. It isn't worth doing a detailed report of which commits we
// found.
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
if len(hashGroups[NOT_MERGED]) > 1 {
// If there are multiple commits that could be the base commit, list
// them in the error message. But only the candidates from the current
// branch, not including any that are already merged.
subjects, err := self.c.Git().Commit.GetHashesAndCommitMessagesFirstLine(hashGroups[NOT_MERGED])
if err != nil { if err != nil {
return err return err
} }
@ -81,21 +124,9 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
return fmt.Errorf("%s\n\n%s", message, subjects) return fmt.Errorf("%s\n\n%s", message, subjects)
} }
commit, index, ok := self.findCommit(hashes[0]) // At this point we know that the NOT_MERGED bucket has exactly one commit,
if !ok { // and that's the one we want to select.
commits := self.c.Model().Commits _, index, _ := self.findCommit(commits, hashGroups[NOT_MERGED][0])
if commits[len(commits)-1].Status == models.StatusMerged {
// If the commit is not found, it's most likely because it's already
// merged, and more than 300 commits away. Check if the last known
// commit is already merged; if so, show the "already merged" error.
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
// If we get here, the current branch must have more then 300 commits. Unlikely...
return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView)
}
if commit.Status == models.StatusMerged {
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
}
doIt := func() error { doIt := func() error {
if !hasStagedChanges { if !hasStagedChanges {
@ -225,7 +256,7 @@ func (self *FixupHelper) blameDeletedLines(deletedLineHunks []*hunk) ([]string,
return result.ToSlice(), errg.Wait() return result.ToSlice(), errg.Wait()
} }
func (self *FixupHelper) blameAddedLines(addedLineHunks []*hunk) ([]string, error) { func (self *FixupHelper) blameAddedLines(commits []*models.Commit, addedLineHunks []*hunk) ([]string, error) {
errg := errgroup.Group{} errg := errgroup.Group{}
hashesChan := make(chan []string) hashesChan := make(chan []string)
@ -288,8 +319,8 @@ func (self *FixupHelper) blameAddedLines(addedLineHunks []*hunk) ([]string, erro
if hashes[0] == hashes[1] { if hashes[0] == hashes[1] {
result.Add(hashes[0]) result.Add(hashes[0])
} else { } else {
_, index1, ok1 := self.findCommit(hashes[0]) _, index1, ok1 := self.findCommit(commits, hashes[0])
_, index2, ok2 := self.findCommit(hashes[1]) _, index2, ok2 := self.findCommit(commits, hashes[1])
if ok1 && ok2 { if ok1 && ok2 {
result.Add(lo.Ternary(index1 < index2, hashes[0], hashes[1])) result.Add(lo.Ternary(index1 < index2, hashes[0], hashes[1]))
} else if ok1 { } else if ok1 {
@ -306,8 +337,8 @@ func (self *FixupHelper) blameAddedLines(addedLineHunks []*hunk) ([]string, erro
return result.ToSlice(), errg.Wait() return result.ToSlice(), errg.Wait()
} }
func (self *FixupHelper) findCommit(hash string) (*models.Commit, int, bool) { func (self *FixupHelper) findCommit(commits []*models.Commit, hash string) (*models.Commit, int, bool) {
return lo.FindIndexOf(self.c.Model().Commits, func(commit *models.Commit) bool { return lo.FindIndexOf(commits, func(commit *models.Commit) bool {
return commit.Hash == hash return commit.Hash == hash
}) })
} }

View File

@ -0,0 +1,47 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FindBaseCommitForFixupDisregardMainBranch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Finds the base commit to create a fixup for, disregarding changes to a commit that is already on master",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.
EmptyCommit("1st commit").
CreateFileAndAdd("file1", "file1 content\n").
Commit("2nd commit").
NewBranch("mybranch").
CreateFileAndAdd("file2", "file2 content\n").
Commit("3rd commit").
EmptyCommit("4th commit").
UpdateFile("file1", "file1 changed content").
UpdateFile("file2", "file2 changed content")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Lines(
Contains("4th commit").IsSelected(),
Contains("3rd commit"),
Contains("2nd commit"),
Contains("1st commit"),
)
t.Views().Files().
Focus().
Press(keys.Files.FindBaseCommitForFixup)
t.Views().Commits().
IsFocused().
Lines(
Contains("4th commit"),
Contains("3rd commit").IsSelected(),
Contains("2nd commit"),
Contains("1st commit"),
)
},
})

View File

@ -82,6 +82,7 @@ var tests = []*components.IntegrationTest{
commit.CreateTag, commit.CreateTag,
commit.DiscardOldFileChanges, commit.DiscardOldFileChanges,
commit.FindBaseCommitForFixup, commit.FindBaseCommitForFixup,
commit.FindBaseCommitForFixupDisregardMainBranch,
commit.FindBaseCommitForFixupOnlyAddedLines, commit.FindBaseCommitForFixupOnlyAddedLines,
commit.FindBaseCommitForFixupWarningForAddedLines, commit.FindBaseCommitForFixupWarningForAddedLines,
commit.Highlight, commit.Highlight,