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

@ -44,6 +44,7 @@ import (
webhook_service "forgejo.org/services/webhook"
"forgejo.org/tests"
"github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -306,9 +307,22 @@ func TestCantMergeConflict(t *testing.T) {
require.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrMergeConflicts(err), "Merge error is not a conflict error")
err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
require.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error")
t.Run("Git version with replay", func(t *testing.T) {
require.NoError(t, git.CheckGitVersionAtLeast("2.44"))
err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
require.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error")
})
t.Run("Git version without replay", func(t *testing.T) {
oldVersion, err := version.NewVersion("2.43.0")
require.NoError(t, err)
defer test.MockVariableValue(&git.GitVersion, oldVersion)()
err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
require.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error")
})
gitRepo.Close()
})
}