Files
git/replay.h
Siddharth Asthana f79189a653 replay: add --revert mode to reverse commit changes
Add a `--revert <branch>` mode to git replay that undoes the changes
introduced by the specified commits. Like --onto and --advance, --revert
is a standalone mode: it takes a branch argument and updates that branch
with the newly created revert commits.

At GitLab, we need this in Gitaly for reverting commits directly on bare
repositories without requiring a working tree checkout.

The approach is the same as sequencer.c's do_pick_commit() -- cherry-pick
and revert are just the same three-way merge with swapped arguments:

  - Cherry-pick: merge(ancestor=parent, ours=current, theirs=commit)
  - Revert: merge(ancestor=commit, ours=current, theirs=parent)

We swap the base and pickme trees passed to merge_incore_nonrecursive()
to reverse the diff direction.

Revert commit messages follow the usual git revert conventions: prefixed
with "Revert" (or "Reapply" when reverting a revert), and including
"This reverts commit <hash>.". The author is set to the current user
rather than preserving the original author, matching git revert behavior.

Helped-by: Christian Couder <christian.couder@gmail.com>
Helped-by: Patrick Steinhardt <ps@pks.im>
Helped-by: Elijah Newren <newren@gmail.com>
Helped-by: Phillip Wood <phillip.wood123@gmail.com>
Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20 09:31:18 -08:00

69 lines
1.8 KiB
C

#ifndef REPLAY_H
#define REPLAY_H
#include "hash.h"
struct repository;
struct rev_info;
/*
* A set of options that can be passed to `replay_revisions()`.
*/
struct replay_revisions_options {
/*
* Starting point at which to create the new commits; must be a branch
* name. The branch will be updated to point to the rewritten commits.
* This option is mutually exclusive with `onto` and `revert`.
*/
const char *advance;
/*
* Starting point at which to create the new commits; must be a
* committish. References pointing at decendants of `onto` will be
* updated to point to the new commits.
*/
const char *onto;
/*
* Starting point at which to create revert commits; must be a branch
* name. The branch will be updated to point to the revert commits.
* This option is mutually exclusive with `onto` and `advance`.
*/
const char *revert;
/*
* Update branches that point at commits in the given revision range.
* Requires `onto` to be set.
*/
int contained;
};
/* This struct is used as an out-parameter by `replay_revisions()`. */
struct replay_result {
/*
* The set of reference updates that are caused by replaying the
* commits.
*/
struct replay_ref_update {
char *refname;
struct object_id old_oid;
struct object_id new_oid;
} *updates;
size_t updates_nr, updates_alloc;
};
void replay_result_release(struct replay_result *result);
/*
* Replay a set of commits onto a new location. Leaves both the working tree,
* index and references untouched. Reference updates caused by the replay will
* be recorded in the `updates` out pointer.
*
* Returns 0 on success, 1 on conflict and a negative error code otherwise.
*/
int replay_revisions(struct rev_info *revs,
struct replay_revisions_options *opts,
struct replay_result *out);
#endif