git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 2/2] replay: add --revert mode to reverse commit changes

From
Siddharth Asthana <siddharthasthana31@gmail.com>
Date
Mar 6, 2026, 05:28 UTC
Message-ID
<77fa95d9-3ea3-4a32-b8fa-22c05c048160@gmail.com>
In-Reply-To
<405b0d34-c2ad-498d-93a1-2e7925ae11f1@gmail.com>
On 26/02/26 20:15, Phillip Wood wrote:
Show 44 quoted lines
> Hi Siddharth
> 
> On 18/02/2026 23:42, Siddharth Asthana wrote:
>> @@ -42,6 +42,25 @@ The history is replayed on top of the <branch> and 
>> <branch> is updated to
>>   point at the tip of the resulting history. This is different from 
>> `--onto`,
>>   which uses the target only as a starting point without updating it.
>> +--revert <branch>::
>> +    Starting point at which to create the reverted commits; must be a
>> +    branch name.
>> ++
>> +When `--revert` is specified, the commits in the revision range are 
>> reverted
>> +(their changes are undone) and the reverted commits are created on 
>> top of
>> +<branch>. The <branch> is then updated to point at the new commits. 
>> This is
>> +the same as running `git revert <revision-range>` but does not update 
>> the
>> +working tree.
>> ++
>> +The commit messages follow `git revert` conventions: they are 
>> prefixed with
>> +"Revert" and include "This reverts commit <hash>." When reverting a 
>> commit
>> +whose message starts with "Revert", the new message uses "Reapply" 
>> instead.
>> +Unlike cherry-pick which preserves the original author, revert 
>> commits use
>> +the current user as the author, matching the behavior of `git revert`.
>> ++
>> +This option is mutually exclusive with `--onto` and `--advance`. It 
>> is also
>> +incompatible with `--contained` (which is a modifier for `--onto` only).
> 
> We seem to have lost
> 
>      NOTE: For reverting an entire merge request as a single commit
>      (rather than commit-by-commit), consider using `git merge-tree
>      --merge-base $TIP HEAD $BASE` which can avoid unnecessary merge
>      conflicts.
> 
> from V2 which is a shame.

Yeah, I dropped it during the v3 cleanup when I was trimming the example text. will add it back.

Show 5 quoted lines
> 
> I do think we should seriously consider reverting commits in the reverse 
> order that they were created (i.e. do not set '--reverse' when setting 
> up the rev-list options) to reduce the likely-hood of conflicts when 
> reverting a sequence of commits.

Good catch. sequencer.c does exactly this in prepare_revs() -- it only sets reverse for REPLAY_PICK, not REPLAY_REVERT, so git revert processes newest-first.

The complication in replay is that pick_regular_commit() chains commits through mapped_commit(base, onto). With oldest-first, the parent is always already in replayed_commits so the chain works. With newest-first, the parent hasn't been processed yet and mapped_commit() falls back to onto -- so each revert be independently based on the original branch tip instead of chaining.

The fix is straightforward: for revert mode, pass last_commit instead of onto as the fallback in the main loop:

	pick_regular_commit(repo, commit, replayed_commits,
                         mode == REPLAY_MODE_REVERT ? last_commit : onto,
                         &merge_opt, &result, mode);

That way each revert builds on the previous one regardless of walk order. I will do this in v4 together with skipping the reverse=1 override for revert mode.

Show 14 quoted lines
> 
>> @@ -152,6 +172,15 @@ all commits they have since `base`, playing them 
>> on top of
>>   `origin/main`. These three branches may have commits on top of `base`
>>   that they have in common, but that does not need to be the case.
>> +To revert commits on a branch:
>> +
>> +------------
>> +$ git replay --revert main main~2..main
> 
> It might be more realistic to revert some commits from a different 
> branch, for example
> 
>    git replay --revert main topic~2..topic

Makes sense. v2 had `git replay --revert main feature~2..feature` for this reason but I simplified it in v3. I will go back to something like your example:

	git replay --revert main topic2..topic
Show 15 quoted lines
> 
>> +static void set_up_branch_mode(struct repository *repo,
>> +                   char **branch_name,
>> +                   const char *option_name,
>> +                   struct ref_info *rinfo,
>> +                   struct commit **onto)
>> [...]
>> +    if (rinfo->positive_refexprs > 1)
>> +        die(_("cannot %s target with multiple sources because 
>> ordering would be ill-defined"),
>> +            option_name + 2); /* skip "--" prefix */
> 
> This is a bit of a nasty hack as it stuffs an English word into the 
> middle of a translated sentence. Using the option name as below might be 
> nicer
Agreed, will use your suggested form:
	die(_("'%s' cannot be used with multiple revision ranges "
           "because the ordering would be ill-defined"), option_name);
Show 12 quoted lines
> 
>      die(_("'%s' cannot be used with multiple revision ranges because 
> the ordering would be ill defined", option_name);
>> @@ -226,25 +269,46 @@ static struct commit *pick_regular_commit(struct 
>> repository *repo,
>>  [...]
>> -    /* Drop commits that become empty */
>> -    if (oideq(&replayed_base_tree->object.oid, &result->tree- 
>> >object.oid) &&
>> +    /* Drop commits that become empty (only for picks) */
> 
> Why? What's the advantage in creating empty revert commits?

Consistency with git revert, which doesn't silently drop empty reverts either -- it stops and asks the user to deal with it. Since replay is non-interactive and can't prompt, I kept them rather than silently dropping, to avoid hiding that something unexpected happened.

That being said, I don't feel strong about it. If you think dropping is the better default for replay, I am happy to change it. Or we could error out (exit code 1) like we do for conflicts?

Thanks, Siddharth

Show 8 quoted lines
> 
>> +    if (mode == REPLAY_MODE_PICK &&
>> +        oideq(&replayed_base_tree->object.oid, &result->tree- 
>> >object.oid) &&
> 
> Thanks
> 
> Phillip
Previous: Phillip WoodNext: Phillip Wood
Message 65 of 96 in “replay: add --revert option to reverse commit changes”
  1. 0/1 replay: add --revert option to reverse commit changesSiddharth Asthana, Nov 25, 2025
  2. 1/1 replay: add --revert option to reverse commit changesSiddharth Asthana, Nov 25, 2025
  3. Junio C HamanoNov 25, 2025
  4. Junio C HamanoNov 25, 2025
  5. Junio C HamanoNov 25, 2025
  6. Junio C HamanoNov 25, 2025
  7. Siddharth AsthanaNov 26, 2025
  8. Siddharth AsthanaNov 26, 2025
  9. Siddharth AsthanaNov 26, 2025
  10. Junio C HamanoNov 26, 2025
  11. Siddharth AsthanaNov 27, 2025
  12. Phillip WoodNov 26, 2025
  13. Elijah NewrenNov 26, 2025
  14. Junio C HamanoNov 26, 2025
  15. Junio C HamanoNov 26, 2025
  16. Elijah NewrenNov 26, 2025
  17. Junio C HamanoNov 26, 2025
  18. Elijah NewrenNov 26, 2025
  19. Siddharth AsthanaNov 26, 2025
  20. Siddharth AsthanaNov 26, 2025
  21. Phillip WoodNov 27, 2025
  22. Siddharth AsthanaNov 27, 2025
  23. Johannes SchindelinNov 25, 2025
  24. Junio C HamanoNov 25, 2025
  25. Siddharth AsthanaNov 26, 2025
  26. Junio C HamanoNov 26, 2025
  27. Siddharth AsthanaNov 27, 2025
  28. Junio C HamanoNov 27, 2025
  29. Elijah NewrenNov 28, 2025
  30. Siddharth AsthanaNov 28, 2025
  31. Junio C HamanoNov 28, 2025
  32. Elijah NewrenNov 28, 2025
  33. Junio C HamanoNov 28, 2025
  34. Elijah NewrenNov 28, 2025
  35. Junio C HamanoNov 29, 2025
  36. 0/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Dec 2, 2025
  37. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Dec 2, 2025
  38. Patrick SteinhardtDec 5, 2025
  39. Siddharth AsthanaDec 7, 2025
  40. Patrick SteinhardtDec 8, 2025
  41. Toon ClaesFeb 11, 2026
  42. Patrick SteinhardtFeb 11, 2026
  43. Kristoffer HaugsbakkFeb 11, 2026
  44. Junio C HamanoFeb 11, 2026
  45. Siddharth AsthanaFeb 18, 2026
  46. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Dec 2, 2025
  47. Patrick SteinhardtDec 5, 2025
  48. Siddharth AsthanaDec 7, 2025
  49. Phillip WoodDec 16, 2025
  50. 0/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Feb 18, 2026
  51. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Feb 18, 2026
  52. Toon ClaesFeb 20, 2026
  53. Junio C HamanoFeb 25, 2026
  54. Siddharth AsthanaMar 6, 2026
  55. Siddharth AsthanaMar 6, 2026
  56. Phillip WoodFeb 26, 2026
  57. Siddharth AsthanaMar 6, 2026
  58. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Feb 18, 2026
  59. Toon ClaesFeb 20, 2026
  60. Junio C HamanoFeb 20, 2026
  61. Christian CouderFeb 23, 2026
  62. Toon ClaesFeb 23, 2026
  63. Siddharth AsthanaMar 6, 2026
  64. Phillip WoodFeb 26, 2026
  65. Siddharth AsthanaMar 6, 2026
  66. Phillip WoodMar 6, 2026
  67. Siddharth AsthanaMar 6, 2026
  68. 0/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 13, 2026
  69. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Mar 13, 2026
  70. Junio C HamanoMar 13, 2026
  71. Toon ClaesMar 16, 2026
  72. Phillip WoodMar 16, 2026
  73. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 13, 2026
  74. Phillip WoodMar 16, 2026
  75. Toon ClaesMar 16, 2026
  76. Phillip WoodMar 17, 2026
  77. Phillip WoodMar 16, 2026
  78. Toon ClaesMar 16, 2026
  79. 0/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 24, 2026
  80. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Mar 24, 2026
  81. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 24, 2026
  82. Junio C HamanoMar 25, 2026
  83. Toon ClaesMar 25, 2026
  84. Siddharth AsthanaMar 25, 2026
  85. Phillip WoodMar 25, 2026
  86. Siddharth AsthanaMar 25, 2026
  87. 0/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 25, 2026
  88. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Mar 25, 2026
  89. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 25, 2026
  90. Tian YuchenMar 28, 2026
  91. Siddharth AsthanaMar 29, 2026
  92. Tian YuchenMar 30, 2026
  93. Toon ClaesMar 31, 2026
  94. Toon ClaesMar 31, 2026
  95. 1/2 sequencer: extract revert message formatting into shared functionSiddharth Asthana, Mar 25, 2026
  96. 2/2 replay: add --revert mode to reverse commit changesSiddharth Asthana, Mar 25, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.