Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions web/learn/concepts/git/git-rerere.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
sidebar_position: 6
---

import DefinitionCard from "@site/src/components/DefinitionCard";

# What is Git Rerere?

_Git rerere records how you resolved a merge conflict and reuses that resolution when the same conflict returns._

## Introduction

**Rerere** stands for reuse recorded resolution. When a merge or [rebase](./merge-vs-rebase) hits the same conflict again, Git can apply the resolution you already chose instead of asking you to edit the markers by hand.

That matters when a long-lived branch keeps meeting the same overlapping edits on `main`, or when you rebuild an integration branch after dropping one topic. You still review the result. You stop retyping the same fix.

## Understanding the Concept

Enable the feature with configuration:

```bash
git config --global rerere.enabled true
```

You can also enable it for one repository by creating `.git/rr-cache`. The config setting is clearer and applies everywhere you work.

When a conflict appears, Git stores the conflicted file state as a **preimage** under `.git/rr-cache/`. After you resolve the file and finish the merge or rebase, Git stores the resolved content as a **postimage**. Later conflicts that match the earlier conflicted state are resolved by a three-way merge of the recorded preimage, the recorded postimage, and the new conflicted file.

<DefinitionCard
term="Preimage"
definition="The conflicted file content, including conflict markers, that rerere records when an automerge first fails."
/>

<DefinitionCard
term="Postimage"
definition="The resolved file content that rerere records after you hand-resolve a conflict and complete the merge or rebase."
/>

{/* TODO: Add a diagram of conflicted file -> preimage in .git/rr-cache, hand resolve -> postimage, later identical conflict -> three-way reuse into the working tree. */}

Merge and rebase invoke rerere for you once it is enabled. You do not need to call `git rerere` on every conflict. Rerere updates the working tree file. It does not stage the resolution, so you still run `git add` after you verify the result.

| Artifact | Meaning |
| --- | --- |
| Preimage | Conflicted state with markers |
| Postimage | Hand-resolved file content |
| `.git/rr-cache/` | Per-repository cache of recorded resolutions |

## Applying It in Practice

Rebase a long-lived feature branch onto current `main`:

```bash
git fetch origin
git switch feature/long-lived
git rebase origin/main
```

When the rebase stops on a conflict, list the paths whose preimages rerere recorded:

```bash
git rerere status
```

Inspect the delta from the recorded conflict to your current working resolution before you stage:

```bash
git rerere diff
```

A typical first encounter prints `Recorded preimage for FILE`. After you resolve, stage, and continue, Git prints `Recorded resolution for FILE`. On a later rebase that hits a matching conflict, Git prints `Resolved FILE using previous resolution` and removes the conflict markers from the working tree. You still verify and `git add` before continuing:

```bash
git add path/to/file
git rebase --continue
```

If you abort a merge or rebase, Git clears the in-progress rerere metadata for that attempt. To drop a bad recorded resolution for selected paths, use:

```bash
git rerere forget path/to/file
```

Paths that still need a hand fix after autoresolve, including cases rerere cannot track such as conflicting submodules, show up with:

```bash
git rerere remaining
```

## Engineering Considerations

Rerere pays off when the same textual conflict returns across many updates. A long-lived feature branch rebased against a moving `main` often replays older commits through the same overlapped hunks. Without a cache, you resolve those hunks on every rebase. With rerere enabled, you resolve each recurring conflict once and let later rebases reuse the postimage.

A common alternative to repeated merges is a test merge into current `main`. You resolve, verify, then reset the merge so the branch history stays free of intermediate merge commits. When you later rebase onto `main` or perform the final merge, the earlier postimage often applies again. That is how a conflicted merge can become a linear rebase without redoing the same hand edits.

Treat an autoresolved file like any other conflict resolution. Read the combined diff, run the tests that cover the overlapped code, and only then stage. A reused postimage is a prior judgment applied to new parents. The surrounding code may have changed enough that the old answer is wrong. For agent-produced conflicts, keep the same review bar described in [How to Fix Merge Conflicts Created by Coding Agents](/learn/how-to/merge-conflicts-with-coding-agents).

Rerere depends on conflict markers in the file. If the file already contains lines that look like markers, recording can fail. Raise `conflict-marker-size` in `.gitattributes` for those paths when that happens.

## Scaling and Operations

Teams that merge many topic branches into one integration branch for testing benefit from the same cache. If the aggregate build fails, you rewind the integration tip, drop the bad topic, and merge the remaining branches again. Rerere re-applies the resolutions you already paid for on the branches that remain.

Prune stale cache entries with:

```bash
git rerere gc
```

By default, `gc.rerereResolved` keeps completed resolutions for 60 days and `gc.rerereUnresolved` drops abandoned preimages after 15 days. Adjust those values when your integration cycle is longer than the defaults.

Do not treat `.git/rr-cache` as shared team state unless you deliberately distribute it. Each clone records its own resolutions. Enable `rerere.enabled` in shared developer setup docs so every machine that rebases the same [pull-request stacks](./stacked-prs) builds a useful cache.

## Next Steps

- [Cherry-pick vs Rebase](./cherry-pick-vs-rebase): distinguish selected patch copying from branch rewriting
- [Stacked PR Workflow](/learn/workflows/git/stacked-pr): apply rebasing to a pull-request stack
- [Auto-Rebasing AI Workspaces](/learn/how-to/auto-rebase-ai-branches): keep dependent branches current without treating a rebase as approval
- [Parallel Development Workflow](/learn/workflows/git/parallel-development): combine concurrent branches with an integration policy
5 changes: 5 additions & 0 deletions web/learn/concepts/git/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ Start with Git's data model, then learn how to manage parallel and dependent bra
href: "/learn/concepts/git/merge-vs-rebase",
label: "Merge vs Rebase",
},
{
type: "link",
href: "/learn/concepts/git/git-rerere",
label: "What is Git Rerere?",
},
{
type: "link",
href: "/learn/concepts/git/cherry-pick-vs-rebase",
Expand Down
2 changes: 1 addition & 1 deletion web/learn/concepts/git/merge-vs-rebase.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Each option throws away something different. Merge commits keep the shape. Squas

Block force pushes on shared branches. If feature branches can be rewritten, say so out loud, so reviewers know whether it is safe to build on one.

After a big rebase, use `git range-diff` to check the rewritten series still says what you meant. Run the full test suite after you resolve conflicts, whichever strategy you picked.
After a big rebase, use `git range-diff` to check the rewritten series still says what you meant. Run the full test suite after you resolve conflicts, whichever strategy you picked. When the same conflict keeps returning on a long-lived branch, [git rerere](./git-rerere) can reuse the resolution you already chose.

## Next Steps

Expand Down
3 changes: 2 additions & 1 deletion web/learn/how-to/auto-rebase-ai-branches.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ After every rebase:

1. Read the new diff against the intended base.
2. Re-run the relevant tests.
3. Treat conflict resolutions as new code under review.
3. Treat conflict resolutions as new code under review. [Git rerere](/learn/concepts/git/git-rerere) can reuse a prior resolution across rebases, and that reused result still needs the same review.

```bash
git diff origin/main...HEAD
Expand Down Expand Up @@ -103,4 +103,5 @@ Pending working-copy edits can block or complicate synchronization. Commit, move
- [What Are Stacked PRs in AI-Assisted Development](/learn/stacked-prs)
- [How to Fix Merge Conflicts Created by Coding Agents](/learn/how-to/merge-conflicts-with-coding-agents)
- [Merge vs Rebase](/learn/concepts/git/merge-vs-rebase)
- [What is Git Rerere?](/learn/concepts/git/git-rerere)
- [Workspaces](/docs/concepts/workspaces)
3 changes: 3 additions & 0 deletions web/learn/how-to/merge-conflicts-with-coding-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ git rebase --abort

Restarting the agent on current `main` can be cheaper than preserving a small obsolete patch. Compare old and new intended behavior before discarding work.

When the same conflict returns across many rebases, enable [git rerere](/learn/concepts/git/git-rerere) so Git can reuse a resolution you already chose. Still review the autoresolved file before you continue.

## Agent-assisted resolution

You can ask an agent to resolve conflicts, but you must review the result. Provide:
Expand Down Expand Up @@ -110,4 +112,5 @@ When a bookmark conflict appears after remote updates, resolve it from the botto
- [Auto-Rebasing AI Workspaces](/learn/how-to/auto-rebase-ai-branches)
- [Parallel Coding Agents Without Branch Chaos](/learn/parallel-coding-agents)
- [Merge vs Rebase](/learn/concepts/git/merge-vs-rebase)
- [What is Git Rerere?](/learn/concepts/git/git-rerere)
- [Merging Workspaces](/docs/tutorials/merging-workspaces)
Loading