<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-08-03T10:13:27+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Dallanma Stratejileri: Ana Kodu Kırmadan Güvenle Geliştirmek</title><link href="https://sonsuzus.github.io/posts/dallanma-stratejileri-ana-kodu-kirmadan-guvenle-gelistirmek/" rel="alternate" type="text/html" title="Dallanma Stratejileri: Ana Kodu Kırmadan Güvenle Geliştirmek" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/dallanma-stratejileri-ana-kodu-kirmadan-guvenle-gelistirmek</id><content type="html" xml:base="https://sonsuzus.github.io/posts/dallanma-stratejileri-ana-kodu-kirmadan-guvenle-gelistirmek/"><![CDATA[<p>Yeni bir özelliği denerken ana uygulamayı bozmak, çalışan motora tornavidayla yaklaşmaya benzer: Küçük bir değişiklik bütün sistemi durdurabilir. Git dalları sayesinde geliştiriciler ana kod tabanından bağımsız çalışma alanları oluşturabilir, deneylerini güvenle yapabilir ve yalnızca hazır olan değişiklikleri projeye ekleyebilir.
``</p>

<h2 id="dal-nedir-ve-neden-kullanılır">Dal Nedir ve Neden Kullanılır?</h2>

<p>Dal, belirli bir commit’i gösteren hareketli bir işaretçidir. Yeni dal oluşturulduğunda Git bütün proje dosyalarını fiziksel olarak kopyalamaz; yalnızca commit geçmişinde yeni bir referans meydana getirir. Bu nedenle dal oluşturmak hızlı ve düşük maliyetlidir.</p>

<p>Bir projenin commit kümesini $C$, belirli bir dalın erişebildiği commit’leri ise $B$ ile gösterirsek dal şu şekilde düşünülebilir:</p>

\[B \subseteq C\]

<p>Her yeni commit, aktif dalın işaretçisini ileri taşır. Ana dal yerinde kalırken özellik dalı kendi geçmişini oluşturur. Böylece yarım kalan kod, üretime gönderilmeye hazır kodla karışmaz.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git switch <span class="nt">-c</span> feature/arama
</code></pre></div></div>

<p>Bu komut <code class="language-plaintext highlighter-rouge">feature/arama</code> adında yeni bir dal oluşturur ve çalışma alanını o dala geçirir. Burada yapılan commit’ler <code class="language-plaintext highlighter-rouge">main</code> dalını doğrudan etkilemez.</p>

<h2 id="yaygın-dallanma-stratejileri">Yaygın Dallanma Stratejileri</h2>

<p>Her ekip aynı geliştirme temposuna sahip değildir. Haftada birkaç kez sürüm çıkaran küçük bir web ekibiyle, aylar süren kurumsal sürümler hazırlayan ekip aynı modeli kullanmak zorunda değildir.</p>

<table>
  <thead>
    <tr>
      <th>Strateji</th>
      <th>Temel yaklaşım</th>
      <th>Avantajı</th>
      <th>Uygun olduğu ortam</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>GitHub Flow</td>
      <td>Kısa ömürlü dallar ve pull request</td>
      <td>Basit, hızlı ve anlaşılır</td>
      <td>Sürekli dağıtım yapan ekipler</td>
    </tr>
    <tr>
      <td>Git Flow</td>
      <td><code class="language-plaintext highlighter-rouge">develop</code>, özellik, sürüm ve düzeltme dalları</td>
      <td>Sürümleri düzenli biçimde ayırır</td>
      <td>Planlı sürüm yayınlayan projeler</td>
    </tr>
    <tr>
      <td>Trunk-Based</td>
      <td>Çok kısa dallar veya doğrudan ana gövde</td>
      <td>Entegrasyon gecikmesini azaltır</td>
      <td>Güçlü CI/CD kültürüne sahip ekipler</td>
    </tr>
    <tr>
      <td>Release Branching</td>
      <td>Her sürüm için ayrı bakım dalı</td>
      <td>Eski sürümlere destek sağlar</td>
      <td>Birden fazla sürümü yaşatan ürünler</td>
    </tr>
  </tbody>
</table>

<h3 id="github-flow">GitHub Flow</h3>

<p>Geliştirici <code class="language-plaintext highlighter-rouge">main</code> üzerinden bir özellik dalı açar, değişikliklerini gönderir ve pull request oluşturur. Kod incelemesiyle otomatik testler tamamlandıktan sonra dal birleştirilir. Küçük ekipler için bürokrasisi az, kullanışlı bir seçenektir.</p>

<h3 id="git-flow">Git Flow</h3>

<p>Git Flow’da <code class="language-plaintext highlighter-rouge">main</code> üretimdeki kararlı kodu, <code class="language-plaintext highlighter-rouge">develop</code> ise sıradaki sürümün birleşim alanını temsil eder. Özellikler <code class="language-plaintext highlighter-rouge">feature</code>, sürüm hazırlıkları <code class="language-plaintext highlighter-rouge">release</code>, acil üretim düzeltmeleri ise <code class="language-plaintext highlighter-rouge">hotfix</code> dallarında yürütülür. Düzenlidir; ancak çok sık dağıtım yapan ekiplerde dal trafiği küçük bir otoyol kavşağına dönüşebilir.</p>

<h3 id="trunk-based-development">Trunk-Based Development</h3>

<p>Bu yaklaşımda geliştiriciler değişiklikleri sık aralıklarla ana gövdeye entegre eder. Dallar varsa bile birkaç saat veya gün yaşar. Tamamlanmamış özellikler, feature flag kullanılarak kullanıcıdan gizlenebilir.</p>

<p>Entegrasyon riski kabaca dalın ömrü ve değişiklik büyüklüğüyle artar:</p>

\[R \propto T \times D\]

<p>Burada $R$ risk, $T$ dalın yaşam süresi, $D$ ise değişiklik miktarıdır. Uzun yaşayan ve yüzlerce dosyayı değiştiren dallar, birleştirme çatışmalarını büyütür.</p>

<h2 id="güvenli-bir-çalışma-akışı">Güvenli Bir Çalışma Akışı</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git switch main
git pull <span class="nt">--ff-only</span>
git switch <span class="nt">-c</span> fix/sepet-toplami

<span class="c"># Değişikliklerden sonra</span>
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s1">'Sepet toplamı hesaplamasını düzelt'</span>
git push <span class="nt">-u</span> origin fix/sepet-toplami
</code></pre></div></div>

<p>İlk iki komut güncel ana dalı temel almayı sağlar. Ardından hata düzeltme dalı açılır, değişiklikler commit edilir ve uzak depoya gönderilir. Son aşamada pull request açılarak test, inceleme ve onay süreçleri işletilir.</p>

<h2 id="i̇yi-dal-kullanımının-kuralları">İyi Dal Kullanımının Kuralları</h2>

<ul>
  <li>Dallara <code class="language-plaintext highlighter-rouge">feature/</code>, <code class="language-plaintext highlighter-rouge">fix/</code> veya <code class="language-plaintext highlighter-rouge">hotfix/</code> gibi anlaşılır adlar verin.</li>
  <li>Tek dalda birbiriyle ilgisiz değişiklikleri biriktirmeyin.</li>
  <li>Dalları kısa ömürlü tutun ve ana dalla düzenli olarak senkronize edin.</li>
  <li>Birleştirmeden önce otomatik testleri çalıştırın.</li>
  <li>Tamamlanan uzak dalları silerek depo görünümünü temiz tutun.</li>
  <li>Ana dalı koruma kurallarıyla doğrudan gönderimlere kapatın.</li>
</ul>

<p>Dallanma, yalnızca bir Git komutu değil, ekip içi risk yönetimi yöntemidir. Doğru strateji seçildiğinde geliştiriciler daha cesur deneyler yapar, hatalar daha kontrollü düzeltilir ve ana kod tabanı üretime hazır kalır. En iyi model en karmaşık olan değil; ekibin sürüm sıklığına, büyüklüğüne ve otomasyon seviyesine en iyi uyum sağlayandır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="Branching" /><category term="Versiyon Kontrolü" /><summary type="html"><![CDATA[Yeni bir özelliği denerken ana uygulamayı bozmak, çalışan motora tornavidayla yaklaşmaya benzer: Küçük bir değişiklik bütün sistemi durdurabilir. Git dalları sayesinde geliştiriciler ana kod tabanından bağımsız çalışma alanları oluşturabilir, deneylerini güvenle yapabilir ve yalnızca hazır olan değişiklikleri projeye ekleyebilir.]]></summary></entry><entry><title type="html">Dinamik Koleksiyonlar ve Vektörler: Heap Üzerinde Esnek Bellek Yönetimi</title><link href="https://sonsuzus.github.io/posts/dinamik-koleksiyonlar-ve-vektorler-heap-uzerinde-esnek-bellek-yonetimi/" rel="alternate" type="text/html" title="Dinamik Koleksiyonlar ve Vektörler: Heap Üzerinde Esnek Bellek Yönetimi" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/dinamik-koleksiyonlar-ve-vektorler-heap-uzerinde-esnek-bellek-yonetimi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/dinamik-koleksiyonlar-ve-vektorler-heap-uzerinde-esnek-bellek-yonetimi/"><![CDATA[<p>Sabit boyutlu bir dizi, kaç misafir geleceğini aylar öncesinden bilerek masa hazırlamaya benzer. Dinamik koleksiyon ise kapı çaldıkça masaya yeni sandalye ekler; gerektiğinde sandalyeleri kaldırır. Vektörler bu esnekliği sunarken arka planda heap belleği, kapasite hesaplarını ve eleman taşıma işlemlerini yönetir.</p>

<p>``</p>

<h2 id="sabit-dizi-ile-dinamik-vektör-arasındaki-fark">Sabit Dizi ile Dinamik Vektör Arasındaki Fark</h2>

<p>Sabit bir dizinin boyutu oluşturulurken belirlenir ve sonradan değiştirilemez. Daha fazla elemana ihtiyaç duyulursa daha büyük bir alan ayırmak, eski elemanları kopyalamak ve önceki alanı serbest bırakmak gerekir. Vektör bütün bu işleri otomatikleştiren bir soyutlamadır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Sabit boyutlu dizi</th>
      <th>Dinamik vektör</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Boyut</td>
      <td>Başlangıçta belirlenir</td>
      <td>Çalışma zamanında değişir</td>
    </tr>
    <tr>
      <td>Bellek</td>
      <td>Stack veya heap olabilir</td>
      <td>Eleman deposu genellikle heap üzerindedir</td>
    </tr>
    <tr>
      <td>Ekleme</td>
      <td>Boş yer yoksa mümkün değildir</td>
      <td>Kapasite artırılarak yapılabilir</td>
    </tr>
    <tr>
      <td>Yönetim</td>
      <td>Çoğunlukla geliştiriciye aittir</td>
      <td>Koleksiyon sınıfı tarafından gerçekleştirilir</td>
    </tr>
    <tr>
      <td>Erişim</td>
      <td>İndeksle hızlıdır</td>
      <td>İndeksle hızlıdır</td>
    </tr>
  </tbody>
</table>

<p>Vektör nesnesinin kendisi stack üzerinde bulunabilir; ancak elemanların tutulduğu büyük ve bitişik bellek bloğu heap üzerinde ayrılır. Nesne genellikle üç önemli bilgi taşır: veri bloğunun adresi, mevcut eleman sayısı ve ayrılmış toplam kapasite.</p>

<h2 id="boyut-ve-kapasite-aynı-şey-değildir">Boyut ve Kapasite Aynı Şey Değildir</h2>

<p>Vektörün <strong>size</strong> değeri gerçekten kullanılan eleman sayısını, <strong>capacity</strong> değeri ise yeniden bellek ayırmadan saklayabileceği eleman sayısını gösterir. Her eklemede bellek istemek pahalı olacağı için kapasite çoğunlukla ihtiyaçtan büyük tutulur.</p>

\[0 \leq size \leq capacity\]

<p>Kapasite dolduğunda daha büyük bir blok ayrılır. Yaygın büyüme stratejilerinden biri kapasiteyi yaklaşık iki katına çıkarmaktır:</p>

\[C_{yeni} = 2C_{eski}\]

<p>Ardından mevcut elemanlar yeni alana kopyalanır veya taşınır, eski heap bloğu serbest bırakılır ve yeni eleman eklenir. Bu yeniden yerleştirme tek seferde $O(n)$ maliyetli olsa da her eklemede gerçekleşmez. Bu nedenle sona ekleme işleminin amortize edilmiş zaman karmaşıklığı $O(1)$ kabul edilir.</p>

<h2 id="c-ile-vektörü-gözlemlemek">C++ ile Vektörü Gözlemlemek</h2>

<p>Aşağıdaki örnek, eleman eklendikçe boyut ve kapasitenin nasıl değiştiğini gösterir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">sayilar</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="mi">10</span><span class="p">);</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Boyut: "</span> <span class="o">&lt;&lt;</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">size</span><span class="p">()</span>
                  <span class="o">&lt;&lt;</span> <span class="s">", Kapasite: "</span> <span class="o">&lt;&lt;</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">capacity</span><span class="p">()</span>
                  <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">push_back</code>, elemanı sona ekler. Kapasite yeterliyse işlem doğrudan yapılır. Yeterli değilse yeni heap alanı ayrılır ve elemanlar taşınır. Kapasitenin büyüme oranı C++ standardında kesin olarak belirtilmediğinden sonuç kullanılan kütüphane uygulamasına göre değişebilir.</p>

<h2 id="önceden-yer-ayırmak">Önceden Yer Ayırmak</h2>

<p>Kaç eleman ekleneceği yaklaşık olarak biliniyorsa <code class="language-plaintext highlighter-rouge">reserve</code> kullanmak gereksiz yeniden ayırmaları önler:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">puanlar</span><span class="p">;</span>
<span class="n">puanlar</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> <span class="c1">// En az 1000 elemanlık kapasite hazırlar.</span>

<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">1000</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">puanlar</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">reserve</code>, vektörün boyutunu değiştirmez; yalnızca kapasite ayırır. Buna karşılık <code class="language-plaintext highlighter-rouge">resize</code>, eleman sayısını değiştirir ve gerekirse yeni elemanlar oluşturur.</p>

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th style="text-align: right">Boyutu değiştirir mi?</th>
      <th style="text-align: right">Kapasiteyi değiştirebilir mi?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reserve(n)</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">resize(n)</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">clear()</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Genellikle hayır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">shrink_to_fit()</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Azaltmayı deneyebilir</td>
    </tr>
  </tbody>
</table>

<h2 id="dikkat-i̇şaretçiler-geçersizleşebilir">Dikkat: İşaretçiler Geçersizleşebilir</h2>

<p>Yeniden bellek ayırma gerçekleştiğinde eski bloğu gösteren işaretçiler, referanslar ve iterator’lar geçersiz hale gelebilir. Artık tahliye edilmiş bir evin adresine kargo göndermek gibi düşünün: adres tanıdık görünür, fakat içeride kimse yoktur.</p>

<p>Vektörler hız, bitişik bellek düzeni ve esneklik arasında güçlü bir denge kurar. Yine de bu rahatlığın arkasında kapasite fazlası, taşıma maliyeti ve referans geçersizleşmesi bulunur. <code class="language-plaintext highlighter-rouge">size</code>, <code class="language-plaintext highlighter-rouge">capacity</code>, <code class="language-plaintext highlighter-rouge">reserve</code> ve yeniden ayırma mantığını bilmek, dinamik koleksiyonları yalnızca kullanmayı değil, verimli ve güvenli kullanmayı sağlar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="veri yapıları" /><category term="bellek yönetimi" /><category term="C++ vector" /><summary type="html"><![CDATA[Sabit boyutlu bir dizi, kaç misafir geleceğini aylar öncesinden bilerek masa hazırlamaya benzer. Dinamik koleksiyon ise kapı çaldıkça masaya yeni sandalye ekler; gerektiğinde sandalyeleri kaldırır. Vektörler bu esnekliği sunarken arka planda heap belleği, kapasite hesaplarını ve eleman taşıma işlemlerini yönetir.]]></summary></entry><entry><title type="html">Git Kurulumu ve VS Code Entegrasyonu: Terminale Dokunmadan Sürüm Takibi</title><link href="https://sonsuzus.github.io/posts/git-kurulumu-ve-vs-code-entegrasyonu-terminale-dokunmadan-surum-takibi/" rel="alternate" type="text/html" title="Git Kurulumu ve VS Code Entegrasyonu: Terminale Dokunmadan Sürüm Takibi" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/git-kurulumu-ve-vs-code-entegrasyonu-terminale-dokunmadan-surum-takibi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/git-kurulumu-ve-vs-code-entegrasyonu-terminale-dokunmadan-surum-takibi/"><![CDATA[<p>Kod yazarken çalışan bir özelliği yanlışlıkla bozmak, çoğu geliştiricinin yaşadığı küçük çaplı bir korku filmidir. Git, projenin değişim geçmişini kaydederek bu filmi mutlu sonla bitirir. VS Code entegrasyonu sayesinde dosya değişikliklerini görmek, commit oluşturmak ve uzak depoya göndermek için terminal komutlarını ezberlemek de gerekmez.
``</p>
<h2 id="git-neyi-çözer">Git neyi çözer?</h2>

<p>Git, <strong>dağıtık versiyon kontrol sistemi</strong>dir. Projenin yalnızca son durumunu değil, belirli zamanlarda kaydedilen sürümlerini de saklar. Her geliştiricide deponun geçmişini içeren yerel bir kopya bulunur. Böylece internet bağlantısı olmadan commit oluşturulabilir ve geçmiş incelenebilir.</p>

<p>Bir dosyanın Git içindeki yolculuğu üç temel alandan geçer:</p>

<table>
  <thead>
    <tr>
      <th>Alan</th>
      <th>Anlamı</th>
      <th>VS Code karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Working Directory</td>
      <td>Üzerinde çalışılan güncel dosyalar</td>
      <td>Editörde değiştirdiğiniz dosyalar</td>
    </tr>
    <tr>
      <td>Staging Area</td>
      <td>Sonraki commit için seçilen değişiklikler</td>
      <td><strong>Changes</strong> listesindeki <code class="language-plaintext highlighter-rouge">+</code> işlemi</td>
    </tr>
    <tr>
      <td>Repository</td>
      <td>Kalıcı olarak kaydedilmiş geçmiş</td>
      <td>Oluşturulan commit kayıtları</td>
    </tr>
  </tbody>
</table>

<p>Bir commit, projenin tamamının gelişigüzel kopyası değildir. Git içerikleri nesneler ve referanslar üzerinden verimli biçimde izler. Basitleştirilmiş olarak bir commit’i şöyle düşünebiliriz:</p>

\[C_n = H(D_n + C_{n-1} + M_n)\]

<p>Burada $D_n$ dosya durumunu, $C_{n-1}$ önceki commit’i, $M_n$ açıklama ve yazar gibi meta verileri, $H$ ise özetleme fonksiyonunu temsil eder. Bu bağlantılı yapı geçmişin tutarlı biçimde takip edilmesini sağlar.</p>

<h2 id="git-kurulumu">Git kurulumu</h2>

<p>Windows kullanıcıları Git’i <a href="https://git-scm.com/">git-scm.com</a> üzerinden indirebilir. Kurulum sihirbazındaki varsayılan seçenekler çoğu kullanıcı için uygundur. macOS üzerinde resmi yükleyici veya Homebrew, Linux üzerinde ise dağıtımın paket yöneticisi kullanılabilir.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># macOS</span>
brew <span class="nb">install </span>git

<span class="c"># Ubuntu ve Debian</span>
<span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install </span>git
</code></pre></div></div>

<p>Kurulumdan sonra kullanıcı bilgileri bir kez yapılandırılır. Bu bilgiler commit’lerin kime ait olduğunu belirtir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config <span class="nt">--global</span> user.name <span class="s1">'Ada Geliştirici'</span>
git config <span class="nt">--global</span> user.email <span class="s1">'ada@example.com'</span>
</code></pre></div></div>

<p>Terminal kullanmak istemiyorsanız bu ayarları VS Code içindeki <strong>Settings</strong> ekranından <code class="language-plaintext highlighter-rouge">git config</code> aramasıyla veya Git istemcisinin kurulum aşamasında belirleyebilirsiniz. Kurulumu doğrulamak için VS Code’u yeniden başlatmak önemlidir.</p>

<h2 id="vs-code-ile-depo-oluşturma">VS Code ile depo oluşturma</h2>

<p>Proje klasörünü VS Code’da açın ve sol kenar çubuğundaki dallanma simgesine, yani <strong>Source Control</strong> görünümüne tıklayın. Klasör henüz Git tarafından izlenmiyorsa <strong>Initialize Repository</strong> düğmesi görünür. Bu düğme, klasörde gizli bir <code class="language-plaintext highlighter-rouge">.git</code> dizini oluşturarak yerel depoyu hazırlar.</p>

<p>Bir dosyayı değiştirdiğinizde <strong>Changes</strong> bölümünde listelenir. Dosyaya tıklamak, eski ve yeni hâli yan yana gösteren karşılaştırma ekranını açar. Satırların anlamı oldukça görseldir:</p>

<table>
  <thead>
    <tr>
      <th>Görünüm</th>
      <th>Anlamı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yeşil satırlar</td>
      <td>Eklenen içerik</td>
    </tr>
    <tr>
      <td>Kırmızı satırlar</td>
      <td>Silinen içerik</td>
    </tr>
    <tr>
      <td>Mavi işaretler</td>
      <td>Değiştirilen bölge</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">U</code> rozeti</td>
      <td>Henüz izlenmeyen dosya</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">M</code> rozeti</td>
      <td>Değiştirilmiş dosya</td>
    </tr>
  </tbody>
</table>

<p>Commit’e eklenecek dosyanın yanındaki <code class="language-plaintext highlighter-rouge">+</code> simgesine basarak dosyayı <strong>Staged Changes</strong> alanına taşıyın. Üstteki kutuya <code class="language-plaintext highlighter-rouge">Kullanıcı giriş ekranını ekle</code> gibi açıklayıcı bir mesaj yazın ve <strong>Commit</strong> düğmesine basın. İyi bir commit tek bir mantıksal değişikliği kapsamalıdır; yüz farklı işi aynı pakete doldurmak, gelecekteki size bırakılmış bir bilmece olur.</p>

<h2 id="github-ile-eşitleme">GitHub ile eşitleme</h2>

<p>VS Code’daki <strong>Publish Branch</strong> veya <strong>Publish to GitHub</strong> seçeneği, yerel depoyu GitHub’a göndermeyi kolaylaştırır. İlk kullanımda tarayıcı üzerinden GitHub hesabına giriş izni istenir. Sonrasında <strong>Sync Changes</strong> düğmesi iki işlemi yönetir:</p>

<ul>
  <li><strong>Push:</strong> Yerel commit’leri uzak depoya gönderir.</li>
  <li><strong>Pull:</strong> Uzak depodaki yeni commit’leri bilgisayara getirir.</li>
</ul>

<p>Dallar arasında geçmek için pencerenin sol altındaki dal adına tıklayabilirsiniz. Yeni özellikleri ayrı bir dalda geliştirmek, ana sürümü korur. Çakışma oluşursa VS Code; mevcut değişikliği, gelen değişikliği veya ikisini birlikte kabul etme seçenekleri sunar.</p>

<p>Son olarak <code class="language-plaintext highlighter-rouge">.env</code>, parola, derleme çıktıları ve <code class="language-plaintext highlighter-rouge">node_modules</code> gibi gereksiz ya da gizli içerikleri <code class="language-plaintext highlighter-rouge">.gitignore</code> dosyasına ekleyin. Böylece görsel araçların rahatlığıyla güvenli ve düzenli bir sürüm geçmişi oluşturabilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="VS Code" /><category term="Versiyon Kontrolü" /><summary type="html"><![CDATA[Kod yazarken çalışan bir özelliği yanlışlıkla bozmak, çoğu geliştiricinin yaşadığı küçük çaplı bir korku filmidir. Git, projenin değişim geçmişini kaydederek bu filmi mutlu sonla bitirir. VS Code entegrasyonu sayesinde dosya değişikliklerini görmek, commit oluşturmak ve uzak depoya göndermek için terminal komutlarını ezberlemek de gerekmez.]]></summary></entry><entry><title type="html">Git Merge ve Conflict Çözümü: Dalları Birleştirme Sanatı</title><link href="https://sonsuzus.github.io/posts/git-merge-ve-conflict-cozumu-dallari-birlestirme-sanati/" rel="alternate" type="text/html" title="Git Merge ve Conflict Çözümü: Dalları Birleştirme Sanatı" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/git-merge-ve-conflict-cozumu-dallari-birlestirme-sanati</id><content type="html" xml:base="https://sonsuzus.github.io/posts/git-merge-ve-conflict-cozumu-dallari-birlestirme-sanati/"><![CDATA[<p>Yazılım ekiplerinde herkes aynı dosyaya sırayla dokunsaydı hayat kolay, geliştirme süreci ise epey yavaş olurdu. Git dalları sayesinde geliştiriciler paralel çalışabilir; ancak bu çalışmaların eninde sonunda yeniden buluşması gerekir. <code class="language-plaintext highlighter-rouge">merge</code>, farklı dallardaki değişiklikleri ortak bir geçmişte birleştirirken conflict çözümü Git’in karar veremediği noktalarda insan muhakemesini devreye sokar.
``</p>
<h2 id="merge-mantığı-i̇ki-geçmiş-tek-sonuç">Merge Mantığı: İki Geçmiş, Tek Sonuç</h2>

<p>Bir dal, belirli bir commit’ten başlayan bağımsız geliştirme çizgisidir. Örneğin <code class="language-plaintext highlighter-rouge">main</code> üretime hazır kodu taşırken <code class="language-plaintext highlighter-rouge">feature/login</code> yeni giriş ekranını içerebilir. Özellik tamamlandığında hedefimiz, feature dalındaki commit’leri <code class="language-plaintext highlighter-rouge">main</code> dalına aktarmaktır.</p>

<p>Commit geçmişini yönlü bir grafik gibi düşünebiliriz. Her commit bir düğüm, ebeveyn bağlantıları ise kenardır. İki dalın ortak atasını $B$, dal uçlarını $M$ ve $F$ olarak gösterirsek üç yönlü birleştirme şu değişimleri karşılaştırır:</p>

\[\Delta_M = M - B \qquad \Delta_F = F - B\]

<p>Git, $\Delta_M$ ile $\Delta_F$ değişikliklerini uyumlu biçimde uygulayabiliyorsa merge otomatik tamamlanır. Aynı bölge farklı şekillerde değiştirilmişse karar kullanıcıya bırakılır.</p>

<table>
  <thead>
    <tr>
      <th>Birleştirme türü</th>
      <th>Ne zaman oluşur?</th>
      <th>Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Fast-forward</td>
      <td>Hedef dalda yeni commit yoksa</td>
      <td>Dal işaretçisi ileri taşınır</td>
    </tr>
    <tr>
      <td>Three-way merge</td>
      <td>Her iki dal da ilerlediyse</td>
      <td>Yeni bir merge commit’i oluşur</td>
    </tr>
    <tr>
      <td>Conflict</td>
      <td>Aynı içerik uyumsuz değiştirildiyse</td>
      <td>Manuel çözüm gerekir</td>
    </tr>
  </tbody>
</table>

<h2 id="temel-bir-merge-i̇şlemi">Temel Bir Merge İşlemi</h2>

<p>Önce hedef dala geçilir, güncel durum alınır ve kaynak dal birleştirilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git switch main
git pull origin main
git merge feature/login
</code></pre></div></div>

<p>Burada önemli ayrıntı şudur: <code class="language-plaintext highlighter-rouge">feature/login</code>, içinde bulunduğumuz <code class="language-plaintext highlighter-rouge">main</code> dalına eklenir. Git temiz bir birleştirme yaparsa işlem tamamdır. Takım politikasına göre dal daha sonra silinebilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-d</span> feature/login
</code></pre></div></div>

<h2 id="conflict-neden-oluşur">Conflict Neden Oluşur?</h2>

<p>Diyelim ki iki geliştirici aynı fonksiyonun dönüş mesajını değiştirdi. Git hangi mesajın iş kuralını doğru temsil ettiğini bilemez. Dosyada şu işaretleri bırakır:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
return "Ana daldaki mesaj";
=======
return "Özellik dalındaki mesaj";
&gt;&gt;&gt;&gt;&gt;&gt;&gt; feature/login
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD</code> mevcut dalın, <code class="language-plaintext highlighter-rouge">&gt;&gt;&gt;&gt;&gt;&gt;&gt; feature/login</code> ise birleştirilen dalın içeriğini gösterir. Ortadaki <code class="language-plaintext highlighter-rouge">=======</code> iki sürümü ayırır. Çözüm, işaretleri silip doğru nihai kodu oluşturmaktır; seçeneklerden birini körü körüne seçmek zorunlu değildir.</p>

<p>Örneğin iki fikri birleştiren sonuç şöyle olabilir:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">loginMessage</span><span class="p">(</span><span class="nx">username</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="s2">`Hoş geldin </span><span class="p">${</span><span class="nx">username</span><span class="p">}</span><span class="s2">, giriş başarılı!`</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Ardından çözüm Git’e bildirilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add src/login.js
git commit <span class="nt">-m</span> <span class="s2">"Resolve login message conflict"</span>
</code></pre></div></div>

<p>Tüm çakışmaları görmek için <code class="language-plaintext highlighter-rouge">git status</code>, yapılan düzenlemeyi incelemek için <code class="language-plaintext highlighter-rouge">git diff</code> kullanılabilir. Yanlış yola girildiyse <code class="language-plaintext highlighter-rouge">git merge --abort</code>, çalışma alanını merge öncesi duruma döndürür.</p>

<h2 id="güvenli-çözüm-stratejisi">Güvenli Çözüm Stratejisi</h2>

<p>Conflict çözmek yalnızca sözdizimini düzeltmek değildir; iki değişikliğin niyetini anlamaktır. Önce çakışan commit’leri ve ilgili gereksinimleri inceleyin. Ardından küçük parçalar hâlinde düzenleme yapın, testleri çalıştırın ve davranışın korunduğunu doğrulayın.</p>

<table>
  <thead>
    <tr>
      <th>Riskli yaklaşım</th>
      <th>Güvenli yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tüm incoming değişiklikleri seçmek</td>
      <td>Her bloğun amacını değerlendirmek</td>
    </tr>
    <tr>
      <td>Test etmeden commit atmak</td>
      <td>Birim ve entegrasyon testlerini çalıştırmak</td>
    </tr>
    <tr>
      <td>Devasa dalları geç birleştirmek</td>
      <td>Küçük ve sık merge yapmak</td>
    </tr>
    <tr>
      <td>Conflict işaretlerini unutmak</td>
      <td><code class="language-plaintext highlighter-rouge">git diff --check</code> ile doğrulamak</td>
    </tr>
  </tbody>
</table>

<p>Son olarak merge commit’ini uzak depoya göndermeden önce uygulamayı derlemek ve test paketini çalıştırmak gerekir. Unutmayın: Git satırları birleştirir, fakat ürün davranışının doğru olup olmadığına karar veremez. Başarılı conflict çözümü; araç bilgisi, iletişim ve biraz da kod dedektifliği gerektirir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="Merge" /><category term="Conflict" /><summary type="html"><![CDATA[Yazılım ekiplerinde herkes aynı dosyaya sırayla dokunsaydı hayat kolay, geliştirme süreci ise epey yavaş olurdu. Git dalları sayesinde geliştiriciler paralel çalışabilir; ancak bu çalışmaların eninde sonunda yeniden buluşması gerekir. merge, farklı dallardaki değişiklikleri ortak bir geçmişte birleştirirken conflict çözümü Git’in karar veremediği noktalarda insan muhakemesini devreye sokar.]]></summary></entry><entry><title type="html">Git Push ve Pull ile Senkronizasyon Akışı</title><link href="https://sonsuzus.github.io/posts/git-push-ve-pull-ile-senkronizasyon-akisi/" rel="alternate" type="text/html" title="Git Push ve Pull ile Senkronizasyon Akışı" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/git-push-ve-pull-ile-senkronizasyon-akisi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/git-push-ve-pull-ile-senkronizasyon-akisi/"><![CDATA[<p>Bir ekip projesinde kod yazmak kadar, yazılan kodu doğru yere ve doğru zamanda ulaştırmak da önemlidir. Git’in <strong>push</strong> ve <strong>pull</strong> komutları, yerel bilgisayarımız ile GitHub, GitLab veya Bitbucket gibi uzak sunucular arasında köprü kurar. Biri tamamladığımız çalışmaları dışarı gönderirken diğeri ekip arkadaşlarımızın değişikliklerini içeri alır; yani biri kargoyu yollar, diğeri kapıda teslim alır.</p>

<p>``</p>

<h2 id="yerel-ve-uzak-depo-mantığı">Yerel ve Uzak Depo Mantığı</h2>

<p>Git ile çalışırken aslında birbirinden bağımsız iki depo bulunur:</p>

<ul>
  <li><strong>Yerel depo (local repository):</strong> Bilgisayarımızdaki proje geçmişidir.</li>
  <li><strong>Uzak depo (remote repository):</strong> Ekibin ortak kullandığı sunucu kopyasıdır.</li>
</ul>

<p>Dosyayı kaydetmek, değişikliği otomatik olarak uzak sunucuya göndermez. Önce değişiklik çalışma alanında oluşur, ardından <code class="language-plaintext highlighter-rouge">git add</code> ile hazırlama alanına alınır ve <code class="language-plaintext highlighter-rouge">git commit</code> ile yerel geçmişe kaydedilir. Ancak bundan sonra <code class="language-plaintext highlighter-rouge">git push</code> kullanılarak uzak depoya aktarılabilir.</p>

<p>Bu akışı basitçe şöyle gösterebiliriz:</p>

\[Çalışma\ Alanı \rightarrow Staging \rightarrow Yerel\ Depo \rightarrow Uzak\ Depo\]

<p>Senkronizasyon durumunu kabaca bir fark denklemiyle de düşünebiliriz:</p>

\[Fark = Yerel\ Commit\ Sayısı - Uzak\ Commit\ Sayısı\]

<p>$Fark &gt; 0$ ise gönderilecek yerel commit’lerimiz vardır. $Fark &lt; 0$ ise uzak depoda henüz almadığımız güncellemeler bulunabilir. Gerçekte Git yalnızca sayıları değil, commit’ler arasındaki yönlü geçmiş ilişkisini inceler.</p>

<h2 id="push-ve-pull-karşılaştırması">Push ve Pull Karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th><code class="language-plaintext highlighter-rouge">git push</code></th>
      <th><code class="language-plaintext highlighter-rouge">git pull</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Veri yönü</td>
      <td>Yerelden uzağa</td>
      <td>Uzaktan yerele</td>
    </tr>
    <tr>
      <td>Temel amaç</td>
      <td>Commit’leri paylaşmak</td>
      <td>Güncellemeleri almak</td>
    </tr>
    <tr>
      <td>Geçmişe etkisi</td>
      <td>Uzak dalı ilerletir</td>
      <td>Yerel dalı birleştirir</td>
    </tr>
    <tr>
      <td>Olası sorun</td>
      <td>Push reddedilebilir</td>
      <td>Birleştirme çakışması oluşabilir</td>
    </tr>
    <tr>
      <td>Güvenli alışkanlık</td>
      <td>Önce pull yapmak</td>
      <td>Değişiklikleri kontrol etmek</td>
    </tr>
  </tbody>
</table>

<h2 id="değişiklikleri-uzak-sunucuya-göndermek">Değişiklikleri Uzak Sunucuya Göndermek</h2>

<p>Aşağıdaki komutlar tamamlanan bir özelliği kaydeder ve <code class="language-plaintext highlighter-rouge">main</code> dalına gönderir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s2">"Kullanıcı profil ekranını ekle"</span>
git push origin main
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">git status</code>, hangi dosyaların değiştiğini gösterir. <code class="language-plaintext highlighter-rouge">git add .</code>, değişiklikleri hazırlama alanına taşır. <code class="language-plaintext highlighter-rouge">git commit</code>, bu aşamanın yerel anlık görüntüsünü oluşturur. Son komuttaki <code class="language-plaintext highlighter-rouge">origin</code>, uzak deponun yaygın takma adı; <code class="language-plaintext highlighter-rouge">main</code> ise gönderilecek daldır.</p>

<p>İlk gönderimde dalın takip ilişkisini kurmak gerekebilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push <span class="nt">-u</span> origin feature/profil
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">-u</code> seçeneği yerel dalı uzak dalla ilişkilendirir. Sonraki işlemlerde yalnızca <code class="language-plaintext highlighter-rouge">git push</code> yazmak çoğunlukla yeterli olur.</p>

<h2 id="güncellemeleri-çalışma-alanına-çekmek">Güncellemeleri Çalışma Alanına Çekmek</h2>

<p>Ekip arkadaşımız uzak depoya yeni commit gönderdiyse bunları şu şekilde alabiliriz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git switch main
git pull origin main
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">git pull</code>, perde arkasında iki işi birlikte gerçekleştirir:</p>

\[git\ pull = git\ fetch + git\ merge\]

<p>Önce <code class="language-plaintext highlighter-rouge">fetch</code> uzak geçmişi indirir, ardından <code class="language-plaintext highlighter-rouge">merge</code> bu geçmişi mevcut dalımızla birleştirir. Süreci daha kontrollü yürütmek isteyenler iki adımı ayrı çalıştırabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin
git log <span class="nt">--oneline</span> main..origin/main
git merge origin/main
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">git log</code>, uzakta bulunan fakat yerel <code class="language-plaintext highlighter-rouge">main</code> dalında olmayan commit’leri gösterir. Böylece neyi birleştirdiğimizi önceden görebiliriz.</p>

<h2 id="çakışmalar-ve-sağlıklı-akış">Çakışmalar ve Sağlıklı Akış</h2>

<p>Aynı dosyanın aynı satırları iki kişi tarafından değiştirilmişse Git hangi sürümün doğru olduğuna karar veremez ve <strong>conflict</strong> oluşturur. Çakışmalı bölümler elle düzenlenir, test edilir ve yeniden commit edilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add duzeltilen-dosya.js
git commit <span class="nt">-m</span> <span class="s2">"Birleştirme çakışmasını çöz"</span>
git push
</code></pre></div></div>

<p>Sağlıklı bir ekip akışında güne <code class="language-plaintext highlighter-rouge">git pull</code> ile başlamak, küçük ve anlamlı commit’ler oluşturmak, push öncesinde testleri çalıştırmak ve doğrudan <code class="language-plaintext highlighter-rouge">main</code> yerine özellik dalları kullanmak faydalıdır. Kısacası <strong>pull dinlemeyi, push konuşmayı temsil eder</strong>. İyi bir Git kullanıcısı ise yalnızca konuşmaz; önce ekibin en güncel hâlini dinler.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="GitHub" /><category term="Sürüm Kontrolü" /><summary type="html"><![CDATA[Bir ekip projesinde kod yazmak kadar, yazılan kodu doğru yere ve doğru zamanda ulaştırmak da önemlidir. Git’in push ve pull komutları, yerel bilgisayarımız ile GitHub, GitLab veya Bitbucket gibi uzak sunucular arasında köprü kurar. Biri tamamladığımız çalışmaları dışarı gönderirken diğeri ekip arkadaşlarımızın değişikliklerini içeri alır; yani biri kargoyu yollar, diğeri kapıda teslim alır.]]></summary></entry><entry><title type="html">Git Temelleri: Değişiklikleri Anlamlı Commit’lerle Kaydetmek</title><link href="https://sonsuzus.github.io/posts/git-temelleri-degisiklikleri-anlamli-commitlerle-kaydetmek/" rel="alternate" type="text/html" title="Git Temelleri: Değişiklikleri Anlamlı Commit’lerle Kaydetmek" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/git-temelleri-degisiklikleri-anlamli-commitlerle-kaydetmek</id><content type="html" xml:base="https://sonsuzus.github.io/posts/git-temelleri-degisiklikleri-anlamli-commitlerle-kaydetmek/"><![CDATA[<p>Bir projede kod yazarken yalnızca sonucun çalışması yeterli değildir; hangi değişikliğin ne zaman ve neden yapıldığını da bilmek gerekir. Git, projenin belirli anlarını yerel bir tarihçeye kaydederek geçmişe bakmayı, hataları izlemeyi ve güvenle deney yapmayı sağlar. Commit ise bu tarihçedeki sıradan bir kayıt değil, projenin belirli bir andaki anlamlı fotoğrafıdır.
``</p>
<h2 id="gitin-temel-yaklaşımı-anlık-fotoğraflar">Git’in temel yaklaşımı: Anlık fotoğraflar</h2>

<p>Git çoğu zaman yalnızca satır satır farkları saklayan bir araç gibi düşünülür. Oysa temel modeli <strong>snapshot</strong>, yani anlık fotoğraf yaklaşımıdır. Commit oluşturulduğunda Git, izlenen dosyaların o andaki durumunu temsil eden bir kayıt üretir. Değişmeyen dosyalar için mevcut nesneler yeniden kullanılabildiğinden bu yöntem düşündüğünüzden daha verimlidir.</p>

<p>Her commit; proje ağacına, yazara, tarihe, açıklama mesajına ve genellikle bir önceki commit’e referans verir. Böylece commit’ler birbirine bağlanarak bir tarihçe oluşturur:</p>

\[C_n = S_n + P(C_{n-1}) + M_n + A_n\]

<p>Burada $S_n$ proje fotoğrafını, $P(C_{n-1})$ önceki commit referansını, $M_n$ mesajı ve $A_n$ yazar bilgilerini temsil eder. İçeriğin özeti alınarak commit kimliği üretilir. Bu nedenle geçmişteki bir kaydın içeriği değiştirilirse kimliği de değişir.</p>

<h2 id="üç-çalışma-alanını-anlamak">Üç çalışma alanını anlamak</h2>

<p>Git kullanımındaki karışıklıkların büyük bölümü çalışma dizini, staging area ve repository ayrımının bilinmemesinden kaynaklanır.</p>

<table>
  <thead>
    <tr>
      <th>Alan</th>
      <th>Görevi</th>
      <th>İlgili komut</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Working Directory</td>
      <td>Dosyaları düzenlediğiniz aktif alan</td>
      <td><code class="language-plaintext highlighter-rouge">git status</code></td>
    </tr>
    <tr>
      <td>Staging Area</td>
      <td>Sonraki commit’e girecek değişikliklerin seçildiği alan</td>
      <td><code class="language-plaintext highlighter-rouge">git add</code></td>
    </tr>
    <tr>
      <td>Repository</td>
      <td>Commit’lerin kalıcı yerel tarihçesi</td>
      <td><code class="language-plaintext highlighter-rouge">git commit</code></td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">git add</code>, değişikliği doğrudan tarihçeye kaydetmez. Yalnızca bir sonraki fotoğrafa hangi düzenlemelerin gireceğini belirler. Bu ara katman, aynı anda yaptığınız ilgisiz değişiklikleri ayrı commit’lere bölmenizi sağlar.</p>

<h2 id="i̇lk-anlamlı-commit-akışı">İlk anlamlı commit akışı</h2>

<p>Aşağıdaki komutlar yeni bir depo oluşturur, durumu inceler ve seçilen değişiklikleri kaydeder:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init
git status
git add README.md src/app.js
git diff <span class="nt">--staged</span>
git commit <span class="nt">-m</span> <span class="s2">"Kullanıcı giriş doğrulamasını ekle"</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">git diff --staged</code>, commit oluşturulmadan önce sahnelenen içeriği gösterir. Bu küçük kontrol, yanlışlıkla şifre, geçici dosya veya ilgisiz kod kaydetme riskini azaltır. Commit sonrasında <code class="language-plaintext highlighter-rouge">git log --oneline</code> ile kısa tarihçe görüntülenebilir.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git log <span class="nt">--oneline</span> <span class="nt">--decorate</span>
git show HEAD
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">git show HEAD</code>, son commit’in bilgilerini ve değişikliklerini incelemek için kullanılır. Buradaki <code class="language-plaintext highlighter-rouge">HEAD</code>, üzerinde çalıştığınız güncel commit’i işaret eder.</p>

<h2 id="i̇yi-commit-mesajı-ne-anlatır">İyi commit mesajı ne anlatır?</h2>

<p>“Değişiklik yaptım” veya “son düzeltme” gibi mesajlar gelecekte kimseye yardımcı olmaz. İyi bir mesaj, kodda görülebilen ayrıntıyı tekrarlamak yerine değişikliğin amacını açıklar.</p>

<table>
  <thead>
    <tr>
      <th>Zayıf mesaj</th>
      <th>Daha iyi mesaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">güncelleme</code></td>
      <td><code class="language-plaintext highlighter-rouge">Sepet toplamında indirim oranını uygula</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">bug fix</code></td>
      <td><code class="language-plaintext highlighter-rouge">Boş e-postada oluşan doğrulama hatasını düzelt</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">kodlar eklendi</code></td>
      <td><code class="language-plaintext highlighter-rouge">Siparişler için sayfalama desteği ekle</code></td>
    </tr>
  </tbody>
</table>

<p>Mesajın emir kipinde, kısa ve odaklı olması okunabilirliği artırır. Büyük bir commit içinde özellik, biçimlendirme ve hata düzeltmesi karıştırmak yerine her mantıksal işi ayrı kaydetmek daha sağlıklıdır.</p>

<h2 id="commit-atmadan-önce-mini-kontrol">Commit atmadan önce mini kontrol</h2>

<p>Önce <code class="language-plaintext highlighter-rouge">git status</code> ile kapsamı, ardından <code class="language-plaintext highlighter-rouge">git diff</code> ile değişiklikleri inceleyin. İlgili testleri çalıştırın, yalnızca aynı amacı taşıyan dosyaları staging area’ya ekleyin ve “Bu commit neden var?” sorusunu cevaplayan bir mesaj yazın.</p>

<p>Commit’i bir yedekleme düğmesi değil, gelecekteki geliştiriciye bırakılan açıklamalı bir zaman kapsülü olarak düşünün. Küçük, çalışır ve anlamlı commit’ler; hata ayıklamayı, kod incelemeyi ve gerektiğinde güvenli biçimde geçmişe dönmeyi ciddi ölçüde kolaylaştırır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="Versiyon Kontrolü" /><category term="Commit" /><summary type="html"><![CDATA[Bir projede kod yazarken yalnızca sonucun çalışması yeterli değildir; hangi değişikliğin ne zaman ve neden yapıldığını da bilmek gerekir. Git, projenin belirli anlarını yerel bir tarihçeye kaydederek geçmişe bakmayı, hataları izlemeyi ve güvenle deney yapmayı sağlar. Commit ise bu tarihçedeki sıradan bir kayıt değil, projenin belirli bir andaki anlamlı fotoğrafıdır.]]></summary></entry><entry><title type="html">Git Uzak Depolar ve Klonlama: Kodun Bulutla Buluşması</title><link href="https://sonsuzus.github.io/posts/git-uzak-depolar-ve-klonlama-kodun-bulutla-bulusmasi/" rel="alternate" type="text/html" title="Git Uzak Depolar ve Klonlama: Kodun Bulutla Buluşması" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/git-uzak-depolar-ve-klonlama-kodun-bulutla-bulusmasi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/git-uzak-depolar-ve-klonlama-kodun-bulutla-bulusmasi/"><![CDATA[<p>Bir projeyi yalnızca kendi bilgisayarında tutmak, bütün yumurtaları aynı sepete koymaya benzer. Git’in uzak depo mekanizması sayesinde kodlar GitHub, GitLab veya Bitbucket gibi servislerde saklanabilir; ekip üyeleri aynı proje üzerinde çalışabilir ve yerel değişiklikler dış dünyayla paylaşılabilir. Bu süreçte <code class="language-plaintext highlighter-rouge">clone</code>, <code class="language-plaintext highlighter-rouge">remote</code>, <code class="language-plaintext highlighter-rouge">fetch</code>, <code class="language-plaintext highlighter-rouge">pull</code> ve <code class="language-plaintext highlighter-rouge">push</code> komutları başrolü üstlenir.</p>

<p>``</p>

<h2 id="yerel-ve-uzak-depo-nedir">Yerel ve uzak depo nedir?</h2>

<p><strong>Yerel depo</strong>, bilgisayarındaki çalışma dosyalarını, commit geçmişini, dalları ve Git metadata’sını içeren depodur. <strong>Uzak depo</strong> ise genellikle internete bağlı bir sunucuda barındırılan ve ekip için ortak buluşma noktası görevi gören Git deposudur.</p>

<p>Git dağıtık bir sürüm kontrol sistemi olduğu için uzak sunucu, geçmişin tek sahibi değildir. Bir projeyi klonladığında commit geçmişinin tamamına yakın bir kopyasını alırsın. Başka bir deyişle yerel depo $L$, uzak depo $R$ ile gösterilirse klonlama sonrasında başlangıçta yaklaşık olarak şu ilişki kurulur:</p>

\[L \approx R\]

<p>Zamanla iki tarafta farklı commit’ler oluşabilir. Ayrışma miktarını basitçe şu şekilde düşünebiliriz:</p>

\[\Delta = |C_L \triangle C_R|\]

<p>Burada $C_L$ ve $C_R$ yerel ve uzak commit kümelerini, $\triangle$ ise iki küme arasındaki farklılığı temsil eder. <code class="language-plaintext highlighter-rouge">fetch</code>, <code class="language-plaintext highlighter-rouge">pull</code> ve <code class="language-plaintext highlighter-rouge">push</code> işlemleri bu farkı yönetmemizi sağlar.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Yerel depo</th>
      <th>Uzak depo</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Konum</td>
      <td>Kendi bilgisayarın</td>
      <td>Git sunucusu veya bulut servisi</td>
    </tr>
    <tr>
      <td>İnternet gereksinimi</td>
      <td>Çoğu işlemde gerekmez</td>
      <td>Veri alışverişinde gerekir</td>
    </tr>
    <tr>
      <td>Temel amaç</td>
      <td>Geliştirme ve commit oluşturma</td>
      <td>Paylaşım, yedekleme ve iş birliği</td>
    </tr>
    <tr>
      <td>Tipik dallar</td>
      <td><code class="language-plaintext highlighter-rouge">main</code>, özellik dalları</td>
      <td><code class="language-plaintext highlighter-rouge">origin/main</code>, ekip dalları</td>
    </tr>
  </tbody>
</table>

<h2 id="bir-projeyi-klonlamak">Bir projeyi klonlamak</h2>

<p>Var olan bir uzak projeyi bilgisayara indirmek için <code class="language-plaintext highlighter-rouge">git clone</code> kullanılır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/kullanici/proje.git
<span class="nb">cd </span>proje
</code></pre></div></div>

<p>Bu komut yalnızca dosyaları indirmez. Commit geçmişini getirir, çalışma dizinini hazırlar ve uzak adresi varsayılan olarak <code class="language-plaintext highlighter-rouge">origin</code> adıyla kaydeder. Farklı bir klasör adı kullanmak da mümkündür:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/kullanici/proje.git benim-projem
</code></pre></div></div>

<p>HTTPS kolay başlangıç sunarken SSH, anahtar tabanlı kimlik doğrulamasıyla sık işlem yapan geliştiriciler için daha rahattır.</p>

<table>
  <thead>
    <tr>
      <th>Bağlantı türü</th>
      <th>Örnek</th>
      <th>Avantajı</th>
      <th>Dikkat edilmesi gereken</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>HTTPS</td>
      <td><code class="language-plaintext highlighter-rouge">https://github.com/a/b.git</code></td>
      <td>Kurulumu kolaydır</td>
      <td>Token gerekebilir</td>
    </tr>
    <tr>
      <td>SSH</td>
      <td><code class="language-plaintext highlighter-rouge">git@github.com:a/b.git</code></td>
      <td>Parolasız ve güvenli kullanım</td>
      <td>SSH anahtarı kurulmalıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="yerel-depoyu-uzak-sunucuya-bağlamak">Yerel depoyu uzak sunucuya bağlamak</h2>

<p>Bilgisayarında sıfırdan oluşturduğun bir projeyi uzak depoya bağlamak için önce serviste boş bir depo oluşturabilir, ardından şu komutları çalıştırabilirsin:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s2">"İlk sürüm"</span>
git branch <span class="nt">-M</span> main
git remote add origin git@github.com:kullanici/proje.git
git push <span class="nt">-u</span> origin main
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">git remote add origin ...</code>, adrese <code class="language-plaintext highlighter-rouge">origin</code> takma adını verir. <code class="language-plaintext highlighter-rouge">git push -u origin main</code> ise yerel <code class="language-plaintext highlighter-rouge">main</code> dalını sunucuya gönderir ve takip ilişkisi kurar. Sonraki gönderimlerde çoğunlukla yalnızca <code class="language-plaintext highlighter-rouge">git push</code> yazmak yeterlidir.</p>

<p>Kayıtlı bağlantıları incelemek için:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote <span class="nt">-v</span>
</code></pre></div></div>

<p>Yanlış adres eklediysen bağlantıyı değiştirebilirsin:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote set-url origin yeni-adres
git remote remove origin
</code></pre></div></div>

<h2 id="fetch-pull-ve-push-farkı">Fetch, pull ve push farkı</h2>

<p>Bu üç komut benzer görünse de aynı işi yapmaz:</p>

<table>
  <thead>
    <tr>
      <th>Komut</th>
      <th>Yön</th>
      <th>Etkisi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git fetch</code></td>
      <td>Uzak → Yerel metadata</td>
      <td>Değişiklikleri getirir, çalışma dalını birleştirmez</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git pull</code></td>
      <td>Uzak → Yerel dal</td>
      <td>Fetch yapar, ardından birleştirir veya rebase uygular</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git push</code></td>
      <td>Yerel → Uzak</td>
      <td>Yerel commit’leri sunucuya gönderir</td>
    </tr>
  </tbody>
</table>

<p>Özellikle ekip çalışmalarında önce <code class="language-plaintext highlighter-rouge">git fetch</code> çalıştırıp farkları incelemek daha kontrollü olabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin
git log <span class="nt">--oneline</span> main..origin/main
git pull <span class="nt">--rebase</span> origin main
git push origin main
</code></pre></div></div>

<p>Bu akış, uzaktaki commit’leri görmeni, değişiklikleri doğrusal bir geçmişle bütünleştirmeni ve ardından kendi commit’lerini paylaşmanı sağlar. Kısacası <code class="language-plaintext highlighter-rouge">clone</code> projeye giriş kapısı, <code class="language-plaintext highlighter-rouge">remote</code> adres defteri, <code class="language-plaintext highlighter-rouge">fetch</code> haberci, <code class="language-plaintext highlighter-rouge">pull</code> teslimatçı ve <code class="language-plaintext highlighter-rouge">push</code> ise kodunu buluta taşıyan kurye gibidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Git" /><category term="GitHub" /><category term="Versiyon Kontrolü" /><summary type="html"><![CDATA[Bir projeyi yalnızca kendi bilgisayarında tutmak, bütün yumurtaları aynı sepete koymaya benzer. Git’in uzak depo mekanizması sayesinde kodlar GitHub, GitLab veya Bitbucket gibi servislerde saklanabilir; ekip üyeleri aynı proje üzerinde çalışabilir ve yerel değişiklikler dış dünyayla paylaşılabilir. Bu süreçte clone, remote, fetch, pull ve push komutları başrolü üstlenir.]]></summary></entry><entry><title type="html">GitHub’sız da Olur: GitLab, Gitea ve Kendi Git Sunucunu Kurma Rehberi</title><link href="https://sonsuzus.github.io/posts/githubsiz-da-olur-gitlab-gitea-ve-kendi-git-sunucunu-kurma-rehberi/" rel="alternate" type="text/html" title="GitHub’sız da Olur: GitLab, Gitea ve Kendi Git Sunucunu Kurma Rehberi" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/githubsiz-da-olur-gitlab-gitea-ve-kendi-git-sunucunu-kurma-rehberi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/githubsiz-da-olur-gitlab-gitea-ve-kendi-git-sunucunu-kurma-rehberi/"><![CDATA[<p>GitHub, açık kaynak dünyasının kalabalık meydanı olabilir; ancak bütün kodlarımızı tek bir ekosisteme emanet etmek zorunda değiliz. Gizlilik, maliyet, kurum politikaları, çevrim dışı çalışma veya eğitim ihtiyaçları nedeniyle kendi Git platformumuzu barındırabiliriz. GitLab ve Gitea gibi çözümler, sıradan bir bulut sunucusunu bağımsız bir yazılım geliştirme merkezine dönüştürür.</p>

<p>``</p>

<h2 id="neden-kendi-git-sunucumuz">Neden kendi Git sunucumuz?</h2>

<p>Git dağıtık bir sürüm kontrol sistemidir. Her geliştiricinin bilgisayarındaki depo, projenin geçmişini taşıyan bağımsız bir kopyadır. GitHub, GitLab veya Gitea ise bu depoların paylaşılmasını kolaylaştıran web tabanlı bir <strong>forge</strong>, yani yazılım geliştirme platformudur.</p>

<p>Kendi platformunu barındırmak veri üzerindeki kontrolü artırır fakat bakım sorumluluğunu da bize verir. Basit bir değerlendirme modeli şöyle kurulabilir:</p>

\[T = K + B + G + Y\]

<p>Burada $T$ toplam sahip olma maliyetini, $K$ sunucu maliyetini, $B$ bakım emeğini, $G$ güvenlik çalışmalarını ve $Y$ yedekleme giderlerini temsil eder. Ücretsiz yazılım, sıfır maliyetli sistem demek değildir; sadece faturanın şekli değişir.</p>

<h2 id="platformların-karşılaştırılması">Platformların karşılaştırılması</h2>

<table>
  <thead>
    <tr>
      <th>Platform</th>
      <th style="text-align: right">Kaynak ihtiyacı</th>
      <th>Güçlü yanı</th>
      <th>Uygun senaryo</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>GitLab Community Edition</td>
      <td style="text-align: right">Yüksek</td>
      <td>CI/CD, kayıt sistemi ve kapsamlı DevOps araçları</td>
      <td>Şirketler ve büyük ekipler</td>
    </tr>
    <tr>
      <td>Gitea</td>
      <td style="text-align: right">Düşük</td>
      <td>Hafif, hızlı ve kolay kurulum</td>
      <td>Kişisel sunucu ve küçük ekipler</td>
    </tr>
    <tr>
      <td>Forgejo</td>
      <td style="text-align: right">Düşük</td>
      <td>Topluluk odaklı Gitea alternatifi</td>
      <td>Bağımsız açık kaynak toplulukları</td>
    </tr>
    <tr>
      <td>GitLab Education</td>
      <td style="text-align: right">Orta/Yüksek</td>
      <td>Gruplar, ödev depoları ve CI ile otomatik test</td>
      <td>Dersler ve laboratuvarlar</td>
    </tr>
  </tbody>
</table>

<p>GitLab, İsviçre çakısı gibidir: CI/CD, paket deposu, sorun takibi ve güvenlik taraması tek pakette gelir. Gitea ise cebinizdeki sağlam çakıdır; daha az kaynak tüketir ve temel işleri hızla tamamlar. Eğitim ortamında Gitea’ya Woodpecker CI eklenebilir veya GitLab CI kullanılarak her öğrenci gönderimi otomatik test edilebilir.</p>

<h2 id="docker-compose-ile-gitea-kurulumu">Docker Compose ile Gitea kurulumu</h2>

<p>En az 2 GB RAM bulunan güncel bir Linux sunucu başlangıç için yeterlidir. DNS üzerinde <code class="language-plaintext highlighter-rouge">git.ornek.com</code> adresini sunucunun IP adresine yönlendirdikten sonra aşağıdaki <code class="language-plaintext highlighter-rouge">compose.yaml</code> dosyası hazırlanabilir:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">services</span><span class="pi">:</span>
  <span class="na">gitea</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">gitea/gitea:latest</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">always</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">3000:3000</span>
      <span class="pi">-</span> <span class="s">2222:22</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./gitea-data:/data</span>
</code></pre></div></div>

<p>Bu yapı, web arayüzünü 3000 ve Git SSH bağlantısını 2222 numaralı portta açar. Veriler <code class="language-plaintext highlighter-rouge">gitea-data</code> klasöründe kalıcı tutulur. Sistemi başlatmak için:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker compose up <span class="nt">-d</span>
docker compose logs <span class="nt">-f</span> gitea
</code></pre></div></div>

<p>İlk komut konteyneri arka planda çalıştırır; ikincisi kurulum günlüklerini gösterir. Ardından tarayıcıdan <code class="language-plaintext highlighter-rouge">http://sunucu-ip:3000</code> adresine gidilerek yönetici hesabı oluşturulur. Gerçek kullanımda Nginx veya Caddy ile ters vekil kurulmalı ve HTTPS etkinleştirilmelidir.</p>

<h2 id="güvenlik-ve-yedekleme">Güvenlik ve yedekleme</h2>

<p>Bağımsızlık, “kur ve unut” anlamına gelmez. Yönetici hesabında iki faktörlü kimlik doğrulama kullanılmalı, kayıt özelliği gerekmedikçe kapatılmalı ve SSH erişimi anahtarlarla sınırlandırılmalıdır. Güncellemeler önce test ortamında denenmelidir.</p>

<p>Kullanılabilirlik yaklaşık olarak şu oranla ölçülebilir:</p>

\[A = \frac{\text{çalışma süresi}}{\text{toplam süre}} \times 100\]

<p>Yüzde 99 kullanılabilirlik iyi görünse de yılda yaklaşık 3,65 gün kesinti anlamına gelir. Bu nedenle veritabanı, depo dosyaları ve yapılandırmalar düzenli olarak farklı bir konuma yedeklenmelidir. Ayrıca geri yükleme işlemi denenmeyen yedek, Schrödinger’in yedeğidir: ihtiyaç anına kadar çalışıp çalışmadığı bilinmez.</p>

<p>Sonuç olarak kapsamlı DevOps süreçleri için GitLab, düşük kaynak tüketimi için Gitea veya Forgejo mantıklı seçimlerdir. Eğitim kurumları ise otomatik test, grup yönetimi ve sınıf şablonlarını merkeze almalıdır. Küçük bir sunucuyla başlayan bu yolculuk, kodun ve geliştirme kültürünün gerçekten size ait olduğu bağımsız bir ekosisteme dönüşebilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="git" /><category term="self-hosted" /><category term="devops" /><summary type="html"><![CDATA[GitHub, açık kaynak dünyasının kalabalık meydanı olabilir; ancak bütün kodlarımızı tek bir ekosisteme emanet etmek zorunda değiliz. Gizlilik, maliyet, kurum politikaları, çevrim dışı çalışma veya eğitim ihtiyaçları nedeniyle kendi Git platformumuzu barındırabiliriz. GitLab ve Gitea gibi çözümler, sıradan bir bulut sunucusunu bağımsız bir yazılım geliştirme merkezine dönüştürür.]]></summary></entry><entry><title type="html">Jenerikler ile Tek Kod, Birçok Tip: Esnek ve Tekrarsız Programlama</title><link href="https://sonsuzus.github.io/posts/jenerikler-ile-tek-kod-bircok-tip-esnek-ve-tekrarsiz-programlama/" rel="alternate" type="text/html" title="Jenerikler ile Tek Kod, Birçok Tip: Esnek ve Tekrarsız Programlama" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/jenerikler-ile-tek-kod-bircok-tip-esnek-ve-tekrarsiz-programlama</id><content type="html" xml:base="https://sonsuzus.github.io/posts/jenerikler-ile-tek-kod-bircok-tip-esnek-ve-tekrarsiz-programlama/"><![CDATA[<p>Aynı işlemi <code class="language-plaintext highlighter-rouge">Int</code>, <code class="language-plaintext highlighter-rouge">String</code> ve özel veri tipleri için ayrı ayrı yazdığınızı düşünün. Kod çalışır; fakat proje büyüdükçe kopyalanmış fonksiyonlar küçük bir klon ordusuna dönüşür. Jenerikler (Generics), fonksiyonları, yapıları ve enum’ları belirli bir tipe kilitlemeden tanımlamamızı sağlar. Böylece tip güvenliğinden vazgeçmeden daha esnek, yeniden kullanılabilir ve bakımı kolay kod üretiriz.</p>

<p>``</p>

<h2 id="jeneriklerin-temel-mantığı">Jeneriklerin Temel Mantığı</h2>

<p>Jenerik programlamada somut bir tip yerine <strong>tip parametresi</strong> kullanılır. Genellikle <code class="language-plaintext highlighter-rouge">T</code>, <code class="language-plaintext highlighter-rouge">U</code>, <code class="language-plaintext highlighter-rouge">Element</code> veya <code class="language-plaintext highlighter-rouge">Value</code> gibi isimlerle gösterilen bu parametre, kod kullanılırken gerçek bir tipe dönüşür.</p>

<p>Örneğin iki değerin yerini değiştiren işlemi her veri tipi için ayrı yazmak gereksizdir. Swift ile jenerik sürümü şöyle tanımlanabilir:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="n">yerDegistir</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">_</span> <span class="nv">ilk</span><span class="p">:</span> <span class="k">inout</span> <span class="kt">T</span><span class="p">,</span> <span class="n">_</span> <span class="nv">ikinci</span><span class="p">:</span> <span class="k">inout</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">gecici</span> <span class="o">=</span> <span class="n">ilk</span>
    <span class="n">ilk</span> <span class="o">=</span> <span class="n">ikinci</span>
    <span class="n">ikinci</span> <span class="o">=</span> <span class="n">gecici</span>
<span class="p">}</span>

<span class="k">var</span> <span class="nv">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">var</span> <span class="nv">y</span> <span class="o">=</span> <span class="mi">20</span>
<span class="nf">yerDegistir</span><span class="p">(</span><span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">)</span>

<span class="k">var</span> <span class="nv">ad1</span> <span class="o">=</span> <span class="s">"Ada"</span>
<span class="k">var</span> <span class="nv">ad2</span> <span class="o">=</span> <span class="s">"Linus"</span>
<span class="nf">yerDegistir</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ad1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ad2</span><span class="p">)</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">T</code>, çağrı sırasında Swift tarafından belirlenir. İlk çağrıda <code class="language-plaintext highlighter-rouge">Int</code>, ikinci çağrıda <code class="language-plaintext highlighter-rouge">String</code> olur. Fonksiyonun gövdesi ise yalnızca bir kez yazılmıştır.</p>

<p>Kod tekrarının yaklaşık maliyetini $C_{tekrar} = n \times m$ şeklinde düşünebiliriz. Burada $n$ desteklenen tip sayısı, $m$ ise her uygulamanın bakım maliyetidir. Jenerik yaklaşımda bu maliyet ideal olarak $C_{jenerik} \approx m$ seviyesine iner.</p>

<h2 id="jenerik-ve-geleneksel-yaklaşım">Jenerik ve Geleneksel Yaklaşım</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Tipe Özel Kod</th>
      <th>Jenerik Kod</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kod tekrarı</td>
      <td>Yüksek</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>Tip güvenliği</td>
      <td>Var</td>
      <td>Var</td>
    </tr>
    <tr>
      <td>Yeniden kullanım</td>
      <td>Sınırlı</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td>Bakım kolaylığı</td>
      <td>Tip sayısıyla azalır</td>
      <td>Merkezi yapı sayesinde artar</td>
    </tr>
    <tr>
      <td>İlk okuma kolaylığı</td>
      <td>Daha basit</td>
      <td>Biraz soyutlama bilgisi ister</td>
    </tr>
  </tbody>
</table>

<p>Jenerikler, <code class="language-plaintext highlighter-rouge">Any</code> kullanmakla aynı şey değildir. <code class="language-plaintext highlighter-rouge">Any</code>, farklı tipleri kabul ederken tip hakkındaki bilgiyi büyük ölçüde çalışma zamanına bırakır. Jenerikler ise derleme zamanında gerçek tipi korur. Bu nedenle yanlış tip kullanımları program çalışmadan yakalanabilir.</p>

<h2 id="jenerik-yapılar">Jenerik Yapılar</h2>

<p>Bir yığın veri yapısı yalnızca sayılarla çalışmak zorunda değildir. Kitaplar, kullanıcılar veya uzay gemileri de aynı yığına eklenebilir; tabii aynı örnek içinde eleman tipi tutarlı olmak şartıyla.</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">Yigin</span><span class="o">&lt;</span><span class="kt">Element</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="kd">private</span> <span class="k">var</span> <span class="nv">elemanlar</span><span class="p">:</span> <span class="p">[</span><span class="kt">Element</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">mutating</span> <span class="kd">func</span> <span class="nf">ekle</span><span class="p">(</span><span class="n">_</span> <span class="nv">eleman</span><span class="p">:</span> <span class="kt">Element</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">elemanlar</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">eleman</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="k">mutating</span> <span class="kd">func</span> <span class="nf">cikar</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">Element</span><span class="p">?</span> <span class="p">{</span>
        <span class="n">elemanlar</span><span class="o">.</span><span class="nf">popLast</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">var</span> <span class="nv">sayilar</span> <span class="o">=</span> <span class="kt">Yigin</span><span class="o">&lt;</span><span class="kt">Int</span><span class="o">&gt;</span><span class="p">()</span>
<span class="n">sayilar</span><span class="o">.</span><span class="nf">ekle</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
<span class="n">sayilar</span><span class="o">.</span><span class="nf">ekle</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>

<span class="k">var</span> <span class="nv">diller</span> <span class="o">=</span> <span class="kt">Yigin</span><span class="o">&lt;</span><span class="kt">String</span><span class="o">&gt;</span><span class="p">()</span>
<span class="n">diller</span><span class="o">.</span><span class="nf">ekle</span><span class="p">(</span><span class="s">"Swift"</span><span class="p">)</span>
<span class="n">diller</span><span class="o">.</span><span class="nf">ekle</span><span class="p">(</span><span class="s">"Rust"</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Element</code>, yığının saklayacağı tipi temsil eder. Aynı yapı tanımıyla sınırsız sayıda tip için güvenli yığınlar oluşturulabilir.</p>

<h2 id="enumlarda-jenerik-gücü">Enum’larda Jenerik Gücü</h2>

<p>Ağ işlemlerinde başarı durumunda veri, başarısızlık durumunda hata taşımak yaygın bir ihtiyaçtır. Jenerik enum bu iki değerin tipini dışarıdan alabilir:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">enum</span> <span class="kt">APIResult</span><span class="o">&lt;</span><span class="kt">Success</span><span class="p">,</span> <span class="kt">Failure</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="k">case</span> <span class="nf">success</span><span class="p">(</span><span class="kt">Success</span><span class="p">)</span>
    <span class="k">case</span> <span class="nf">failure</span><span class="p">(</span><span class="kt">Failure</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">struct</span> <span class="kt">User</span> <span class="p">{</span>
    <span class="k">let</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">Int</span>
    <span class="k">let</span> <span class="nv">name</span><span class="p">:</span> <span class="kt">String</span>
<span class="p">}</span>

<span class="kd">enum</span> <span class="kt">NetworkError</span> <span class="p">{</span>
    <span class="k">case</span> <span class="n">timeout</span>
    <span class="k">case</span> <span class="n">unauthorized</span>
<span class="p">}</span>

<span class="k">let</span> <span class="nv">result</span><span class="p">:</span> <span class="kt">APIResult</span><span class="o">&lt;</span><span class="kt">User</span><span class="p">,</span> <span class="kt">NetworkError</span><span class="o">&gt;</span> <span class="o">=</span>
    <span class="o">.</span><span class="nf">success</span><span class="p">(</span><span class="kt">User</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nv">name</span><span class="p">:</span> <span class="s">"Grace"</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu model, başarılı sonucun <code class="language-plaintext highlighter-rouge">User</code>, hatanın ise <code class="language-plaintext highlighter-rouge">NetworkError</code> olduğunu açıkça belirtir. Böylece belirsiz sözlükler veya zorunlu tip dönüşümleri ortadan kalkar.</p>

<h2 id="tip-kısıtlamaları">Tip Kısıtlamaları</h2>

<p>Her jenerik işlem bütün tiplerle çalışamaz. Örneğin iki değerin eşitliğini kontrol etmek için tipin <code class="language-plaintext highlighter-rouge">Equatable</code> protokolüne uyması gerekir:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="n">ayniMi</span><span class="o">&lt;</span><span class="kt">T</span><span class="p">:</span> <span class="kt">Equatable</span><span class="o">&gt;</span><span class="p">(</span><span class="n">_</span> <span class="nv">sol</span><span class="p">:</span> <span class="kt">T</span><span class="p">,</span> <span class="n">_</span> <span class="nv">sag</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Bool</span> <span class="p">{</span>
    <span class="n">sol</span> <span class="o">==</span> <span class="n">sag</span>
<span class="p">}</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">ayniMi</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">ayniMi</span><span class="p">(</span><span class="s">"Swift"</span><span class="p">,</span> <span class="s">"Kotlin"</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">T: Equatable</code> ifadesi, “Herhangi bir tip olabilir ama eşitlik karşılaştırmasını desteklemeli” demektir. Kısıtlamalar jenerikleri daraltmaz; aksine hangi yeteneklere güvenilebileceğini açıkça tanımlar.</p>

<p>Jenerikler doğru kullanıldığında kod tabanını küçültür, hataları derleme aşamasına taşır ve soyutlamaları güçlendirir. Ancak yalnızca bir yerde kullanılacak basit kodu gereksiz yere jenerikleştirmek okunabilirliği azaltabilir. Altın kural şudur: Aynı davranış birden fazla tip için gerçekten anlamlıysa jenerikler sahneye çıkmalı; aksi hâlde soyutlama pelerinini dolapta bırakmalıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="generics" /><category term="swift" /><category term="temiz kod" /><summary type="html"><![CDATA[Aynı işlemi Int, String ve özel veri tipleri için ayrı ayrı yazdığınızı düşünün. Kod çalışır; fakat proje büyüdükçe kopyalanmış fonksiyonlar küçük bir klon ordusuna dönüşür. Jenerikler (Generics), fonksiyonları, yapıları ve enum’ları belirli bir tipe kilitlemeden tanımlamamızı sağlar. Böylece tip güvenliğinden vazgeçmeden daha esnek, yeniden kullanılabilir ve bakımı kolay kod üretiriz.]]></summary></entry><entry><title type="html">Kapanışlar ve İteratörler: Veriyi Fonksiyonel Bir Akışa Dönüştürmek</title><link href="https://sonsuzus.github.io/posts/kapanislar-ve-iteratorler-veriyi-fonksiyonel-bir-akisa-donusturmek/" rel="alternate" type="text/html" title="Kapanışlar ve İteratörler: Veriyi Fonksiyonel Bir Akışa Dönüştürmek" /><published>2026-08-03T00:00:00+00:00</published><updated>2026-08-03T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/kapanislar-ve-iteratorler-veriyi-fonksiyonel-bir-akisa-donusturmek</id><content type="html" xml:base="https://sonsuzus.github.io/posts/kapanislar-ve-iteratorler-veriyi-fonksiyonel-bir-akisa-donusturmek/"><![CDATA[<p>Kapanışlar (closures) ve iteratörler, veriyi “nasıl dolaşacağımızı” adım adım anlatmak yerine “hangi dönüşümleri istediğimizi” ifade etmemizi sağlar. Kapanışlar çevrelerindeki değişkenleri hatırlayan isimsiz fonksiyonlardır; iteratörler ise koleksiyon elemanlarını sırayla üreten soyutlamalardır. Birlikte kullanıldıklarında kısa, okunabilir ve yeniden kullanılabilir veri işleme zincirleri ortaya çıkar.</p>

<p>``</p>

<h2 id="kapanış-neden-sıradan-bir-fonksiyondan-farklıdır">Kapanış neden sıradan bir fonksiyondan farklıdır?</h2>

<p>Normal bir fonksiyon çoğunlukla yalnızca parametrelerine ve erişebildiği genel değerlere bağlıdır. Kapanış ise tanımlandığı kapsamın değişkenlerini <strong>yakalayabilir</strong>. Matematiksel açıdan sıradan bir fonksiyonu</p>

\[f(x)=x^2\]

<p>şeklinde düşünürsek, dışarıdaki $a$ değerini yakalayan kapanış şu aileyi temsil eder:</p>

\[f_a(x)=ax^2\]

<p>Burada $a$, açıkça parametre olarak verilmemesine rağmen hesaplamanın parçasıdır. Kapanışın yanında taşıdığı bu çevresel bilgilere bazen <strong>closure environment</strong> denir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Normal fonksiyon</th>
      <th>Kapanış</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>İsme ihtiyaç duyar mı?</td>
      <td>Genellikle evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Dış değişken yakalar mı?</td>
      <td>Genellikle hayır</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Kısa işlemlerde kullanım</td>
      <td>Daha törensel</td>
      <td>Oldukça pratik</td>
    </tr>
    <tr>
      <td>Durum taşıyabilir mi?</td>
      <td>Ek yapı gerekir</td>
      <td>Yakalanan değerlerle taşıyabilir</td>
    </tr>
  </tbody>
</table>

<p>Rust’ta bir kapanış çevresindeki değeri referansla ödünç alabilir, değiştirilebilir biçimde ödünç alabilir veya sahipliğini üstlenebilir. Derleyici buna göre kapanışı <code class="language-plaintext highlighter-rouge">Fn</code>, <code class="language-plaintext highlighter-rouge">FnMut</code> ya da <code class="language-plaintext highlighter-rouge">FnOnce</code> davranışlarından biriyle ilişkilendirir.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">katsayi</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
    <span class="k">let</span> <span class="n">carp</span> <span class="o">=</span> <span class="p">|</span><span class="n">sayi</span><span class="p">:</span> <span class="nb">i32</span><span class="p">|</span> <span class="n">sayi</span> <span class="o">*</span> <span class="n">katsayi</span><span class="p">;</span>

    <span class="nd">println!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="nf">carp</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span> <span class="c1">// 15</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">carp</code>, <code class="language-plaintext highlighter-rouge">katsayi</code> değişkenini çevresinden yakalar. Böylece her çağrıda katsayıyı ayrıca göndermemiz gerekmez.</p>

<h2 id="i̇teratör-koleksiyon-değil-üretim-süreci">İteratör: Koleksiyon değil, üretim süreci</h2>

<p>İteratör bir koleksiyonun kendisi değildir; sıradaki elemanın nasıl elde edileceğini tanımlayan bir mekanizmadır. Temel fikir, her adımda ya yeni bir değer ya da akışın bittiğini bildiren sonuç üretmektir.</p>

<p>$n$ elemanlı bir koleksiyon tek kez dolaşılıyorsa zaman karmaşıklığı çoğunlukla</p>

\[T(n)=O(n)\]

<p>olur. <code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">filter</code> ve <code class="language-plaintext highlighter-rouge">take</code> gibi işlemlerin zincirlenmesi mutlaka her aşamada yeni bir koleksiyon oluşturmaz. Birçok dilde, özellikle Rust’ta, iteratörler <strong>tembeldir</strong>: Sonuç tüketilene kadar hesaplama başlamaz.</p>

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th>Görevi</th>
      <th>Sonuç türü</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">map</code></td>
      <td>Her elemanı dönüştürür</td>
      <td>Yeni iteratör</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">filter</code></td>
      <td>Koşula uyanları geçirir</td>
      <td>Yeni iteratör</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">take</code></td>
      <td>İlk belirli sayıda değeri alır</td>
      <td>Sınırlı iteratör</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">fold</code></td>
      <td>Değerleri tek sonuçta birleştirir</td>
      <td>Tek değer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">collect</code></td>
      <td>Akışı koleksiyona dönüştürür</td>
      <td>Koleksiyon</td>
    </tr>
  </tbody>
</table>

<h2 id="i̇kisini-birlikte-kullanalım">İkisini birlikte kullanalım</h2>

<p>Aşağıdaki örnek çift sayıları seçer, dışarıdan yakalanan katsayıyla çarpar ve sonuçları toplar:</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">sayilar</span> <span class="o">=</span> <span class="nd">vec!</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">];</span>
    <span class="k">let</span> <span class="n">katsayi</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>

    <span class="k">let</span> <span class="n">toplam</span><span class="p">:</span> <span class="nb">i32</span> <span class="o">=</span> <span class="n">sayilar</span>
        <span class="nf">.iter</span><span class="p">()</span>
        <span class="nf">.filter</span><span class="p">(|</span><span class="n">sayi</span><span class="p">|</span> <span class="o">*</span><span class="n">sayi</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
        <span class="nf">.map</span><span class="p">(|</span><span class="n">sayi</span><span class="p">|</span> <span class="n">sayi</span> <span class="o">*</span> <span class="n">katsayi</span><span class="p">)</span>
        <span class="nf">.sum</span><span class="p">();</span>

    <span class="nd">println!</span><span class="p">(</span><span class="s">"Toplam: {}"</span><span class="p">,</span> <span class="n">toplam</span><span class="p">);</span> <span class="c1">// 120</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">filter</code> içindeki kapanış yalnızca çift değerleri geçirir. <code class="language-plaintext highlighter-rouge">map</code> kapanışı ise <code class="language-plaintext highlighter-rouge">katsayi</code> değişkenini yakalayarak değerleri dönüştürür. <code class="language-plaintext highlighter-rouge">sum</code>, tembel zinciri tüketen <strong>terminal işlem</strong> olduğu için gerçek hesaplama bu noktada gerçekleşir.</p>

<p>Aynı yaklaşım klasik bir döngüyle de yazılabilir; ancak iteratör zinciri “indeksi artır, elemana eriş, sonucu geçici değişkende tut” ayrıntılarını gizler. Böylece kod, mekanizmadan çok niyeti anlatır.</p>

<h2 id="ne-zaman-dikkatli-olmalıyız">Ne zaman dikkatli olmalıyız?</h2>

<p>Uzun ve iç içe kapanış zincirleri okunabilirliği azaltabilir. Yan etkiler, karmaşık hata yönetimi veya çok sayıda koşul varsa işlemleri isimlendirilmiş fonksiyonlara ayırmak daha sağlıklıdır. Ayrıca sahiplik kullanan dillerde <code class="language-plaintext highlighter-rouge">move</code> ile yakalanan bir değerin artık önceki kapsamda kullanılamayabileceği unutulmamalıdır.</p>

<p>Özetle kapanışlar davranışı veri gibi taşır, iteratörler ise veriyi kontrollü bir akışa dönüştürür. Birlikte kullanıldıklarında döngü yazmaktan fazlasını yaparız: Dönüşümleri birbirine bağlayan küçük ve güçlü bir işlem hattı kurarız.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="closures" /><category term="iteratörler" /><category term="fonksiyonel programlama" /><summary type="html"><![CDATA[Kapanışlar (closures) ve iteratörler, veriyi “nasıl dolaşacağımızı” adım adım anlatmak yerine “hangi dönüşümleri istediğimizi” ifade etmemizi sağlar. Kapanışlar çevrelerindeki değişkenleri hatırlayan isimsiz fonksiyonlardır; iteratörler ise koleksiyon elemanlarını sırayla üreten soyutlamalardır. Birlikte kullanıldıklarında kısa, okunabilir ve yeniden kullanılabilir veri işleme zincirleri ortaya çıkar.]]></summary></entry></feed>