Skip to content

Bump minimum required git version to 2.32 #4718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 9, 2025
Merged
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
7 changes: 3 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ jobs:
fail-fast: false
matrix:
git-version:
- 2.22.0 # oldest supported version
- 2.23.0
- 2.25.1
- 2.30.8
- 2.32.0 # oldest supported version
- 2.38.2 # first version that supports the rebase.updateRefs config
- 2.44.0
- latest # We rely on github to have the latest version installed on their VMs
runs-on: ubuntu-latest
name: "Integration Tests - git ${{matrix.git-version}}"
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (app *App) validateGitVersion() (*git_commands.GitVersion, error) {
return nil, minVersionError
}

if version.IsOlderThan(2, 22, 0) {
if version.IsOlderThan(2, 32, 0) {
return nil, minVersionError
}

Expand Down
3 changes: 1 addition & 2 deletions pkg/commands/git_commands/commit_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,7 @@ func (self *CommitLoader) extractCommitFromLine(hashPool *utils.StringPool, line
}

func (self *CommitLoader) getHydratedRebasingCommits(hashPool *utils.StringPool, addConflictingCommit bool) ([]*models.Commit, error) {
todoFileHasShortHashes := self.version.IsOlderThan(2, 25, 2)
return self.getHydratedTodoCommits(hashPool, self.getRebasingCommits(hashPool, addConflictingCommit), todoFileHasShortHashes)
return self.getHydratedTodoCommits(hashPool, self.getRebasingCommits(hashPool, addConflictingCommit), false)
}

func (self *CommitLoader) getHydratedSequencerCommits(hashPool *utils.StringPool, workingTreeState models.WorkingTreeState) ([]*models.Commit, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/git_commands/rebase.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
Arg("--interactive").
Arg("--autostash").
Arg("--keep-empty").
ArgIf(opts.keepCommitsThatBecomeEmpty && self.version.IsAtLeast(2, 26, 0), "--empty=keep").
ArgIf(opts.keepCommitsThatBecomeEmpty, "--empty=keep").
Arg("--no-autosquash").
Arg("--rebase-merges").
ArgIf(opts.onto != "", "--onto", opts.onto).
Expand Down
16 changes: 3 additions & 13 deletions pkg/commands/git_commands/repo_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ type RepoPaths struct {
isBareRepo bool
}

var gitPathFormatVersion = GitVersion{2, 31, 0, ""}

// Path to the current worktree. If we're in the main worktree, this will
// be the same as RepoPath()
func (self *RepoPaths) WorktreePath() string {
Expand Down Expand Up @@ -79,15 +77,14 @@ func GetRepoPaths(
if err != nil {
return nil, err
}
return GetRepoPathsForDir(cwd, cmd, version)
return GetRepoPathsForDir(cwd, cmd)
}

func GetRepoPathsForDir(
dir string,
cmd oscommands.ICmdObjBuilder,
version *GitVersion,
) (*RepoPaths, error) {
gitDirOutput, err := callGitRevParseWithDir(cmd, version, dir, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree")
gitDirOutput, err := callGitRevParseWithDir(cmd, dir, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--is-bare-repository", "--show-superproject-working-tree")
if err != nil {
return nil, err
}
Expand All @@ -96,12 +93,6 @@ func GetRepoPathsForDir(
worktreePath := gitDirResults[0]
worktreeGitDirPath := gitDirResults[1]
repoGitDirPath := gitDirResults[2]
if version.IsOlderThanVersion(&gitPathFormatVersion) {
repoGitDirPath, err = filepath.Abs(repoGitDirPath)
if err != nil {
return nil, err
}
}
isBareRepo := gitDirResults[3] == "true"

// If we're in a submodule, --show-superproject-working-tree will return
Expand Down Expand Up @@ -131,11 +122,10 @@ func GetRepoPathsForDir(

func callGitRevParseWithDir(
cmd oscommands.ICmdObjBuilder,
version *GitVersion,
dir string,
gitRevArgs ...string,
) (string, error) {
gitRevParse := NewGitCmd("rev-parse").ArgIf(version.IsAtLeastVersion(&gitPathFormatVersion), "--path-format=absolute").Arg(gitRevArgs...)
gitRevParse := NewGitCmd("rev-parse").Arg("--path-format=absolute").Arg(gitRevArgs...)
if dir != "" {
gitRevParse.Dir(dir)
}
Expand Down
13 changes: 2 additions & 11 deletions pkg/commands/git_commands/repo_paths_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,13 @@ func TestGetRepoPaths(t *testing.T) {
runner := oscommands.NewFakeRunner(t)
cmd := oscommands.NewDummyCmdObjBuilder(runner)

version, err := GetGitVersion(oscommands.NewDummyOSCommand())
if err != nil {
t.Fatal(err)
}

getRevParseArgs := func() []string {
args := []string{"rev-parse"}
if version.IsAtLeast(2, 31, 0) {
args = append(args, "--path-format=absolute")
}
return args
return []string{"rev-parse", "--path-format=absolute"}
}
// prepare the filesystem for the scenario
s.BeforeFunc(runner, getRevParseArgs)

repoPaths, err := GetRepoPathsForDir("", cmd, version)
repoPaths, err := GetRepoPathsForDir("", cmd)

// check the error and the paths
if s.Err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/git_commands/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (self *SyncCommands) fetchCommandBuilder(fetchAll bool) *GitCommandBuilder
ArgIf(fetchAll, "--all").
// avoid writing to .git/FETCH_HEAD; this allows running a pull
// concurrently without getting errors
ArgIf(self.version.IsAtLeast(2, 29, 0), "--no-write-fetch-head")
Arg("--no-write-fetch-head")
}

func (self *SyncCommands) FetchCmdObj(task gocui.Task) *oscommands.CmdObj {
Expand Down
8 changes: 4 additions & 4 deletions pkg/commands/git_commands/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestSyncFetch(t *testing.T) {
test: func(cmdObj *oscommands.CmdObj) {
assert.True(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"})
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--no-write-fetch-head"})
},
},
{
Expand All @@ -128,7 +128,7 @@ func TestSyncFetch(t *testing.T) {
test: func(cmdObj *oscommands.CmdObj) {
assert.True(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"})
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all", "--no-write-fetch-head"})
},
},
}
Expand Down Expand Up @@ -157,7 +157,7 @@ func TestSyncFetchBackground(t *testing.T) {
test: func(cmdObj *oscommands.CmdObj) {
assert.False(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"})
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--no-write-fetch-head"})
},
},
{
Expand All @@ -166,7 +166,7 @@ func TestSyncFetchBackground(t *testing.T) {
test: func(cmdObj *oscommands.CmdObj) {
assert.False(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"})
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all", "--no-write-fetch-head"})
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/git_commands/worktree_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
if worktree.IsPathMissing {
return
}
gitDir, err := callGitRevParseWithDir(self.cmd, self.version, worktree.Path, "--absolute-git-dir")
gitDir, err := callGitRevParseWithDir(self.cmd, worktree.Path, "--absolute-git-dir")
if err != nil {
self.Log.Warnf("Could not find git dir for worktree %s: %v", worktree.Path, err)
return
Expand Down
6 changes: 1 addition & 5 deletions pkg/commands/git_commands/worktree_loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,7 @@ branch refs/heads/mybranch-worktree
}

getRevParseArgs := func() []string {
args := []string{"rev-parse"}
if version.IsAtLeast(2, 31, 0) {
args = append(args, "--path-format=absolute")
}
return args
return []string{"rev-parse", "--path-format=absolute"}
}

s.before(runner, fs, getRevParseArgs)
Expand Down
2 changes: 1 addition & 1 deletion pkg/i18n/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,7 @@ func EnglishTranslationSet() *TranslationSet {
CreateNewBranchFromCommit: "Create new branch off of commit",
BuildingPatch: "Building patch",
ViewCommits: "View commits",
MinGitVersionError: "Git version must be at least 2.22 (i.e. from 2019 onwards). Please upgrade your git version. Alternatively raise an issue at https://github.com/jesseduffield/lazygit/issues for lazygit to be more backwards compatible.",
MinGitVersionError: "Git version must be at least 2.32 (i.e. from 2021 onwards). Please upgrade your git version. Alternatively raise an issue at https://github.com/jesseduffield/lazygit/issues for lazygit to be more backwards compatible.",
RunningCustomCommandStatus: "Running custom command",
SubmoduleStashAndReset: "Stash uncommitted submodule changes and update",
AndResetSubmodules: "And reset submodules",
Expand Down
28 changes: 13 additions & 15 deletions pkg/integration/tests/commit/create_amend_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,18 @@ var CreateAmendCommit = NewIntegrationTest(NewIntegrationTestArgs{
Contains("commit 01"),
)

if t.Git().Version().IsAtLeast(2, 32, 0) { // Support for auto-squashing "amend!" commits was added in git 2.32.0
t.Views().Commits().
Press(keys.Commits.SquashAboveCommits).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Apply fixup commits")).
Select(Contains("Above the selected commit")).
Confirm()
}).
Lines(
Contains("commit 03"),
Contains("commit 02 amended").IsSelected(),
Contains("commit 01"),
)
}
t.Views().Commits().
Press(keys.Commits.SquashAboveCommits).
Tap(func() {
t.ExpectPopup().Menu().
Title(Equals("Apply fixup commits")).
Select(Contains("Above the selected commit")).
Confirm()
}).
Lines(
Contains("commit 03"),
Contains("commit 02 amended").IsSelected(),
Contains("commit 01"),
)
},
})
1 change: 0 additions & 1 deletion pkg/integration/tests/config/negative_refspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
var NegativeRefspec = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Having a config with a negative refspec",
ExtraCmdArgs: []string{},
GitVersion: AtLeast("2.29.0"),
SetupRepo: func(shell *Shell) {
shell.
SetConfig("remote.origin.fetch", "^refs/heads/test").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ var MoveToEarlierCommit = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Move a patch from a commit to an earlier commit",
ExtraCmdArgs: []string{},
Skip: false,
GitVersion: AtLeast("2.26.0"),
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ var MoveToNewCommitBefore = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Move a patch from a commit to a new commit before the original one",
ExtraCmdArgs: []string{},
Skip: false,
GitVersion: AtLeast("2.26.0"),
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateDir("dir")
Expand Down
Loading