---
title: 'Anlamlı Sürümleme'
source: 'https://academia.sh/tr/kurslar/javascript-ekosistemi/anlamli-surumleme'
course: 'Modüller, Araçlar ve Ekosistem'
language: tr
updated: '2026-08-17T18:09:45+00:00'
license: 'CC BY-SA 4.0'
---

# Anlamlı Sürümleme

Sürüm numarasının üç parçasının taşıdığı söz, karşılaştırma ve öncelik kuralları, ön yayın etiketleri, sürüm aralıklarının sınırları ve kırıcı değişikliğin tanımı.

Önceki ders, bildirimdeki `^1.4.0` gibi bir aralığın tek bir sürüm değil bir küme
belirttiğini söyledi. Kümenin sınırlarını çizen şey, sürüm numarasının parçalarına anlam
yükleyen bir sözleşmedir.

Bu sözleşmeye **anlamlı sürümleme (semantic versioning)** denir. Teknik bir mekanizma
değil, bir söz verme biçimidir: numarayı yükselten taraf, tüketiciye ne yaptığını söyler.
Mekanizma olan kısım — karşılaştırma ve aralık hesabı — sözleşmenin üzerine kurulur.

## Üç Parçanın Verdiği Söz

Sürüm numarası noktalarla ayrılmış üç sayıdan oluşur: **ana (major)**, **ikincil (minor)**
ve **yama (patch)**. Bir yayın hazırlanırken hangi parçanın artırılacağı, yapılan
değişikliğin türüne bağlıdır:

| Değişiklik | Artan parça | Tüketiciye verilen söz |
|---|---|---|
| Hata düzeltmesi, iç iyileştirme | Yama | Kodunuz değişmeden çalışır |
| Geriye dönük uyumlu yetenek eklemesi | İkincil | Kodunuz değişmeden çalışır, yeni yetenek de vardır |
| Var olan davranışı değiştiren düzenleme | Ana | Kodunuz değişebilir; geçiş notlarını okuyun |

Sözün konusu, paketin **açık arayüzüdür**: dışa aktarım haritasında listelenen yollar ve
o yollardan erişilen adlar. Haritada olmayan bir iç dosyanın yeniden adlandırılması ana
sürümü artırmaz — kapsüllemenin karşılığı budur. Bu, Programlama Temelleri kursunda
tanıtılan geriye dönük uyumluluk kavramının paket düzeyinde bir sözleşmeye
dönüştürülmesidir.

Sözleşmenin kendisi hiçbir şey zorlamaz. Numarayı doğru artırmak yazarın sorumluluğudur;
tüketici tarafında ise numaraya duyulan güvenin sınırı, bir sonraki bölümdeki aralıkların
neden savunmasız olduğunu açıklar.

## Karşılaştırma ve Öncelik

Aralık hesabının önkoşulu, iki sürümün karşılaştırılabilmesidir. Karşılaştırma metin
sırasıyla yapılamaz: `1.10.0` sürümü `1.9.0` sürümünden büyüktür ama metin olarak küçük
görünür. Linux'a Giriş kursundaki paket yöneticisi dersinde aynı sorun sistem paketleri
için anlatılmıştı; burada kural daha dardır ve tümüyle yazılıdır.

Kural üç adımdır: üç sayı soldan sağa sayısal olarak karşılaştırılır; eşitlik durumunda
ön yayın etiketi olan sürüm olmayandan küçüktür; iki taraf da ön yayınsa etiket parçaları
tek tek karşılaştırılır.

```javascript
// dosya: surum.mjs
// Sürüm dizesini çekirdek üçlü ve ön yayın parçalarına ayırır; yapı üstverisi atılır.
export function ayristir(dizge) {
  const [surumsuz] = dizge.split('+');
  const [cekirdek, onYayin = ''] = surumsuz.split('-', 2);
  const [buyuk, kucuk, yama] = cekirdek.split('.').map(Number);
  return {
    buyuk,
    kucuk,
    yama,
    onYayin: onYayin === '' ? [] : onYayin.split('.'),
  };
}

function parcaKarsilastir(a, b) {
  const aSayi = /^\d+$/.test(a);
  const bSayi = /^\d+$/.test(b);
  if (aSayi && bSayi) return Number(a) - Number(b);
  if (aSayi) return -1;          // sayısal parça, harfli parçadan küçüktür
  if (bSayi) return 1;
  return a < b ? -1 : a > b ? 1 : 0;
}

export function karsilastir(x, y) {
  const a = ayristir(x);
  const b = ayristir(y);
  for (const alan of ['buyuk', 'kucuk', 'yama']) {
    if (a[alan] !== b[alan]) return a[alan] - b[alan];
  }
  if (a.onYayin.length === 0 && b.onYayin.length > 0) return 1;
  if (a.onYayin.length > 0 && b.onYayin.length === 0) return -1;
  const uzunluk = Math.min(a.onYayin.length, b.onYayin.length);
  for (let i = 0; i < uzunluk; i += 1) {
    const sonuc = parcaKarsilastir(a.onYayin[i], b.onYayin[i]);
    if (sonuc !== 0) return sonuc;
  }
  return a.onYayin.length - b.onYayin.length;
}
```

```javascript
// dosya: sirala.mjs — surum.mjs yukarıdaki dosyadır
import { karsilastir } from './surum.mjs';

const surumler = ['1.10.0', '1.9.0', '2.0.0-rc.2', '2.0.0-rc.10', '2.0.0', '2.0.0-alpha', '1.9.0+derleme.7'];
console.log(surumler.sort(karsilastir).join('  <  '));
```

```
$ node sirala.mjs
1.9.0  <  1.9.0+derleme.7  <  1.10.0  <  2.0.0-alpha  <  2.0.0-rc.2  <  2.0.0-rc.10  <  2.0.0
```

Çıktıdaki dört gözlem kuralın tamamını özetler:

`1.10.0` sürümü `1.9.0` sürümünden sonra geldi — parçalar sayı olarak karşılaştırıldı.

`2.0.0-alpha` sürümü `2.0.0` sürümünden **önce** geldi. Ön yayın etiketi taşıyan bir sürüm,
aynı çekirdek üçlüye sahip etiketsiz sürümden küçüktür. Etiket, "bu sürüm henüz o sürüm
değil" anlamına gelir.

`2.0.0-rc.2` sürümü `2.0.0-rc.10` sürümünden önce geldi. Etiketin sayısal parçaları sayı
olarak karşılaştırılır; metin sırası kullanılsaydı sıra ters çıkardı.

`1.9.0` ile `1.9.0+derleme.7` karşılaştırmada **eşit** çıktı: artı işaretinden sonrası
**yapı üstverisidir (build metadata)** ve önceliğe girmez. Sıralama kararlı olduğu için
ikisi, listedeki asıl sıralarını korudu. Eşitlik, iki farklı arşifin aynı sürüm sayılması
demektir; bu yüzden yapı üstverisi yayımlanan sürümleri ayırmakta kullanılamaz.

## Sürüm Aralıkları

Bildirimdeki aralık, kabul edilen sürüm kümesini belirtir. En sık kullanılan iki işaret,
sözleşmenin iki farklı düzeyine güvenir: biri ana sürümün, diğeri ikincil sürümün sabit
kalmasını ister.

```javascript
// dosya: aralik.mjs — surum.mjs bir önceki bölümdeki dosyadır
import { ayristir, karsilastir } from './surum.mjs';

// '^' ve '~' aralıklarını [alt, ust) çiftine çevirir.
export function sinirlar(aralik) {
  const isaret = aralik[0] === '^' || aralik[0] === '~' ? aralik[0] : '=';
  const taban = isaret === '=' ? aralik : aralik.slice(1);
  const { buyuk, kucuk, yama } = ayristir(taban);
  if (isaret === '=') return [taban, `${buyuk}.${kucuk}.${yama + 1}`];
  if (isaret === '~') return [taban, `${buyuk}.${kucuk + 1}.0`];
  if (buyuk > 0) return [taban, `${buyuk + 1}.0.0`];
  if (kucuk > 0) return [taban, `0.${kucuk + 1}.0`];
  return [taban, `0.0.${yama + 1}`];
}

export function uyar(surum, aralik) {
  const [alt, ust] = sinirlar(aralik);
  const onYayinli = ayristir(surum).onYayin.length > 0;
  const tabanOnYayinli = ayristir(alt).onYayin.length > 0;
  if (onYayinli && !tabanOnYayinli) return false;
  return karsilastir(surum, alt) >= 0 && karsilastir(surum, ust) < 0;
}
```

```javascript
// dosya: deneme.mjs — aralik.mjs yukarıdaki dosyadır
import { sinirlar, uyar } from './aralik.mjs';

for (const aralik of ['^1.4.0', '~1.4.0', '^0.4.2', '^0.0.3', '1.4.0']) {
  const [alt, ust] = sinirlar(aralik);
  console.log(`${aralik.padEnd(8)} => ${alt} <= s < ${ust}`);
}

console.log('');
const denemeler = [
  ['1.4.9', '^1.4.0'], ['1.9.0', '^1.4.0'], ['2.0.0', '^1.4.0'],
  ['1.5.0', '~1.4.0'], ['0.4.9', '^0.4.2'], ['0.5.0', '^0.4.2'],
  ['2.0.0-rc.1', '^1.4.0'],
];
for (const [surum, aralik] of denemeler) {
  console.log(`${surum.padEnd(11)} ${aralik.padEnd(8)} ${uyar(surum, aralik) ? 'uyar' : 'uymaz'}`);
}
```

```
$ node deneme.mjs
^1.4.0   => 1.4.0 <= s < 2.0.0
~1.4.0   => 1.4.0 <= s < 1.5.0
^0.4.2   => 0.4.2 <= s < 0.5.0
^0.0.3   => 0.0.3 <= s < 0.0.4
1.4.0    => 1.4.0 <= s < 1.4.1

1.4.9       ^1.4.0   uyar
1.9.0       ^1.4.0   uyar
2.0.0       ^1.4.0   uymaz
1.5.0       ~1.4.0   uymaz
0.4.9       ^0.4.2   uyar
0.5.0       ^0.4.2   uymaz
2.0.0-rc.1  ^1.4.0   uymaz
```

Şapka işareti "ana sürüm değişmesin" der ve ikincil yükseltmeleri kabul eder. Tilde işareti
"ikincil sürüm de değişmesin" der ve yalnızca yama yükseltmelerini kabul eder. İşaretsiz
yazım tek bir sürümü sabitler.

Üçüncü ve dördüncü satırlar özel bir kuralı gösterir. Ana sürümü sıfır olan paketler
kararlı sayılmaz; sözleşme henüz yürürlükte değildir. Bu yüzden şapka işareti sıfırıncı ana
sürümde bir basamak sağa kayar ve ikincil sürümü sabit tutar. Sıfırıncı ikincil sürümde bir
basamak daha kayar. Bu kayma, kararsız paketlerin sessiz yükseltmelerle projeye
sızmamasını sağlar.

Son satır ön yayınlarla ilgili kuralı gösterir: `2.0.0-rc.1` sürümü sayısal olarak
`2.0.0` sürümünden küçük olsa da `^1.4.0` aralığına girmez. Ön yayınlar, aralığın tabanı
zaten bir ön yayın değilse hiçbir aralığa dahil edilmez. Aksi hâlde kararlı bir aralık,
yayımlanmamış sayılan sürümleri çekerdi.

## Sözleşmenin Sınırları

Aralık işaretlerinin verdiği rahatlık — ikincil yükseltmeleri otomatik almak — bir varsayıma
dayanır: yayıncının ikincil sürüm sözünü tutması. Bu varsayım üç yerde zayıflar.

**Kırıcı değişikliğin tanımı belirsizdir.** Belgelenmemiş bir davranışa bağlanan tüketici,
o davranış değişince kırılır; yayıncı ise açık arayüzü değiştirmediğini düşünür. Belgelenmiş
davranışın sınırı yazılı değilse anlaşmazlık kaçınılmazdır.

**Hata düzeltmesi de kırabilir.** Yanlış bir sonucu düzelten yama sürümü, o yanlış sonuca
göre yazılmış kodu bozar. Sözleşme bunu yama sayar.

**İnsan hatası vardır.** Yanlış parça artırılabilir; kırıcı bir değişiklik ikincil sürüm
olarak yayımlanabilir.

Bu üç nedenle aralıklar bir güvence değil, bir kolaylıktır. Yeniden üretilebilirliği veren
şey aralık değil, önceki derste tanıtılan kilit dosyasıdır. Aralık "hangi yükseltmeleri
kabul etmeye hazırım" der; kilit dosyası kurulu ağacın tam hâlini kaydeder.
İkisi birlikte çalışır: yükseltme kararı bilinçli bir işlemle alınır, kilit dosyası
güncellenir, sınamalar çalıştırılır.

Yayıncı tarafında sözleşmeyi işler kılan araç, **kullanımdan kaldırma (deprecation)**
adımıdır: kaldırılacak bir yetenek önce ikincil bir sürümde uyarı verecek biçimde
işaretlenir, yerine geçecek yol belgelenir, ancak bir sonraki ana sürümde kaldırılır. Bu
adım atlanırsa ana sürüm numarası yükseltmeyi bildirir ama geçişi mümkün kılmaz.

## Özet

- Sürüm numarasının üç parçası bir söz taşır: yama ve ikincil yükseltmeler kodun
  değişmeden çalışacağını, ana yükseltme değişebileceğini bildirir.
- Sözün konusu paketin açık arayüzüdür; kapsüllenmiş iç dosyalardaki değişiklik ana sürümü
  artırmaz.
- Karşılaştırma parçalar üzerinden sayısal yapılır; ön yayın etiketli sürüm etiketsizden
  küçüktür, yapı üstverisi önceliğe girmez.
- Şapka işareti ana sürümü, tilde işareti ikincil sürümü sabit tutar; ana sürümü sıfır olan
  paketlerde bu sınırlar bir basamak sağa kayar.
- Aralıklar kolaylıktır, güvence değil: kırıcı değişikliğin tanımı belirsizdir, yama
  düzeltmeleri de kırabilir. Yeniden üretilebilirliği kilit dosyası verir.

## Sonraki Adım

Şimdiye kadar tek bir paketin tek bir aralığı incelendi. Gerçek bir projede onlarca paket,
aynı bağımlılığı farklı aralıklarla ister ve bu istekler her zaman kesişmez. Sonraki ders,
kesişmediğinde ne olduğunu gösterir: ağaçta yinelenen sürümler, aynı kütüphanenin iki ayrı
örneği ve bu ikiliğin ürettiği kimlik sorunları.
