
# Pendahuluan

merql adalah pustaka PHP murni yang melakukan penggabungan tiga arah pada keadaan database. Pustaka ini mengambil snapshot tabel, menghitung kumpulan perubahan di antara snapshot, menggabungkan dua kumpulan perubahan berdasarkan base bersama, dan mendeteksi konflik di tingkat kolom. Algoritme yang sama dengan yang digunakan git untuk berkas sumber, diterapkan pada baris dan kolom, bukan baris teks.

Tanpa alat eksternal. Mendukung MySQL dan SQLite melalui adaptor koneksi dan driver dialek yang dapat dipasang.

## Contoh singkat

Penggabungan memerlukan tiga keadaan dari data yang sama: base tempat kedua salinan bermula, dan dua salinan setelah berubah secara independen. Dalam contoh ini, sandbox disalin dari database live, lalu keduanya diedit.

```php
use Merql\Connection;
use Merql\Merql;

$live    = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');

// Base: live at the moment the sandbox was copied from it.
Merql::init($live);
Merql::snapshot('base');

// ... copy live.sqlite to sandbox.sqlite, then both databases change ...

// Ours: the sandbox with our edits. Theirs: live with its own changes.
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');

$result = Merql::merge('base', 'ours', 'theirs');

if ($result->isClean()) {
    foreach ($result->operations() as $operation) {
        echo "{$operation->type} {$operation->table} #{$operation->rowKey} ({$operation->source})\n";
    }
} else {
    echo "Conflicts: {$result->conflictCount()}\n";
}
```

Setiap snapshot diambil dari database yang menyimpan keadaan tersebut. Mengambil ketiganya secara berurutan dari satu database tidak menggambarkan dua salinan yang telah menyimpang: theirs akan sudah memuat perubahan ours, dan setiap baris yang disisipkan ours akan dilaporkan sebagai konflik `insert_insert`.

Hasilnya mencantumkan operasi yang mengubah base menjadi keadaan gabungan dari kedua sisi, masing-masing ditandai dengan sumbernya (`ours`, `theirs`, atau `merged`). Untuk menulis perubahan sandbox ke live, terapkan operasi yang belum dimiliki live dengan [Terapkan dengan Pengamanan](https://merql.inline0.dev/id/docs/apply/guarded).

Atau dari CLI, yang terhubung ke database bernama di `MERQL_DB_DSN` untuk setiap `snapshot`:

```bash
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs

vendor/bin/merql merge base ours theirs --dry-run
```

## Mengapa merql

Sebagian besar alat database yang membandingkan keadaan bekerja pada tingkat baris: jika ada kolom dalam satu baris yang berbeda antara dua versi, seluruh baris ditandai sebagai konflik. Ini menghasilkan konflik palsu ketika dua orang mengedit kolom yang berbeda pada baris yang sama.

merql menggabungkan pada tingkat kolom. Jika satu sisi mengubah `title` dan sisi lain mengubah `status`, perubahan tersebut dapat digabungkan dengan bersih tanpa konflik. Konflik hanya terjadi ketika kedua sisi mengubah kolom yang sama menjadi nilai yang berbeda.

Untuk kolom TEXT dan JSON, merql dapat bekerja lebih mendalam dengan penggabungan tingkat sel. Dua suntingan pada baris berbeda dalam kolom teks, atau kunci berbeda dalam kolom JSON, dapat digabungkan dengan bersih menggunakan algoritme tiga arah yang sama. Penggabungan tingkat sel bersifat opsional: teruskan `CellMergeConfig` ke `ThreeWayMerge`. Fasade `Merql` dan CLI hanya menggabungkan pada tingkat kolom. Lihat [Penggabungan Tingkat Sel](https://merql.inline0.dev/id/docs/merge/cell-level).

## Model penggabungan

```
         Base (snapshot at fork time)
        /                              \
   Ours (one copy's changes)            Theirs (the other copy's changes)
        \                              /
         --------- MERGE ----------
                     |
              Merged result
              + conflicts (if any)
```

Tiga keadaan, sama seperti git. Base adalah leluhur bersama. Ours dan theirs adalah dua salinan setelah keduanya menyimpang, masing-masing diambil dari databasenya sendiri. Aturan penggabungan memperlakukan kedua sisi secara setara. Nama-nama tersebut muncul di `source` setiap operasi, dalam jenis konflik (`update_delete` berarti ours memperbarui dan theirs menghapus), serta dalam kebijakan resolusi `OursWins` dan `TheirsWins`. Tanpa base bersama, Anda tidak dapat membedakan "ditambahkan" dari "tidak berubah".

Penggabungan tidak menulis apa pun dengan sendirinya. Operasinya mengubah base menjadi keadaan gabungan, jadi `Merql::apply()` menjalankan semuanya dengan bersih hanya pada database yang masih menyimpan base. Untuk membawa perubahan dari satu sisi ke database yang sudah menyimpan sisi lain, seperti menerapkan perubahan sandbox ke live, terapkan hanya operasi yang belum ada; lihat [Terapkan dengan Pengamanan](https://merql.inline0.dev/id/docs/apply/guarded).

## Persyaratan

- PHP 8.2 atau lebih baru.
- `ext-mbstring` dan `ext-zlib`, diperlukan oleh dependensi `pitmaster/pitmaster` yang menyediakan perbedaan teks.
- Ekstensi database untuk adaptor yang Anda gunakan: `ext-pdo` dengan `ext-pdo_sqlite` atau `ext-pdo_mysql`, atau `ext-mysqli`. `composer.json` merql hanya menyarankan `ext-pdo` dan `ext-mysqli`, jadi Composer tidak memeriksanya.
- Database MySQL atau SQLite. Mesin lain memerlukan [driver](https://merql.inline0.dev/id/docs/apply/drivers) khusus.

## Hal yang bukan termasuk

merql bukan alat migrasi skema. merql tidak mereplikasi database atau menyinkronkannya secara waktu nyata. merql menyelesaikan satu masalah spesifik: dengan tiga keadaan database, menghasilkan keadaan keempat yang telah digabungkan dan mengidentifikasi konfliknya.

## Dokumentasi

- [Memulai](https://merql.inline0.dev/id/docs/getting-started) -- instalasi, snapshot pertama, penggabungan pertama.
- [CLI Referensi](https://merql.inline0.dev/id/docs/cli) -- referensi lengkap untuk perintah `vendor/bin/merql`.
- [PHP API Referensi](https://merql.inline0.dev/id/docs/api) -- dokumentasi API lengkap untuk semua kelas.
- [Rencana Penggabungan](https://merql.inline0.dev/id/docs/merge/plans) -- ID operasi yang stabil, kelompok perubahan, dan pilihan.
- [Terapkan dengan Pengamanan](https://merql.inline0.dev/id/docs/apply/guarded) -- penulisan terpilih dengan prasyarat baris live.
- [Rollback](https://merql.inline0.dev/id/docs/apply/rollback) -- artefak rollback dan pemeriksaan penyimpangan.
