49

As I understood, it is useful for the synchronization of projects through the saving of conflict resolution information, but it is not entirely clear to me how to use and configure it.

I want to configure for my continuous integration (CI) environment. Is it recommended do this?

Please don't mark a duplicate with this other question: Are there any downsides to enabling git rerere?. Because my doubt isn't related to "So is there any downside to enabling rerere?. What potential problems can it cause that would not otherwise occur?"

Carlos Laspina
  • 2,013
  • 4
  • 27
  • 44
  • 1
    Possible duplicate of [Are there any downsides to enabling git rerere?](https://stackoverflow.com/questions/5519244/are-there-any-downsides-to-enabling-git-rerere) – mkrieger1 Mar 26 '18 at 21:56

3 Answers3

77

What is git rerere?

As the documentation notes, rerere stands for reuse recorded resolution.

That doesn't really explain what it is, though. It's worth adding first, here, that git rerere itself—the command—is not something you have to run. It has just six subcommands: clear, forget, diff, status, remaining, and gc. None of these record or reuse a resolution—in fact, git rerere clear and git rerere forget <path> just discard some recorded resolutions. The gc command is similar, but refers to ones that are old, rather than current ones.

Most of the work happens from the setting of rerere.enabled (which makes Git run git rerere, with no subcommand, for you, at the appropriate times). You can run git rerere with no subcommands yourself, but this doesn't really do anything important since Git will do that on its own.

git config rerere.enabled true

Once you have set rerere.enabled, when Git does a merge—any merge, including those from git am and git rebase and git cherry-pick and so on, not just those from git merge itself—and hits a conflict, Git will:

  1. record (once the merge-as-a-verb hits them) the conflicting diff hunks;
  2. wait for you to resolve them manually;
  3. record (at git commit time) what you did to resolve them.

There's a step missing here, which is why this is numbered starting at 2. Step 1 is:

  1. check for previous recorded resolutions for these conflicts: if they exist, use them to resolve those conflicts automatically.

If the recorded resolutions completely resolve the conflicts, steps 2-4 become redundant. Git may still run them all (I'm not sure that it does) to update the timestamps on the recorded resolutions.

Summary

Once you set rerere.enabled, it's the act of merging itself that both creates the conflicts and (because it automatically runs git rerere with no arguments) records them and then tries to re-use any existing recorded resolutions. It's the act of committing itself that records the final resolutions (because Git automatically runs git rerere again for you). So it is all automatic—you just need to make sure, by running your own git diff commands, that your previous re-used resolutions are correct. If not, just fix them files, add, and commit as usual, and Git will replace the recorded resolutions with the new ones.

Note that you must still git add and git commit! You should always inspect the merge results (and/or run tests)—though you should do this always, regardless of your rerere.enabled setting.

As VonC points out in a comment, if you have existing merge conflict resolutions you did not record earlier, you can "train" the rerere database on those resolutions. There is a contributed script in the Git source to do this; it's also available on-line.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 9
    "Once you set `rerere.enabled`"... well, yes, but don't forget you can train rerere on *past* conflict resolutions done when it was *not* yet enable. Either manually (https://stackoverflow.com/a/4155237/6309) or through the `contrib/rerere-train.sh` script (https://stackoverflow.com/a/45664714/6309) – VonC Mar 27 '18 at 06:21
  • 1
    Aha, the `train` script is the one I always wanted to have. – torek Mar 27 '18 at 14:26
  • Thank you for "record (**at git commit time**) what you did to resolve them." The `git help rerere` page isn't clear about when that happens. – LarsH Jun 02 '18 at 07:35
  • 1
    I cannot seem to get the rerere train script to work correctly. It just keeps asking me for my pin to sign what I believe is each and every commit available in the repo. This isn't really workable. I also don't see why it would need to do this as the commits shouldn't change here. – Martijn Otto Mar 01 '19 at 13:47
  • 1
    @MartijnOtto the train script re-performs each merge, committing (then throwing away) the result. If you've set Git to demand GPG signatures on each commit, you'll have to sign all these new merge commits. The script could stand to disable signing while it does this training. You might submit that as a fix to either the Git mailing list, or the author of the script. – torek Mar 01 '19 at 16:42
  • will my resolutions get recorded if I enable rerere after running `git merge` but before `git add & git commit`? – zaabson Jun 16 '22 at 13:40
  • 1
    @zaabson: no: the initial inputs need to be recorded and that happens at the time `git merge` stops with a conflict. You can abort the merge (`git merge --abort`) and then start it over; now that `rerere` is enabled, the *new* merge will stop with the same conflict(s) and this time, it will record them. If you've done a bunch of work to resolve them, you might want to save that work before you `git merge --abort`, of course. (I should also add that perhaps running `git rerere` with no arguments would suffice. I haven't tested this!) – torek Jun 16 '22 at 13:42
9

It makes no sense to enable rerere for your CI environment, because your CI environment should never be resolving merge conflicts in the first place. Why do you think you would want it there?

Marnen Laibow-Koser
  • 5,959
  • 1
  • 28
  • 33
1

I cannot seem to get the rerere train script to work correctly. It just keeps asking me for my pin to sign what I believe is each and every commit available in the repo.

It should ask you less with git 2.38 (Q3 2022): "rerere-train" script (in contrib/) used to honor commit.gpgSign while recreating the throw-away merges. This has been fixed.

See commit cc391fc (20 Jul 2022) by Celeste Liu (CoelacanthusHex).
(Merged by Junio C Hamano -- gitster -- in commit f0f9a03, 01 Aug 2022)

contrib/rerere-train: avoid useless gpg sign in training

Signed-off-by: Celeste Liu

Users may have configured "git merge"(man) to always require GPG signing the resulting commits.
We are not running "git merge" to re-create merge commits, but merely to replay merge conflicts, and we will immediately discard the resulting commits; there is no point in signing them.

Override such configuration that forces useless signing from the command line with the "--no-gpg-sign" option.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250