[PATCH v6 2/3] replay: resolve the replay base outside pick_regular_commit()
From: Toon Claes <hidden>
Date: 2026-07-02 17:59:06
Subsystem:
the rest · Maintainer:
Linus Torvalds
Depending on what gets passed into the function pick_regular_commit(), it decides the new base for the replayed commit. It first tries to find the replayed results of `pickme`'s parent in the `replayed_commits` map. If not found, it falls back to `onto`. When using git-replay(1) with --onto, the fallback is the revision passed in with this option, but when using --revert, the fallback is `last_commit`. It's rather confusing the base is decided partly inside pick_regular_commit() and partly by its caller. Move the base selection completely into the caller: replay_revisions(). This bundles all the logic of deciding on the base together. Also, this reduces the number of parameters of pick_regular_commit(), making it's interface cleaner. This refactoring doesn't bring any behavior changes. Signed-off-by: Toon Claes <redacted> --- replay.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/replay.c b/replay.c
index b9f8fc47ce..5aee0eafbc 100644
--- a/replay.c
+++ b/replay.c@@ -280,25 +280,19 @@ static void put_mapped_commit(kh_oid_map_t *replayed_commits, static struct commit *pick_regular_commit(struct repository *repo, struct commit *pickme, - kh_oid_map_t *replayed_commits, - struct commit *onto, + struct commit *replayed_base, struct merge_options *merge_opt, struct merge_result *result, enum replay_mode mode, enum replay_empty_commit_action empty) { - struct commit *base, *replayed_base; struct tree *pickme_tree, *base_tree, *replayed_base_tree; - if (pickme->parents) { - base = pickme->parents->item; - base_tree = repo_get_commit_tree(repo, base); - } else { - base = NULL; + if (pickme->parents) + base_tree = repo_get_commit_tree(repo, pickme->parents->item); + else base_tree = lookup_tree(repo, repo->hash_algo->empty_tree); - } - replayed_base = get_mapped_commit(replayed_commits, base, onto); replayed_base_tree = repo_get_commit_tree(repo, replayed_base); pickme_tree = repo_get_commit_tree(repo, pickme);
@@ -439,12 +433,26 @@ int replay_revisions(struct rev_info *revs, while ((commit = get_revision(revs))) { const struct name_decoration *decoration; + /* + * Decide where to replay this commit on. + * If the parent commit was replayed already, the replayed result + * can be found in `replayed_commits`. Otherwise fall back to `onto`. + * When reverting, commits are replayed in reverse order and thus + * its parent isn't replayed yet. Therefore revert commits are + * always replayed onto `last_commit`. + */ + struct commit *parent = commit->parents ? commit->parents->item : NULL; + struct commit *base = get_mapped_commit(replayed_commits, parent, onto); + + if (mode == REPLAY_MODE_REVERT) + base = last_commit; + if (commit->parents && commit->parents->next) die(_("replaying merge commits is not supported yet!")); - last_commit = pick_regular_commit(revs->repo, commit, replayed_commits, - mode == REPLAY_MODE_REVERT ? last_commit : onto, - &merge_opt, &result, mode, opts->empty); + last_commit = pick_regular_commit(revs->repo, commit, base, + &merge_opt, &result, + mode, opts->empty); if (!last_commit) break;
--
2.53.0.1323.g189a785ab5