feat: use git-replay for rebasing (#7527)
Some checks are pending
/ release (push) Waiting to run
testing / backend-checks (push) Has been skipped
testing / frontend-checks (push) Has been skipped
testing / test-unit (push) Has been skipped
testing / test-e2e (push) Has been skipped
testing / test-mysql (push) Has been skipped
testing / test-pgsql (push) Has been skipped
testing / test-sqlite (push) Has been skipped
testing / test-remote-cacher (redis) (push) Has been skipped
testing / test-remote-cacher (valkey) (push) Has been skipped
testing / test-remote-cacher (garnet) (push) Has been skipped
testing / test-remote-cacher (redict) (push) Has been skipped
testing / security-check (push) Has been skipped

Closes #7525

This is better for performance, because it can do more work in-memory. It also preserves unknown headers, which can be important for some clients. For example, Jujutsu uses a non-standard "change-id" header to track commits across rebase and amend, but regular git-rebase drops such unknown headers.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7527
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Remo Senekowitsch <remo@buenzli.dev>
Co-committed-by: Remo Senekowitsch <remo@buenzli.dev>
This commit is contained in:
Remo Senekowitsch 2025-04-29 20:51:56 +00:00 committed by Gusted
parent 32e64ccd34
commit ec076e66d8
4 changed files with 94 additions and 18 deletions

View file

@ -40,13 +40,13 @@ var (
HasSSHExecutable bool
gitVersion *version.Version
GitVersion *version.Version
)
// loadGitVersion returns current Git version from shell. Internal usage only.
func loadGitVersion() error {
// doesn't need RWMutex because it's executed by Init()
if gitVersion != nil {
if GitVersion != nil {
return nil
}
stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil)
@ -62,7 +62,7 @@ func loadGitVersion() error {
versionString := fields[2]
var err error
gitVersion, err = version.NewVersion(versionString)
GitVersion, err = version.NewVersion(versionString)
return err
}
@ -88,7 +88,7 @@ func SetExecutablePath(path string) error {
return err
}
if gitVersion.LessThan(versionRequired) {
if GitVersion.LessThan(versionRequired) {
moreHint := "get git: https://git-scm.com/downloads"
if runtime.GOOS == "linux" {
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
@ -97,7 +97,7 @@ func SetExecutablePath(path string) error {
moreHint = "get git: https://git-scm.com/downloads/linux and https://ius.io"
}
}
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", gitVersion.Original(), RequiredVersion, moreHint)
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", GitVersion.Original(), RequiredVersion, moreHint)
}
return nil
@ -105,11 +105,11 @@ func SetExecutablePath(path string) error {
// VersionInfo returns git version information
func VersionInfo() string {
if gitVersion == nil {
if GitVersion == nil {
return "(git not found)"
}
format := "%s"
args := []any{gitVersion.Original()}
args := []any{GitVersion.Original()}
// Since git wire protocol has been released from git v2.18
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
format += ", Wire Protocol %s Enabled"
@ -346,8 +346,8 @@ func CheckGitVersionAtLeast(atLeast string) error {
if err != nil {
return err
}
if gitVersion.Compare(atLeastVersion) < 0 {
return fmt.Errorf("installed git binary version %s is not at least %s", gitVersion.Original(), atLeast)
if GitVersion.Compare(atLeastVersion) < 0 {
return fmt.Errorf("installed git binary version %s is not at least %s", GitVersion.Original(), atLeast)
}
return nil
}
@ -361,8 +361,8 @@ func CheckGitVersionEqual(equal string) error {
if err != nil {
return err
}
if !gitVersion.Equal(atLeastVersion) {
return fmt.Errorf("installed git binary version %s is not equal to %s", gitVersion.Original(), equal)
if !GitVersion.Equal(atLeastVersion) {
return fmt.Errorf("installed git binary version %s is not equal to %s", GitVersion.Original(), equal)
}
return nil
}