Une ref devient une version. Pointez une source vers des tags et chacun est
publié, avec un segment de version dans l’URL et une entrée dans le sélecteur.

Les refs exigent un `repo` explicite, même pour publier un autre ref de ce
dépôt. Sans `repo`, une source lit le checkout local actuel et refuse `refs` (y
compris `latest`) ainsi que les substitutions locales de `ref` par langue.
`origin.repo` et `origin.ref` fournissent uniquement des liens de provenance ;
ils ne sélectionnent aucun contenu. Une langue ayant son propre `repo` explicite
peut choisir son propre `ref`. Pour les versions locales, utilisez `version` sur
des sources avec des dossiers distincts ou les `versions` par fichier d’une
section générée.

## Étapes

::steps
1. **Listez les refs.** Une chaîne simple est une **branche**. Un tag doit le
   dire — git garde les deux dans des espaces de noms séparés, et demander un
   tag sous `refs/heads` fait échouer la compilation.

   ```ts [app/app.config.ts]
   sources: [
     {
       repo: 'acme/api',
       path: 'docs',
       refs: [
         { branch: 'main', status: 'upcoming' },
         { tag: 'v2.0.0' },
         { tag: 'v1.4.0' },
         { tag: 'v0.9.0', status: 'eol' }
       ]
     }
   ],
   sourceOptions: { defaultRef: 'v2.0.0' }
   ```

2. **Nommez la version par défaut.** `defaultRef` est la ref servie sans préfixe
   de version et celle vers laquelle les moteurs de recherche sont dirigés. Non
   définie, c’est la première de la liste — ce qui est rarement souhaitable
   quand la liste commence par une branche.

3. **Indiquez le cycle de vie là où il ne peut pas être déduit.** Semver ordonne
   les tags : « plus ancienne que la version par défaut » n’a besoin d’aucune
   aide. Il ne peut pas situer une branche face à un tag : `main` est
   `upcoming`, et sans le dire on demande à son lecteur de passer à une version
   plus ancienne que celle qu’il lit.

4. **Découvrez les versions si vous ne voulez pas modifier la liste à chaque
   publication.** Choisissez l’historique qui doit rester adressable : toutes
   les versions, le dernier correctif de chaque ligne mineure ou la dernière
   version de chaque ligne majeure.

   ```ts
   releases: { select: 'minor' },
   refs: [{ branch: 'main', status: 'upcoming' }]
   ```

   `all`, `minor` et `major` sont des politiques d’URL durables. Les
   préversions restent exclues sauf avec `prereleases: true`. Pour une seule
   version mobile, `'latest'` reste disponible.

5. **Signalez l’exigence de version d’une page dans le texte**, là où un lecteur
   qui regarde une version ne voit pas les autres :

   ```md
   ### Nouvelles tentatives :since{version="v2.0.0"}
   ```

::

## La granularité d’une version

Le nom est **le choix du site, pas du mécanisme**, et c’est la décision essentielle
ici : chaque lien vers votre documentation le portera.

**Une ligne par version, sous forme de branche.** C’est le choix de Laravel,
Symfony et Django : `11.x`, `10.x` et `9.x` sont des branches qui continuent
d’évoluer, et un correctif ne change rien à l’URL.

```ts [app/app.config.ts]
sources: [
  {
    repo: 'acme/api',
    path: 'docs',
    refs: [
      { branch: '12.x', status: 'upcoming' },
      '11.x',
      { branch: '10.x', status: 'deprecated' },
      { branch: '9.x', status: 'eol' }
    ]
  }
],
sourceOptions: { defaultRef: '11.x' }
```

Une chaîne simple **est** une branche ; seul un tag doit le préciser.

**Une ligne par version, depuis des tags.** Lorsque la version publiée est un
tag mais que l’URL ne doit pas changer à chaque correctif, `label` la renomme :

```ts
refs: [
  { tag: 'v2.4.1', label: 'v2' },
  { tag: 'v1.9.3', label: 'v1', status: 'deprecated' }
]
```

**Chaque publication a sa propre version.** `{ tag: 'v2.4.1' }` sans libellé.
Chacune reste citable pour toujours, et le sélecteur gagne une entrée à chaque
publication : adapté à une spécification, mais pas à un manuel.

Les mêmes politiques peuvent être entretenues depuis les tags plutôt que
répétées dans la configuration :

```ts
// Chaque publication qui doit rester citable.
releases: { select: 'all' }

// Ou le dernier correctif de chaque ligne mineure durable.
releases: { select: 'minor' }

// Ou une publication courante pour chaque ligne majeure.
releases: { select: 'major' }
```

La publication sélectionnée la plus récente est celle par défaut, sauf si une
ref explicite avec `default: true` ou `sourceOptions.defaultRef` en décide
autrement. Une sélection sans tag correspondant fait échouer le build ; un dépôt
injoignable est signalé comme une erreur Git, pas pris pour une sélection vide.

Le même choix vaut pour une section qui nomme ses versions : `version: 'v2'`
ou `version: '2.4.1'`, avec exactement le même compromis. Un modèle, une décision,
que le contenu provienne d’une ref ou d’un fichier.

::callout{type="tip" title="Les noms généraux vieillissent mieux"}
Un segment de version fait partie de chaque lien vers votre documentation.
`v2` survit aux quarante prochaines publications ; `2.4.1` est dépassée dès la
sortie de `2.4.2`.
::

## Quand les versions ne sont pas des refs

Une version est normalement un checkout. Deux formes courantes ne le sont pas :

**La documentation dans des dossiers.** `docs/v1` à côté de `docs/v2` dans un
dépôt, sans tags. Chaque source nomme sa version :

```ts [app/app.config.ts]
sources: [
  { path: 'docs/v2', version: 'v2' },
  { path: 'docs/v1', version: 'v1', status: 'deprecated' }
]
```

**Une API dans des fichiers.** `openapi/v1.yaml` à côté de `openapi/v2.yaml` est
la façon habituelle de conserver une API. Les versions appartiennent à la
*section*, pas à la source :

```ts [app/app.config.ts]
generated: [
  {
    type: 'openapi',
    label: 'API',
    path: 'openapi/v2.yaml',
    versions: [
      { version: 'v2', path: 'openapi/v2.yaml' },
      { version: 'v1', path: 'openapi/v1.yaml', status: 'deprecated' }
    ]
  }
]
```

Les deux produisent exactement ce que produisent les refs : un segment d’URL,
une entrée dans le sélecteur, le bandeau et le canonical. Le sélecteur reste
limité à l’artefact lu : sur `/api`, il propose les versions de l’API ; sur une
page de prose, celles de la documentation.

::callout{type="warning" title="L’un ou l’autre, jamais les deux"}
Une source qui déclare `refs` **et** `version`, ou une section avec `versions`
sur une source ayant des refs, fait échouer la compilation : les deux réclament
le même segment d’URL. Voir la liste des champs dans [Sources](/reference/sources).
::

## Ce qu’il advient des anciennes versions

Une version non par défaut porte `noindex` et un `canonical` pointant vers la
même page dans celle par défaut, et une version `eol` quitte entièrement le
sitemap. C’est ce qui empêche un moteur de recherche de proposer `v0.9.0` là où
le lecteur voulait la documentation du jour — voir
[URL et versions](/concepts/urls-and-versions).

## Liste de contrôle

- [ ] Chaque tag est écrit `{ tag: … }`, pas en chaîne simple
- [ ] Les noms de version suivent la granularité des lignes de support du projet
- [ ] `defaultRef` nomme la version sur laquelle les lecteurs doivent arriver
- [ ] Une branche de la liste porte un `status` explicite
- [ ] Le sélecteur affiche chaque version, avec un badge sur les mortes
- [ ] La page d’une version morte est absente de `/sitemap.xml`
- [ ] Si les versions sont des dossiers ou des fichiers plutôt que des refs, un seul
      de `refs`, `version` d’une source et `versions` d’une section est utilisé