---
title: バージョンと ref
description: バージョンは固めたカタログと記録、ref はバージョンを指す名前です。DuckLake のスナップショットや Git のコミットとの関係も説明します。
---

## バージョン

バージョンは、固めた DuckLake カタログ 1 つと、それがどうできたかの記録です。自分のフォルダに置かれ、一度書いたら変わりません。

```
versions/019a3c4e-7b21-7f3a-9c55-2f0d8e1a4b6c/
  version.json         記録: 親、作者、メッセージ、チェックサム
  dataset.json         中身の説明: 表、列、ライセンス
  ducklake.duckdb      固めたカタログ
```

記録には次のことを書きます。

- `id`: バージョン ID。UUIDv7 なので作った順に並び、2 人の書き手が同じ ID を作ることはありません
- `seq`: 人に見せる番号。親の `seq` に 1 を足した数です
- `parents`: 積んだ元のバージョン。最初のバージョンでは空です
- `author`、`message`、`created_at`
- `catalog`: カタログファイルの大きさと sha256。読み手は取得したものを確かめられます
- `ducklake`: カタログの DuckLake 形式と、固めたときのスナップショット

ID は、Git のコミットと違って中身のハッシュではありません。同じカタログでも、DuckDB のリリースが違うと別のバイト列になるので、中身のハッシュは安定しません。中身は `catalog` の sha256 で確かめます。

項目の一覧は、仕様の[バージョン](/ja/spec/versions)にあります。

## スナップショットとバージョン

DuckLake は書き込みのたびにスナップショットを作ります。`INSERT`、`CREATE TABLE`、`ALTER` をそれぞれのトランザクションで流すたびに 1 つです。1 日の作業で数百になることもあります。バージョンは、作業ができたと判断したときに作り、その時点の最後のスナップショットを取ります。

スナップショットとバージョンの関係は、作業ブランチのコミットと、それを squash して `main` に入れたコミットの関係と同じです。スナップショットは `commit_message` や `commit_extra_info` と一緒にカタログの中に残るので、細かい履歴は失われません。`version.json` には、親から足したスナップショットの範囲だけを書き、中身は写しません。

## ref

ref は、バージョン ID と改行だけを書いたファイルです。読み手は ID を知らなくても、ref からバージョンを見つけられます。

```
refs/heads/main          019a3c4e-7b21-7f3a-9c55-2f0d8e1a4b6c
refs/tags/2025-final     019a2f10-0c4d-7e88-a1b2-55c0d9e3f7aa
HEAD                     ref: refs/heads/main
```

| 種類 | パス | 動くか |
| --- | --- | --- |
| ブランチ | `refs/heads/<name>` | 前へだけ動く |
| タグ | `refs/tags/<name>` | 動かない |
| リクエスト | `refs/requests/<number>` | ホストが決める |
| HEAD | `HEAD` | めったに動かない |

読み手がほかを指定しなければ、`main` を読みます。Git と同じく、`HEAD` が `main` を指します。タグは、読み手が頼れるバージョンを固定します。たとえばある年の確定値です。`refs/requests/` はホストのためのものです。承認待ちのバージョンを、`main` に載せずにここで持てます。

リポジトリの中で変わるファイルは ref だけです。ほかのファイルは一度しか書きません。

## ブランチを動かす

ブランチは前へだけ動きます。新しいバージョンが `main` になれるのは、その `parents` に、いま `main` が指すバージョンが入っているときです。Git でいう fast-forward です。

```
main → A
           Alice が A をチェックアウトし、B（親 A）をコミットして push: main → B
           Bob も A をチェックアウトしていて、C（親 A）をコミットして push: 断られる
```

C は B の上に積まれていないので、Bob の push は断られます。受け付けると、誰も決めていないのに B が `main` の履歴から消えてしまいます。Bob は B をチェックアウトし、変更をやり直します。

FDL は行をマージしません。2 つの DuckLake カタログをマージするには、両方で変わった行のどちらを残すかを決める必要があります。DuckLake には、カタログをまたいで表の同一性を示す情報がないので、安全に決められません。新しいバージョンの上でのやり直しは、たいてい同じ SQL を流し直すだけで済みます。

バージョンを取り消すためにブランチを後ろへ戻すのは、明示的に指示したときだけできます。取り消したバージョンも、リポジトリと履歴には残ります。

## 履歴

`fdl log` は、ref が指すバージョンから最初のバージョンまで、最初の親をたどります。

```
   3  019a4b…  2026-11-01T09:00:00Z  alice
      Correct the 2026 figures
   2  019a3c…  2026-10-15T09:00:00Z  bob
      Add 2026
   1  019a2f…  2026-10-01T09:00:00Z  alice
      First towns
```

保持期間を過ぎたバージョンも履歴に残ります。記録はそのままで、カタログだけがありません。[保持期間](/ja/internals/inside-a-repository#保持期間を過ぎたバージョン)を参照してください。
