2台目の iPhone を買って、Anki なり別の暗記アプリなりを入れて、同期をオンにする。そこで片方の端末でやったぶんの学習記録が消える——珍しい話ではありません。
先に結論を書きます。多くの場合これは不具合ではなく、同期の設計どおりの動作です。 同期には「どちらかのデータで上書きする」やり方と「両方を突き合わせて合流させる」やり方があり、前者を選んでいる場合、後から同期した側の記録は設計上必ず消えます。
そして厄介なのは、情報の種類によって正解が違うことです。「あとが勝つ」で扱ってよい情報と、足し合わせないと消える情報が同居しています。この記事では何がどう消えるのかを、暗記アプリの同期を実装した立場から説明します。Anki を例に挙げますが、原因は Anki 固有のものではありません——間隔反復で学習履歴を持つアプリに共通の問題です。このサイトは RepeCa の開発元が運営しています。
なぜ2台目を使い始めた瞬間に消えるのか
危ないのは、両方の端末に既にデータがある状態で初めて同期したときです。
片方が空なら問題は起きません。空の端末に流し込むだけだからです。しかし2台とも使い込んでいると、同じカードについて2つの異なる履歴がある状態になります。ここでどちらを採用するかを決めなければならず、その決め方が設計そのものです。
Anki の公式マニュアルも、この場面を特別扱いしています。
If you have different cards on both devices, more work is required to avoid losing data. (両方の端末に異なるカードがある場合、データを失わないためには追加の作業が必要です)
— Anki Manual, Syncing(2026-08-26 確認)
「追加の作業が必要」と書かれている時点で、自動では守られないということです。
同期は何を「勝たせる」かを決めているだけ
同期の設計とは、突き詰めると「衝突したときに何を勝たせるか」の規則です。
もっとも単純なのは LWW(Last Write Wins・あとが勝つ) で、タイムスタンプが新しい方を採用します。実装が単純で、多くの場面で妥当です。
問題は、暗記アプリのデータが1種類ではないことです。 RepeCa では3つに分けて規則を変えています(実装確認: sync/merge.ts。2026-08-26 時点)。
| 情報の種類 | 例 | 勝たせ方 |
|---|---|---|
| カードの内容 | 表・裏・所属フォルダ・タグ | あとで編集した方(updatedAt の LWW) |
| 復習スケジュール | 現在のレベル・次に出る日 | あとで採点した方 |
| 累計の記録 | 生涯の正答数・誤答数 | 🔴 両端末の増分を足す |
3つ目だけ扱いが違います。理由は次の節です。なお、ここでいう「レベル」と「次に出る日」が何を指すのかは間隔反復(SRS)とはにまとめてあります。
累計の数字を「あとが勝つ」で扱うと何が起きるか
消えます。しかも気づきにくい形で消えます。
端末Aで8回、端末Bで12回そのカードに答えたとします。「あとが勝つ」で処理すると、結果は 8 か 12 のどちらかになります。本当は20回答えているのに、記録上は片方だけが残ります。
カードの表裏なら「あとが勝つ」で構いません。最新の1つが正しいからです。しかし累計の数字は履歴の積み上げなので、片方を捨てると積み上げた事実そのものが消えます。
RepeCa は端末ごとに「前回の同期からどれだけ増えたか」を覚えていて、その増分を足し合わせます。実装上は server + max(0, ローカルの値 - 前回同期時の値) という形で、二重計上も欠落もせずに揃います。
⚠️ この違いは、使っていて気づきません。 正答率の分母が減っても「そんなものか」と思うだけで、エラーも警告も出ないからです。復習スケジュールは正常に動き続けるので、不具合として認識されません。統計を見返したときに数字が合わない、という形でようやく気づきます。
消したはずのカードが復活するのはなぜか
削除を「レコードが無い状態」として同期すると、必ず復活します。
端末Aでカードを消したとします。同期のときに端末Aは「そのカードを持っていない」状態です。一方で端末Bはまだ持っています。ここで「持っている方を正とする」と、削除が「まだ受け取っていないだけ」と区別できません。結果、消したカードが戻ってきます。
解決策は、削除を消えた状態ではなく「消したという記録」として送ることです。RepeCa では削除された印(deletedAt)を持つレコードを送り合い、内容と同じ LWW の規則で伝播させます。削除も1つの編集として扱う、という考え方です。
同じ名前のタグが増えるのはなぜか
2台で同じ名前のタグを別々に作ると、内部の識別子が違うので別物として両方残ります。
利用者から見れば同じ「英単語」というタグですが、システムから見れば別のレコードです。同期のたびに増えていき、タグ一覧に同じ名前が並びます。
RepeCa は受信時に同じ名前のタグを1つへ畳みます(実装確認: sync/apply.ts の dedupeTagName)。どちらを残すかは識別子の小さい方に固定していて、どの端末から見ても同じ結果になるようにしています。勝者を「先に届いた方」にすると端末ごとに違う結果になり、収束しません。
初回に「どちらかを選ばせない」ようにする
両方に既にデータがある初回同期こそ、いちばん壊れやすい場面です。
RepeCa は同期をオンにしたとき、クラウドの全件を取り込んでから、手元の全件を送り出します(実装確認: sync/engine.ts の bootstrapSync)。順序が逆だと、取り込む前に上書きしてしまいます。この2段階を踏むので、利用者に「アップロードとダウンロードのどちらか」を選ばせる場面がありません。
同じ id のカードが両方にあれば上の3つの規則でマージされ、片方にしかないカードはそのまま残ります。結果は両者の合流になります。
受信したレコード1件を適用する処理は1か所に集約してあります。通常の受信と、衝突が起きたときの解決が同じコードを通るようにするためです。2か所に分けて書くと、片方だけ直したときにドリフトが起きます。
それでも RepeCa の同期が既定オフなのはなぜか
ここは正直に書きます。設計は上のとおりですが、2台同時に使ったときの挙動を実機で十分に検証できていません。
RepeCa の iCloud 同期は既定でオフで、使うには設定から手動で有効にする必要があります。この一手間を意図的に残しているのは、検証体制がまだ限定的だからです(実装のコメントにもその理由を残してあります)。
設計上の規則を決めてあることと、2台で動かして確かめたことは別です。 前者は説明できますが、後者はまだ胸を張れる段階にありません。検証が済んだら、この記事にも実測を追記します。
同期そのものの仕様はiCloud 同期に、有効にする手順はiCloud 同期を有効にするにまとめてあります。
使う側にできること
道具を選ぶ・使う立場からは、次の3点が効きます。
- 2台目を使い始める前に、片方で同期をオンにして送り出しておく——両方に育ったデータがある状態を作らないのが、いちばん確実です
- 書き出し(エクスポート)ができる道具を選ぶ——同期の設計は外から確かめられませんが、書き出せれば最悪の場合に自力で戻せます
- 累計の数字を時々見ておく——正答率の分母が不自然に減っていたら、上書き型の同期が働いた可能性があります
意図して学習の記録を戻したい場合は別の話で、そちらは学習履歴のリセットにまとめました。意図せず消えるのが本記事、意図して戻すのがあちらです。
まとめ
- 2台で記録が消えるのは、多くの場合は不具合ではなく同期の設計どおり。危ないのは両方にデータがある状態での初回同期
- 情報の種類ごとに正解が違う。カードの内容は「あとが勝つ」でよいが、累計の記録は足し合わせないと消える
- 削除は「無い状態」ではなく「消したという記録」として送らないと復活する
- 同名タグの増殖は、勝者を決定的に決めれば収束する(RepeCa は識別子の小さい方に固定)
- 初回は「取り込んでから送り出す」の順序にすれば、どちらかを選ばせずに合流できる
- 🔴 RepeCa の同期は既定オフ。設計は決めてあるが、2台での実機検証はまだ十分ではない
この記事について
このサイトは、暗記アプリ RepeCa の開発元が運営しています。本文の設計判断(3種類のマージ規則・削除の伝播・同名タグの畳み込み・初回同期の順序)は、実装のときに決めた内容とその理由をそのまま書いたもので、2026-08-26 にコードを読み直して確認しています。
RepeCa の同期は既定オフで、2台同時に使ったときの挙動は実機で十分に検証できていません。 「うちは解決済み」という記事ではなく、「こういう分かれ道があり、私たちはこう選んだ」という記事として読んでください。
- Anki Manual. Syncing. 両方の端末に異なるカードがある状態での初回同期は、データを失わないために追加の作業が必要である旨の記述。2026-08-26 確認。