mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Merge remote-tracking branch 'Thecave3/rerere-doc' into integration_2026_w28
doc: add a Git guide (commit signing, branch management, rerere) (#202) Adds doc/git-guide.md, a single entry point for the practical Git knowledge needed to contribute to OAI: commit signing setup (DCO + verified commits), branch management (including fixup commits and --autosquash), submodules, recovering from mistakes, and reusing conflict resolutions with git rerere. This started as a rerere-only guide. Review discussion (@luispereira106, @rorsc, @sgarg00) converged on a broader scope: the Git how-tos are scattered across the documentation (signing in CONTRIBUTING.md, branch management in code-style-contrib.md), and configuring commit signing in particular was reported as hard to get right. This PR consolidates the how-tos in one guide while the policy documents stay authoritative for the rules. Single commit (review rounds squashed per the linear-history policy): - New doc/git-guide.md with sections on commit signing (moved from CONTRIBUTING.md, led by a copy-pasteable SSH recipe), branch management (moved from code-style-contrib.md; git switch, fixup/--autosquash, --fixup=amend:), submodules (unintended pointer-update pitfall), recovering from mistakes (restore/reset/reflog), and git rerere. - CONTRIBUTING.md keeps the normative DCO/Verified requirements and links to the guide; code-style-contrib.md keeps the workflow policy and links to the guide; doc/README.md lists the guide under Developer tools. - Cross-references (not moved, since they are coupled to their own docs): clang-format.md pre-commit hook, GET_SOURCES.md branch/tag model, doc_best_practices.md docs: commit prefix. - Small typo fix in the T tracer addconsoletrace.md documentation. Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org> Reviewed-by: Francesco Mani <email@francescomani.it> Reviewed-by: Shubhika Garg <shubhika.garg@openairinterface.org>
This commit is contained in:
112
CONTRIBUTING.md
112
CONTRIBUTING.md
@@ -30,114 +30,10 @@ Every pull request must pass two CI checks before it can be merged:
|
||||
|
||||
### Signing Commits
|
||||
|
||||
GitHub supports commit signing using either SSH keys or GPG keys.
|
||||
For more information, see the
|
||||
[GitHub documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits).
|
||||
|
||||
Before configuring commit signing:
|
||||
|
||||
- Generate an SSH key pair or GPG key pair.
|
||||
- Add your public key to your GitHub account.
|
||||
- Verify your GitHub email address (required for “Verified” commits to work).
|
||||
- If using SSH signing, ensure the key is registered in GitHub for:
|
||||
- Authentication (SSH and GPG keys)
|
||||
- Signing commits (Signing Keys)
|
||||
|
||||
> **NOTE:**
|
||||
> Adding an SSH key for repo access does not automatically enable commit signing.
|
||||
> The key must also be added under GitHub's Signing Keys settings.
|
||||
|
||||
|
||||
To ensure commits show as Verified on GitHub:
|
||||
|
||||
- Your `git config user.email` must match a GitHub email
|
||||
- That email must be verified in your GitHub account
|
||||
|
||||
For more information, see the
|
||||
[GitHub Docs](https://docs.github.com/en/account-and-profile/how-tos/email-preferences/verifying-your-email-address)
|
||||
|
||||
Configure your repository's `.git/config`:
|
||||
|
||||
```ini
|
||||
# Edit the git configuration
|
||||
|
||||
[user]
|
||||
name = YOUR NAME
|
||||
email = YOUR VERIFIED EMAIL ADDRESS
|
||||
|
||||
# REQUIRED for commit signing
|
||||
# Use ONE signing method (SSH or GPG)
|
||||
|
||||
signingkey = YOUR_SIGNING_KEY
|
||||
|
||||
# Examples:
|
||||
# SSH signing:
|
||||
# signingkey = ~/.ssh/id_ed25519.pub
|
||||
|
||||
# GPG signing:
|
||||
# signingkey = YOUR_GPG_KEY_ID
|
||||
|
||||
[gpg]
|
||||
# REQUIRED: defines signing method (SSH or GPG)
|
||||
|
||||
format = YOUR_SIGNING_FORMAT
|
||||
|
||||
# Examples:
|
||||
# SSH signing:
|
||||
# format = ssh
|
||||
|
||||
# GPG signing:
|
||||
# format = openpgp
|
||||
|
||||
[commit]
|
||||
gpgsign = true
|
||||
```
|
||||
|
||||
> The private key is used automatically by SSH/Git when signing commits (SSH only).
|
||||
|
||||
#### Verifying Signed Commits
|
||||
|
||||
You can verify that commits are properly signed locally using:
|
||||
|
||||
```bash
|
||||
git log --show-signature
|
||||
```
|
||||
|
||||
GitHub should also display a Verified badge next to signed commits once the
|
||||
signing key has been correctly configured in your account.
|
||||
|
||||
##### SSH Signature Verification (`allowed_signers`)
|
||||
|
||||
For SSH commit signing, local Git verification may require an `allowed_signers`
|
||||
file. This is only used for local verification in Git and is not required
|
||||
by GitHub.
|
||||
|
||||
If you see errors such as:
|
||||
|
||||
```text
|
||||
No principal matched
|
||||
Can't check signature
|
||||
error: gpg.ssh.allowedSignersFile needs to be configured
|
||||
```
|
||||
you may need to configure it.
|
||||
|
||||
Create the file and add your signing identity:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/git
|
||||
touch ~/.config/git/allowed_signers
|
||||
echo "user@example.com ssh-ed25519 AAAACexamplekeystringhere" > ~/.config/git/allowed_signers
|
||||
```
|
||||
|
||||
Enable it in local repository Git config:
|
||||
|
||||
```bash
|
||||
git config gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers
|
||||
```
|
||||
|
||||
> **NOTE:**
|
||||
> This is only for local Git signature verification and does not affect GitHub,
|
||||
> or remote repository behavior.
|
||||
GitHub supports commit signing using either SSH keys or GPG keys. For the
|
||||
step-by-step setup (key generation, Git configuration, registering the key on
|
||||
GitHub, and verifying signatures locally), see the
|
||||
[commit signing section of the Git guide](doc/git-guide.md#setting-up-commit-signing).
|
||||
|
||||
> **NOTE:** If your commits are not signed, the CI framework will not accept the PR.
|
||||
For more information regarding contribution guidelines
|
||||
|
||||
@@ -11,7 +11,7 @@ LOG_D(<component>,<format>,<argument>,...)
|
||||
LOG_T(<component>,<format>,<argument>,...)
|
||||
)
|
||||
```
|
||||
these macros are used in place of the printf C function. The additionnal ***component*** parameter identifies the functionnal module which generates the message. At run time, the message will only be printed if the configured log level for the component is greater or equal than the macro level used in the code.
|
||||
these macros are used in place of the printf C function. The additional ***component*** parameter identifies the functional module which generates the message. At run time, the message will only be printed if the configured log level for the component is greater or equal than the macro level used in the code.
|
||||
|
||||
| macro | level letter | level value | level name |
|
||||
|:---------|:---------------|:---------------|----------------:|
|
||||
|
||||
@@ -133,6 +133,9 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
|
||||
## Developer tools
|
||||
|
||||
- [code-style-contrib.md](./code-style-contrib.md): overall working practices, code style, and review process
|
||||
- [git-guide.md](./git-guide.md): Git how-tos — commit signing setup, branch
|
||||
management, submodules, recovering from mistakes, reusing conflict
|
||||
resolutions (rerere)
|
||||
- [cross-compile.md](./cross-compile.md): how to cross-compile OAI for ARM
|
||||
- [clang-format.md](./clang-format.md): how to format the code. See also the
|
||||
next entry for an error detection tool.
|
||||
|
||||
@@ -118,43 +118,12 @@ e.g., `v3.0`. We target to make releases bi-yearly.
|
||||
|
||||
### How to manage your own branch
|
||||
|
||||
Before starting to work, please make sure to branch off the latest `develop`
|
||||
branch. Make commits as appropriate.
|
||||
```bash
|
||||
$ git fetch origin
|
||||
$ git checkout develop
|
||||
$ git checkout -b my-new-feature # name as appropriate
|
||||
$ git add -p # add changes for change set 1, use `-p` to review what to include
|
||||
$ git commit # in the editor, describe your changes
|
||||
$ git add -p # add changes for change set 2
|
||||
$ git commit # in the editor, describe your changes
|
||||
```
|
||||
|
||||
Again, commit message should take multiple lines; after the initial title, a
|
||||
blank line should follow. Read the `DISCUSSION` section in `man git commit` for
|
||||
more information.
|
||||
|
||||
If your development takes longer, make sure to synchronize regularly with
|
||||
`origin/develop` using `git rebase`:
|
||||
```bash
|
||||
$ git fetch origin
|
||||
$ git rebase -i origin/develop
|
||||
```
|
||||
|
||||
If you do logical changes, you should not have to resolve the same conflicts
|
||||
over and over again. Note that if you jumped over multiple develop tags, you
|
||||
can also rebase in intermediate steps, in case you fear the differences might
|
||||
be too big.
|
||||
```
|
||||
$ git rebase -i 2023.w38
|
||||
$ git rebase -i 2023.w41
|
||||
$ git rebase -i develop
|
||||
```
|
||||
|
||||
Once you rebased, push the changes to the remote
|
||||
```
|
||||
$ git push origin my-new-feature --force-with-lease # force with lease let's you only overwrite what you also have locally in origin/my-new-feature
|
||||
```
|
||||
Branch off the latest `develop` branch before starting to work, keep your
|
||||
branch synchronized with `origin/develop` through regular rebases, and push
|
||||
with `--force-with-lease` after rebasing. The step-by-step commands — including
|
||||
how to rebase over multiple develop tags in intermediate steps and how to avoid
|
||||
resolving the same conflicts repeatedly with `git rerere` — are in the
|
||||
[branch management section of the Git guide](./git-guide.md#managing-your-own-branch).
|
||||
|
||||
### Use of git commit trailers
|
||||
|
||||
|
||||
390
doc/git-guide.md
Normal file
390
doc/git-guide.md
Normal file
@@ -0,0 +1,390 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
# Git guide
|
||||
|
||||
This guide collects the practical Git knowledge needed to contribute to OAI in
|
||||
one place: how to set up commit signing, how to manage and synchronize a
|
||||
feature branch, how to handle submodules, how to recover from common mistakes,
|
||||
and how to avoid resolving the same merge conflicts over and over. It is a
|
||||
how-to companion to the contribution *requirements*, which are
|
||||
defined in [CONTRIBUTING.md](../CONTRIBUTING.md) (CLA, DCO, verified commits)
|
||||
and [code-style-contrib.md](./code-style-contrib.md) (workflow, commit, and
|
||||
review policy).
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
## Setting up commit signing
|
||||
|
||||
Every commit in a pull request must pass two independent CI checks, described
|
||||
in [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines):
|
||||
|
||||
1. **[Developer Certificate of Origin (DCO)](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin)**:
|
||||
the commit message carries a `Signed-off-by:` trailer.
|
||||
2. **[Verified commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)**:
|
||||
the commit is cryptographically signed with an SSH or GPG key.
|
||||
|
||||
These are two different mechanisms: the sign-off is a line of text you add with
|
||||
`git commit -s`, the signature is created automatically by Git once signing is
|
||||
configured. You need both.
|
||||
|
||||
### Quick setup (SSH signing)
|
||||
|
||||
```bash
|
||||
# 1. Generate a key pair (skip if you already have one)
|
||||
ssh-keygen -t ed25519 -C "<your email>"
|
||||
|
||||
# 2. Configure Git to sign every commit with it
|
||||
git config --global user.name "<Your Name>"
|
||||
git config --global user.email "<your email>"
|
||||
git config --global gpg.format ssh
|
||||
git config --global user.signingkey ~/.ssh/id_ed25519.pub
|
||||
git config --global commit.gpgsign true
|
||||
```
|
||||
|
||||
> **NOTE:**
|
||||
> `--global` writes to `~/.gitconfig` and applies to every repository on the
|
||||
> machine. When working on a shared server (or with different identities in
|
||||
> different clones), drop `--global` to store the same settings in the current
|
||||
> repository's `.git/config` only.
|
||||
|
||||
Then print the public key with `cat ~/.ssh/id_ed25519.pub` and paste it into
|
||||
your GitHub account under *Settings → SSH and GPG keys → New SSH key*, choosing
|
||||
the key type **Signing Key**.
|
||||
|
||||
> **NOTE:**
|
||||
> Adding an SSH key for repository access does not automatically enable commit
|
||||
> signing. The key must also be added under GitHub's Signing Keys settings.
|
||||
|
||||
For commits to show as *Verified* on GitHub:
|
||||
|
||||
- your `git config user.email` must match an email of your GitHub account,
|
||||
- that email must be [verified in your GitHub account](https://docs.github.com/en/account-and-profile/how-tos/email-preferences/verifying-your-email-address),
|
||||
- and it must be the email address used for the CLA (see
|
||||
[CONTRIBUTING.md](../CONTRIBUTING.md)).
|
||||
|
||||
If you prefer GPG over SSH, set `gpg.format` to `openpgp` and `user.signingkey`
|
||||
to your GPG key ID instead; see the [GitHub documentation on signing
|
||||
commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)
|
||||
for the full walkthrough of both methods.
|
||||
|
||||
### Signing off your commits (DCO)
|
||||
|
||||
The `Signed-off-by:` trailer is added with the `-s`/`--signoff` flag:
|
||||
|
||||
```bash
|
||||
git commit -s # new commit
|
||||
git commit --amend -s --no-edit # add the trailer to the last commit
|
||||
```
|
||||
|
||||
It must read `Signed-off-by: Full Name <email-for-cla>`. See the
|
||||
[commit trailers section](./code-style-contrib.md#use-of-git-commit-trailers)
|
||||
of the contribution guidelines for this and other trailers.
|
||||
|
||||
### Verifying signed commits
|
||||
|
||||
You can verify that commits are properly signed locally using:
|
||||
|
||||
```bash
|
||||
git log --show-signature
|
||||
```
|
||||
|
||||
GitHub should also display a *Verified* badge next to signed commits once the
|
||||
signing key has been correctly configured in your account.
|
||||
|
||||
For SSH commit signing, local Git verification may require an
|
||||
`allowed_signers` file. This is only used for local verification in Git and is
|
||||
not required by GitHub. If you see errors such as:
|
||||
|
||||
```text
|
||||
No principal matched
|
||||
Can't check signature
|
||||
error: gpg.ssh.allowedSignersFile needs to be configured
|
||||
```
|
||||
|
||||
create the file, add your signing identity, and enable it in your Git config:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/git
|
||||
echo "user@example.com ssh-ed25519 AAAACexamplekeystringhere" > ~/.config/git/allowed_signers
|
||||
git config gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers
|
||||
```
|
||||
|
||||
> **NOTE:**
|
||||
> This is only for local Git signature verification and does not affect GitHub,
|
||||
> or remote repository behavior.
|
||||
|
||||
## Managing your own branch
|
||||
|
||||
The general development branch, and the target of every contribution, is
|
||||
`develop`; see [GET_SOURCES.md](./GET_SOURCES.md) for the branch and tag model
|
||||
(weekly `YYYY.wXX` tags, `vX.Y` releases). The rules for what a branch should
|
||||
look like — linear history, small self-contained logical commits, commit
|
||||
messages that explain *why* — are policy and live in
|
||||
[code-style-contrib.md](./code-style-contrib.md#workflow).
|
||||
|
||||
Before starting to work, please make sure to branch off the latest `develop`
|
||||
branch. Make commits as appropriate.
|
||||
|
||||
```bash
|
||||
git fetch origin
|
||||
git checkout develop
|
||||
git checkout -b my-new-feature # name as appropriate
|
||||
git add -p # add changes for change set 1, use `-p` to review what to include
|
||||
git commit -s # in the editor, describe your changes
|
||||
git add -p # add changes for change set 2
|
||||
git commit -s # in the editor, describe your changes
|
||||
```
|
||||
|
||||
Recent Git versions also offer `git switch` as a clearer alternative to
|
||||
`git checkout` for branch operations: `git switch develop` changes branch,
|
||||
`git switch -c my-new-feature` creates one.
|
||||
|
||||
Commit messages should take multiple lines; after the initial title, a blank
|
||||
line should follow. Read the `DISCUSSION` section in `man git commit` for more
|
||||
information. For documentation-only commits, prefix the title with `docs:`
|
||||
(see [doc_best_practices.md](./doc_best_practices.md)).
|
||||
|
||||
Code must be formatted with clang-format; an optional pre-commit hook can
|
||||
check this automatically at every commit — see
|
||||
[clang-format.md](./clang-format.md) for its installation and how to combine
|
||||
it with `git add -p`/`git stash -p`.
|
||||
|
||||
If your development takes longer, make sure to synchronize regularly with
|
||||
`origin/develop` using `git rebase`:
|
||||
|
||||
```bash
|
||||
git fetch origin
|
||||
git rebase -i origin/develop
|
||||
```
|
||||
|
||||
If you do logical changes, you should not have to resolve the same conflicts
|
||||
over and over again. If the same conflicts do keep reappearing, e.g., when
|
||||
maintaining a long-lived fork, consider enabling
|
||||
[`git rerere`](#reusing-conflict-resolutions-with-git-rerere). Note that if
|
||||
you jumped over multiple develop tags, you can also rebase in intermediate
|
||||
steps, in case you fear the differences might be too big.
|
||||
|
||||
```bash
|
||||
git rebase -i 2023.w38
|
||||
git rebase -i 2023.w41
|
||||
git rebase -i develop
|
||||
```
|
||||
|
||||
Once you rebased, push the changes to the remote:
|
||||
|
||||
```bash
|
||||
git push origin my-new-feature --force-with-lease # force with lease lets you only overwrite what you also have locally in origin/my-new-feature
|
||||
```
|
||||
|
||||
### Fixing up earlier commits
|
||||
|
||||
The [workflow policy](./code-style-contrib.md#workflow) asks for a history
|
||||
without "clean up" commits: when review or testing reveals a problem in an
|
||||
earlier commit of your branch, fold the fix into that commit instead of
|
||||
appending a `Fix bug` commit on top. Git automates this with fixup commits and
|
||||
`--autosquash`:
|
||||
|
||||
```bash
|
||||
git add -p # stage the fix
|
||||
git commit --fixup=<commit> # creates a commit titled "fixup! <original title>"
|
||||
git rebase -i --autosquash origin/develop # moves it after <commit> and squashes the two
|
||||
```
|
||||
|
||||
During the `--autosquash` rebase, Git pre-arranges the todo list so each
|
||||
`fixup!` commit is squashed into the commit it references; you normally just
|
||||
accept it. The result is the same clean history as if the fix had been part of
|
||||
the original commit.
|
||||
|
||||
A handy variant is `git commit --fixup=amend:<commit>`, which folds in the fix
|
||||
and also rewrites the commit message: during the `--autosquash` rebase the
|
||||
editor opens pre-filled with the original message, ready to be edited into the
|
||||
new one.
|
||||
|
||||
## Working with submodules
|
||||
|
||||
Parts of the tree are Git submodules. After cloning, and after every branch
|
||||
switch or pull, make sure they match the superproject:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
A recurring review problem is the *unintended submodule pointer update*: a
|
||||
submodule whose checked-out commit differs from what the superproject records
|
||||
shows up in `git status` as `modified: <path> (new commits)`, and a broad
|
||||
`git add .`, `git add -A`, or `git commit -a` silently records the new pointer
|
||||
in your commit. To avoid it:
|
||||
|
||||
- review `git status` before committing and stage files explicitly (e.g. with
|
||||
`git add -p`) rather than adding everything;
|
||||
- if a pointer change was staged by accident, unstage it with
|
||||
`git restore --staged <path>` and realign the submodule with
|
||||
`git submodule update --init <path>`.
|
||||
|
||||
Only commit a submodule pointer change when updating that submodule is the
|
||||
purpose of the commit, and say so in the commit message.
|
||||
|
||||
## Recovering from mistakes
|
||||
|
||||
To unstage a file that was added by accident (the changes stay in your working
|
||||
tree), or to throw away local changes to a file:
|
||||
|
||||
```bash
|
||||
git restore --staged <file> # unstage; keeps the modifications
|
||||
git restore <file> # discard unstaged modifications - cannot be undone
|
||||
```
|
||||
|
||||
`git reset` moves the current branch to another commit and differs in what it
|
||||
does to your files:
|
||||
|
||||
```bash
|
||||
git reset --soft HEAD~1 # undo the last commit, keep its changes staged (e.g. to re-split it)
|
||||
git reset --hard <commit> # make branch, index and working tree identical to <commit>
|
||||
```
|
||||
|
||||
> **Warning:** `git reset --hard` discards all uncommitted changes; there is no
|
||||
> way to recover them.
|
||||
|
||||
Committed work is much harder to lose than it seems: `git reflog` records every
|
||||
position of `HEAD` (commits, rebases, resets, checkouts) for a retention period
|
||||
of at least 30 days, even for commits no branch points to anymore. If a rebase
|
||||
or reset went wrong, find the last good state and reset back to it:
|
||||
|
||||
```bash
|
||||
git reflog # e.g.: e75076172 HEAD@{5}: commit: doc: add git rerere guide
|
||||
git reset --hard 'HEAD@{5}' # return the branch to that state
|
||||
```
|
||||
|
||||
## Reusing conflict resolutions with git rerere
|
||||
|
||||
The `develop` branch is updated roughly once a week. Feature branches that live
|
||||
for more than a few days therefore have to be re-synced with `develop`
|
||||
repeatedly, and the same merge conflicts tend to reappear at every sync - often
|
||||
in the same scheduler, PHY, or RRC files that several contributors touch at
|
||||
once. Resolving the identical conflict by hand every week is error-prone and
|
||||
wastes time.
|
||||
|
||||
Git ships a built-in feature for exactly this situation: `rerere`, short for
|
||||
**reuse recorded resolution**. Once enabled, Git remembers how you resolved a
|
||||
given conflict and replays that resolution automatically the next time the same
|
||||
conflict appears.
|
||||
|
||||
This section explains how to enable and use it. It is a local developer
|
||||
convenience: nothing about it changes the repository, the history you push, or
|
||||
the contribution workflow.
|
||||
|
||||
### What it does
|
||||
|
||||
When a conflict occurs, `rerere` records the conflicted hunk (the *preimage*).
|
||||
After you resolve it, `rerere` records your resolution (the *postimage*), keyed
|
||||
by a hash of the preimage. The next time a conflict with the same preimage shows
|
||||
up - in a later rebase, a later merge, or even another branch - Git reapplies
|
||||
your recorded resolution instead of presenting the conflict again.
|
||||
|
||||
The data lives in `.git/rr-cache/` inside your local clone. It is never part of
|
||||
any commit and is never pushed.
|
||||
|
||||
### Enabling it
|
||||
|
||||
Enable it once, globally, so it applies to every repository on your machine:
|
||||
|
||||
```bash
|
||||
git config --global rerere.enabled true
|
||||
git config --global rerere.autoupdate true
|
||||
```
|
||||
|
||||
`rerere.autoupdate` stages a replayed resolution automatically. Without it, the
|
||||
resolution is still written into your working tree, but you have to `git add`
|
||||
the file yourself.
|
||||
|
||||
### Typical flow
|
||||
|
||||
The first time you hit a conflict after enabling `rerere`, resolve it exactly as
|
||||
you always have:
|
||||
|
||||
```bash
|
||||
# during a rebase or a merge that conflicts
|
||||
git status # rerere reports which paths it is recording
|
||||
# edit the conflicted files, remove the markers
|
||||
git add <resolved-files>
|
||||
git rebase --continue # or: git commit, for a merge
|
||||
```
|
||||
|
||||
That resolution is now recorded. The next time the same conflict appears, Git
|
||||
resolves it for you. With `autoupdate` on, the file is already staged and you can
|
||||
go straight to:
|
||||
|
||||
```bash
|
||||
git rebase --continue # or git commit
|
||||
```
|
||||
|
||||
Always review the replayed result before continuing - see *Caveats* below.
|
||||
|
||||
### Inspecting and undoing recorded resolutions
|
||||
|
||||
```bash
|
||||
git rerere status # paths with a recorded preimage in the current operation
|
||||
git rerere diff # the resolution rerere is applying
|
||||
git rerere forget <path> # discard a recorded resolution (e.g. a wrong one)
|
||||
```
|
||||
|
||||
`git rerere forget` is the escape hatch when you recorded a bad resolution: it
|
||||
drops the cached entry for that path so the next conflict is presented fresh.
|
||||
|
||||
### Seeding from existing history
|
||||
|
||||
If your branch already contains **merge commits** whose conflicts you resolved
|
||||
before enabling `rerere`, you can backfill the cache so those resolutions are
|
||||
available immediately. Git ships a helper for this in `contrib/`:
|
||||
|
||||
```bash
|
||||
sh /path/to/git/contrib/rerere-train.sh origin/develop..HEAD
|
||||
```
|
||||
|
||||
It replays the merge commits in the given range, reconstructs each conflict, and
|
||||
records the resolution found in the merge commit.
|
||||
|
||||
> **Note:** this only works for resolutions captured in merge commits. A purely
|
||||
> linear (rebased) history has no merge commits to learn from, so there is
|
||||
> nothing to backfill - `rerere` will simply start recording from your next
|
||||
> conflict onward.
|
||||
|
||||
### Sharing the cache (optional)
|
||||
|
||||
The cache is local. If you work across several machines, or want a team to share
|
||||
resolutions for the same recurring conflicts, copy the directory:
|
||||
|
||||
```bash
|
||||
rsync -a ~/work/oai-A/.git/rr-cache/ ~/work/oai-B/.git/rr-cache/
|
||||
```
|
||||
|
||||
There is no built-in push/pull for the cache; treat it as an ordinary directory
|
||||
to sync.
|
||||
|
||||
### Caveats and good practice
|
||||
|
||||
- `rerere` matches on the **exact** conflicting text. If `develop` changed the
|
||||
lines surrounding your change, the preimage differs and the conflict is
|
||||
presented as new. This is expected - the resolution is still recorded for the
|
||||
next identical occurrence.
|
||||
- A replayed resolution is only as correct as the original. When the code around
|
||||
a conflict has evolved, an old resolution can apply cleanly yet be wrong.
|
||||
**Review every replayed resolution and build/test before continuing.**
|
||||
- `rerere` reduces repeated manual work; it does not change which branch
|
||||
strategy you use. It helps both when rebasing onto `develop` and when merging
|
||||
`develop` into a feature branch. Remember that branches intended for
|
||||
contribution must have a linear history without merge commits (see the
|
||||
[workflow policy](./code-style-contrib.md#workflow)); a fork can of course
|
||||
carry merge commits if that is convenient for its development.
|
||||
|
||||
## See also
|
||||
|
||||
- [CONTRIBUTING.md](../CONTRIBUTING.md) - CLA, DCO, and licensing requirements.
|
||||
- [code-style-contrib.md](./code-style-contrib.md) - workflow, commit, and
|
||||
review policy, including commit trailers.
|
||||
- [GET_SOURCES.md](./GET_SOURCES.md) - branches, tags, and how to obtain the
|
||||
sources.
|
||||
- [clang-format.md](./clang-format.md) - code formatting and its Git
|
||||
integration (pre-commit hook).
|
||||
- The [Git Book](https://git-scm.com/book/en/v2) and the
|
||||
[`git rerere` manual](https://git-scm.com/docs/git-rerere)
|
||||
Reference in New Issue
Block a user