<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Git on kenji.blog</title><link>http://kenji.blog/id/categories/git/</link><description>Recent content in Git on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/categories/git/index.xml" rel="self" type="application/rss+xml"/><item><title>【Perintah Git】Perbedaan antara rebase dan merge, serta penggunaan yang tepat dalam praktik</title><link>http://kenji.blog/id/p/git-rebase-vs-merge-practical-guide/</link><pubDate>Sun, 13 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/git-rebase-vs-merge-practical-guide/</guid><description>&lt;img src="http://kenji.blog/p/git-rebase-vs-merge-practical-guide/img/eyecatch.jpg" alt="Featured image of post 【Perintah Git】Perbedaan antara rebase dan merge, serta penggunaan yang tepat dalam praktik" />&lt;h1 id="1-pendahuluan-mengapa-merge-atau-rebase-menjadi-perdebatan-abadi">1. Pendahuluan: Mengapa &amp;ldquo;merge atau rebase&amp;rdquo; menjadi perdebatan abadi
&lt;/h1>&lt;p>Git adalah sistem pengontrol versi yang sangat penting dalam pengembangan perangkat lunak modern. Saat beberapa pengembang mengubah basis kode secara bersamaan, model cabang (branching) Git yang kuat akan sangat berguna. Namun, dalam pengembangan tim, perdebatan tentang &amp;ldquo;apakah harus menggunakan merge atau rebase&amp;rdquo; merupakan salah satu topik yang selalu membingungkan pengembang, mulai dari pemula hingga ahli.&lt;/p>
&lt;p>Artikel ini akan mengupas perbedaan mekanisme antara &lt;code>git merge&lt;/code> dan &lt;code>git rebase&lt;/code> secara mendalam, mulai dari struktur internal Git yaitu DAG (Directed Acyclic Graph) dan sifat matematis dari hash komit. Selain itu, artikel ini juga akan menjelaskan secara menyeluruh bagaimana cara menggunakan keduanya secara tepat dalam praktik, disertai dengan alur kerja (workflow) yang konkret. Dengan memahami tidak hanya sekadar pengenalan perintah, tetapi juga perhitungan apa yang dilakukan Git di balik layar, Anda akan menghilangkan ketakutan terhadap konflik dan mampu membangun riwayat yang bersih serta mudah dilacak.&lt;/p>
&lt;hr>
&lt;h1 id="2-struktur-internal-git-hash-komit-dan-model-objek">2. Struktur Internal Git: Hash Komit dan Model Objek
&lt;/h1>&lt;p>Untuk memahami bagaimana Git mengintegrasikan riwayat, pertama-tama kita perlu mengetahui bagaimana Git menyimpan data. Git tidak sekadar menyimpan perbedaan (patch) dari perubahan file, melainkan menyimpan cuplikan (snapshot) dari seluruh sistem file pada suatu titik waktu.&lt;/p>
&lt;h2 id="21-sifat-kriptografi-dari-hash-komit">2.1 Sifat Kriptografi dari Hash Komit
&lt;/h2>&lt;p>Setiap komit Git diidentifikasi secara unik dengan 40 digit heksadesimal yang dihasilkan oleh fungsi hash SHA-1 (Secure Hash Algorithm 1) berdasarkan isinya. Objek komit terdiri dari elemen-elemen berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Pointer ke objek Tree&lt;/strong>: Cuplikan struktur direktori dan file (Blob) pada saat itu.&lt;/li>
&lt;li>&lt;strong>Pointer ke komit induk (parent)&lt;/strong>: Nilai hash dari satu atau lebih komit induk (komit pertama tidak memiliki induk, sedangkan komit merge memiliki dua induk atau lebih).&lt;/li>
&lt;li>&lt;strong>Informasi pembuat (Author)&lt;/strong>: Orang yang menulis kode beserta tanggal dan waktunya.&lt;/li>
&lt;li>&lt;strong>Informasi committer (Committer)&lt;/strong>: Orang yang membuat/menerapkan komit beserta tanggal dan waktunya.&lt;/li>
&lt;li>&lt;strong>Pesan komit&lt;/strong>: Teks yang menjelaskan maksud perubahan.&lt;/li>
&lt;/ol>
&lt;p>Secara matematis, nilai hash $H(C)$ untuk objek komit $C$ didefinisikan sebagai berikut:&lt;/p>
$$
H(C) = \text{SHA-1}( \text{tree} \parallel \text{parent} \parallel \text{author} \parallel \text{committer} \parallel \text{message} )
$$&lt;p>Di sini, $\parallel$ merepresentasikan penggabungan data. Karena karakteristik fungsi hash, meskipun hanya mengubah satu karakter pada pesan komit, atau jika komit induknya berbeda, nilai hash yang dihasilkan akan benar-benar berbeda. Artinya, &lt;strong>komit bersifat tidak dapat diubah (Immutable)&lt;/strong>. Alasan mengapa &lt;code>rebase&lt;/code> yang akan dibahas nanti sering disebut &amp;ldquo;menulis ulang riwayat&amp;rdquo; sebenarnya adalah karena Git &amp;ldquo;membuat komit baru yang isinya mirip tetapi memiliki nilai hash yang berbeda&amp;rdquo;.&lt;/p>
&lt;p>Ukuran ruang hash adalah $2^{160}$, dan probabilitas $P$ terjadinya tabrakan (dua komit berbeda memiliki nilai hash yang sama) dapat diaproksimasi menggunakan teori Paradoks Ulang Tahun (Birthday Paradox) sebagai berikut ($n$ adalah jumlah komit):&lt;/p>
$$
P(\text{collision}) \approx 1 - \exp\left(-\frac{n^2}{2 \times 2^{160}}\right)
$$&lt;p>Probabilitas ini sangat rendah, sehingga secara praktis hampir tidak mungkin terjadi tabrakan hash komit pada Git.&lt;/p>
&lt;hr>
&lt;h1 id="3-teori-graf-dan-dag-model-matematis-riwayat-git">3. Teori Graf dan DAG: Model Matematis Riwayat Git
&lt;/h1>&lt;p>Riwayat komit Git dimodelkan sebagai &amp;ldquo;Directed Acyclic Graph (DAG)&amp;rdquo; dalam teori graf.&lt;/p>
&lt;h2 id="31-apa-itu-dag-directed-acyclic-graph">3.1 Apa itu DAG (Directed Acyclic Graph)?
&lt;/h2>&lt;p>Dalam graf $G = (V, E)$, $V$ adalah himpunan komit (simpul/vertex), dan $E$ adalah himpunan edge berarah yang menunjukkan hubungan induk-anak antar komit. Pada Git, arah edge menuju dari &amp;ldquo;komit anak ke komit induk&amp;rdquo;. Hal ini karena komit baru menyimpan pointer ke komit sebelumnya.&lt;/p>
&lt;pre class="mermaid">
graph BT
A[&amp;#34;Komit A (Awal)&amp;#34;]
B[&amp;#34;Komit B&amp;#34;]
C[&amp;#34;Komit C (Main)&amp;#34;]
D[&amp;#34;Komit D (Fitur)&amp;#34;]
E[&amp;#34;Komit E (Merge)&amp;#34;]
B --&amp;gt; A
C --&amp;gt; B
D --&amp;gt; B
E --&amp;gt; C
E --&amp;gt; D
&lt;/pre>
&lt;p>Fitur utama DAG adalah &amp;ldquo;tidak adanya siklus (putaran)&amp;rdquo;. Dengan ini, algoritma yang menelusuri riwayat komit tidak akan terjebak dalam loop tak terbatas, dan pasti akan mencapai titik akhir (komit awal).&lt;/p>
&lt;h2 id="32-topological-sort-dan-urutan-riwayat">3.2 Topological Sort dan Urutan Riwayat
&lt;/h2>&lt;p>Saat menampilkan riwayat menggunakan perintah &lt;code>git log&lt;/code>, DAG diurutkan sebagai daftar 1 dimensi menggunakan algoritma Topological Sort (Pengurutan Topologi). Untuk setiap edge berarah $u \to v$ dalam DAG ($u$ adalah anak dari $v$), daftar disusun sedemikian rupa sehingga $u$ selalu berada sebelum $v$.&lt;/p>
&lt;hr>
&lt;h1 id="4-mekanisme-dan-jenis-git-merge">4. Mekanisme dan Jenis git merge
&lt;/h1>&lt;p>Perintah paling dasar untuk mengintegrasikan perubahan pada cabang adalah &lt;code>git merge&lt;/code>. Namun, bergantung pada status saat ini, Git secara otomatis akan memilih strategi merge yang berbeda.&lt;/p>
&lt;h2 id="41-merge-fast-forward---ff">4.1 Merge Fast-Forward (&amp;ndash;ff)
&lt;/h2>&lt;p>Jika cabang tujuan integrasi (misalnya: &lt;code>main&lt;/code>) adalah leluhur langsung dari cabang sumber integrasi (misalnya: &lt;code>feature&lt;/code>), Git akan menjalankan merge &amp;ldquo;Fast-Forward&amp;rdquo;. Ini adalah operasi yang tidak membuat komit baru, melainkan hanya memajukan pointer cabang ke depan.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;A&amp;#34;
commit id: &amp;#34;B&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;C&amp;#34;
commit id: &amp;#34;D&amp;#34;
checkout main
merge feature
&lt;/pre>
&lt;p>Merge Fast-Forward menjaga riwayat tetap dalam satu garis lurus, namun memiliki kelemahan yaitu hilangnya konteks &amp;ldquo;kelompok komit mana yang digabungkan sebagai satu pengembangan fitur (feature)&amp;rdquo;.&lt;/p>
&lt;h2 id="42-merge-non-fast-forward---no-ff">4.2 Merge Non-Fast-Forward (&amp;ndash;no-ff)
&lt;/h2>&lt;p>Jika Anda secara eksplisit menentukan &lt;code>git merge --no-ff&lt;/code>, Git akan selalu membuat &amp;ldquo;komit merge&amp;rdquo; baru meskipun situasi tersebut memungkinkan Fast-Forward. Komit merge adalah komit khusus yang memiliki dua induk.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;A&amp;#34;
commit id: &amp;#34;B&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;C&amp;#34;
commit id: &amp;#34;D&amp;#34;
checkout main
commit id: &amp;#34;Main Work 1&amp;#34;
merge feature type: NORMAL
&lt;/pre>
&lt;p>Keuntungan dari metode ini adalah bahwa keberadaan dan riwayat cabang fitur tetap terekam dengan jelas pada DAG. Saat terjadi masalah, Anda dapat membatalkan (revert) seluruh fitur sekaligus dengan aman dengan menjalankan &lt;code>git revert -m 1 &amp;lt;hash komit merge&amp;gt;&lt;/code>.&lt;/p>
&lt;h2 id="43-algoritma-3-way-merge">4.3 Algoritma 3-Way Merge
&lt;/h2>&lt;p>Ketika cabang tujuan dan cabang sumber masing-masing memiliki komitnya sendiri, Git akan menjalankan 3-Way Merge (merge 3 arah). Pada saat ini, Git menelusuri DAG dan menemukan &amp;ldquo;leluhur umum (Lowest Common Ancestor, LCA)&amp;rdquo; dari kedua cabang tersebut.&lt;/p>
&lt;p>Kompleksitas perhitungan algoritma untuk menemukan LCA, $T_{\text{LCA}}$, dapat dieksekusi dalam waktu linear terhadap jumlah simpul $|V|$ dan jumlah edge $|E|$:&lt;/p>
$$
T_{\text{LCA}} = \mathcal{O}(|V| + |E|)
$$&lt;p>Git membandingkan tiga hal: &amp;ldquo;status LCA&amp;rdquo;, &amp;ldquo;status cabang saat ini&amp;rdquo;, dan &amp;ldquo;status cabang lawan&amp;rdquo;. Jika tidak ada konflik perubahan, Git secara otomatis akan menghasilkan komit merge.&lt;/p>
&lt;hr>
&lt;h1 id="5-mekanisme-git-rebase-dan-rekonstruksi-riwayat">5. Mekanisme git rebase dan Rekonstruksi Riwayat
&lt;/h1>&lt;p>Jika &lt;code>git merge&lt;/code> &amp;ldquo;mengintegrasikan&amp;rdquo; riwayat, maka &lt;code>git rebase&lt;/code> &amp;ldquo;merekonstruksi (memindahkan)&amp;rdquo; riwayat.&lt;/p>
&lt;h2 id="51-pergerakan-di-balik-rebase">5.1 Pergerakan di Balik Rebase
&lt;/h2>&lt;p>Operasi internal saat melakukan rebase pada cabang &lt;code>feature&lt;/code> ke cabang &lt;code>main&lt;/code> (&lt;code>git rebase main&lt;/code>) adalah sebagai berikut:&lt;/p>
&lt;ol>
&lt;li>Menemukan leluhur umum (LCA) antara cabang &lt;code>feature&lt;/code> dan cabang &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Menyimpan sementara perbedaan komit dari LCA hingga ujung cabang &lt;code>feature&lt;/code>.&lt;/li>
&lt;li>Memindahkan pointer cabang &lt;code>feature&lt;/code> ke ujung cabang &lt;code>main&lt;/code>.&lt;/li>
&lt;li>Menerapkan (Cherry-Pick) perbedaan yang disimpan tadi satu per satu secara berurutan ke atas base baru (ujung &lt;code>main&lt;/code>), dan membuat komit baru.&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Komit A&amp;#34;] --&amp;gt; B[&amp;#34;Komit B&amp;#34;]
B --&amp;gt; C[&amp;#34;Komit C (Main)&amp;#34;]
B --&amp;gt; D[&amp;#34;Komit D (Fitur Lama)&amp;#34;]
D -.-&amp;gt; E[&amp;#34;Komit D&amp;#39; (Fitur Baru)&amp;#34;]
C --&amp;gt; E
style D stroke-dasharray: 5 5, fill: #f9f9f9, color: #999
&lt;/pre>
&lt;p>Hal penting di sini adalah komit yang dihasilkan oleh rebase $D'$ memiliki &lt;strong>induk komit yang berbeda dari komit aslinya $D$, sehingga memiliki nilai hash yang benar-benar berbeda&lt;/strong> (merujuk pada definisi fungsi hash $H(C)$ yang disebutkan sebelumnya).&lt;/p>
&lt;h2 id="52-rebase-interaktif-interactive-rebase">5.2 Rebase Interaktif (Interactive Rebase)
&lt;/h2>&lt;p>Dengan menggunakan &lt;code>git rebase -i&lt;/code> (atau &lt;code>--interactive&lt;/code>), Anda dapat memanipulasi riwayat komit sesuka hati. Ini adalah alat paling ampuh untuk merapikan riwayat lokal.&lt;/p>
&lt;ul>
&lt;li>&lt;code>pick&lt;/code> : Menerima komit apa adanya&lt;/li>
&lt;li>&lt;code>reword&lt;/code> : Hanya mengubah pesan komit&lt;/li>
&lt;li>&lt;code>edit&lt;/code> : Menjeda untuk memodifikasi isi komit&lt;/li>
&lt;li>&lt;code>squash&lt;/code> : Menggabungkan komit ini dengan komit sebelumnya, dan juga menggabungkan pesannya&lt;/li>
&lt;li>&lt;code>fixup&lt;/code> : Sama seperti &lt;code>squash&lt;/code>, tetapi membuang pesan dari komit ini&lt;/li>
&lt;li>&lt;code>drop&lt;/code> : Menghapus komit sepenuhnya&lt;/li>
&lt;/ul>
&lt;p>Secara matematis, jika sebuah cabang memiliki $N$ komit, variasi (permutasi) riwayat linear $P$ yang dapat dihasilkan dengan mengubah urutan rebase adalah sebagai berikut:&lt;/p>
$$
P = N!
$$&lt;p>Git memberikan $N!$ macam kebebasan kepada pengembang, memungkinkan mereka untuk menjaga riwayat dalam kondisi yang logis dan indah.&lt;/p>
&lt;hr>
&lt;h1 id="6-aturan-emas-rebase-the-golden-rule-of-rebase">6. Aturan Emas Rebase (The Golden Rule of Rebase)
&lt;/h1>&lt;p>&lt;code>rebase&lt;/code> sangatlah kuat, namun terdapat satu aturan mutlak.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>&amp;ldquo;Jangan pernah melakukan rebase pada riwayat publik yang telah dibagikan.&amp;rdquo;&lt;/strong>
&lt;em>(Never rebase public history)&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h2 id="61-mengapa-kita-tidak-boleh-melakukan-rebase-pada-riwayat-publik">6.1 Mengapa Kita Tidak Boleh Melakukan Rebase pada Riwayat Publik?
&lt;/h2>&lt;p>Git bersifat terdistribusi. Komit yang Anda dorong (push) ke &lt;code>origin/main&lt;/code> juga di-kloning (disalin) ke repositori lokal milik pengembang lain. Jika Anda merebase komit yang sudah di-push untuk menulis ulang riwayat, dan memaksakan penimpaan dengan &lt;code>git push --force&lt;/code>, apa yang akan terjadi?&lt;/p>
&lt;p>DAG lokal milik pengembang lain dan DAG jarak jauh (remote) akan bercabang secara mendasar. Ketika pengembang lain menjalankan &lt;code>git pull&lt;/code>, Git akan mencoba memaksa penggabungan sekelompok komit yang memiliki sejarah berbeda. Hal ini akan menyebabkan banyak konflik dan komit duplikat (komit dengan perubahan yang sama tetapi hash yang berbeda), sehingga membuat repositori menjadi berantakan.&lt;/p>
&lt;p>Aturan emasnya adalah rebase &lt;strong>hanya boleh dilakukan pada &amp;ldquo;cabang lokal yang belum dibagikan kepada siapa pun&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="7-penyelesaian-konflik-dan-git-rebase---continue">7. Penyelesaian Konflik dan git rebase &amp;ndash;continue
&lt;/h1>&lt;p>Ketika beberapa orang mengubah bagian yang sama dari file yang sama, konflik akan terjadi. Proses penyelesaian konflik antara &lt;code>merge&lt;/code> dan &lt;code>rebase&lt;/code> berbeda.&lt;/p>
&lt;h2 id="71-penyelesaian-konflik-pada-merge">7.1 Penyelesaian Konflik pada Merge
&lt;/h2>&lt;p>Pada &lt;code>git merge&lt;/code>, penyelesaian konflik hanya terjadi &lt;strong>satu kali&lt;/strong>. Sesaat sebelum membuat komit merge akhir, Anda memperbaiki semua bagian yang konflik sekaligus.&lt;/p>
&lt;h2 id="72-penyelesaian-konflik-pada-rebase">7.2 Penyelesaian Konflik pada Rebase
&lt;/h2>&lt;p>Pada &lt;code>git rebase&lt;/code>, karena sifatnya yang menerapkan ulang komit satu per satu, ada kemungkinan &lt;strong>konflik terjadi pada setiap komit&lt;/strong>.&lt;/p>
&lt;p>Jika konflik terjadi selama rebase, Git akan menjeda prosesnya. Alur penyelesaiannya adalah sebagai berikut:&lt;/p>
&lt;ol>
&lt;li>Buka editor atau IDE (seperti VS Code) dan perbaiki penanda konflik (seperti &lt;code>&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code>, &lt;code>======&lt;/code>, &lt;code>&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code>) secara manual.&lt;/li>
&lt;li>Tambahkan file yang telah diperbaiki ke dalam indeks:
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git add &amp;lt;file yang diperbaiki&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>Tanpa membuat komit baru, lanjutkan proses rebase:
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git rebase --continue
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Jika Anda ingin membatalkan rebase itu sendiri dan kembali ke keadaan semula, jalankan perintah berikut:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git rebase --abort
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>（&lt;em>Jika penyelesaian konflik tidak diperlukan dan Anda ingin melewati komit tersebut, gunakan &lt;code>git rebase --skip&lt;/code>&lt;/em>)&lt;/p>
&lt;hr>
&lt;h1 id="8-penggunaan-yang-tepat-dalam-praktik-praktik-workflow">8. Penggunaan yang Tepat dalam Praktik (Praktik Workflow)
&lt;/h1>&lt;p>Lalu, bagaimana sebaiknya kita menggunakan &lt;code>merge&lt;/code> dan &lt;code>rebase&lt;/code> dalam praktik pengembangan yang sebenarnya? Di sini kita akan memperkenalkan pendekatan yang paling standar dan aman.&lt;/p>
&lt;h2 id="81-skenario-1-merapikan-riwayat-pekerjaan-lokal-menggunakan-rebase">8.1 【Skenario 1】 Merapikan Riwayat Pekerjaan Lokal (Menggunakan Rebase)
&lt;/h2>&lt;p>Misalkan saat mengembangkan di cabang fitur, banyak komit kecil menumpuk (seperti &amp;ldquo;Perbaikan typo&amp;rdquo; atau &amp;ldquo;Simpan sementara&amp;rdquo;). Sebelum membuat Pull Request (PR), gunakan rebase interaktif untuk merapikannya ke dalam unit-unit yang bermakna.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Jalankan saat berada di cabang feature&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase -i HEAD~5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (Editor akan terbuka, gunakan squash atau fixup untuk membersihkan riwayat)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan melakukan ini, Anda dapat membuat riwayat komit yang indah dan maksudnya mudah dipahami oleh pengulas (reviewer).&lt;/p>
&lt;h2 id="82-skenario-2-mengikuti-pembaruan-cabang-main-terbaru-menggunakan-rebase">8.2 【Skenario 2】 Mengikuti Pembaruan Cabang main Terbaru (Menggunakan Rebase)
&lt;/h2>&lt;p>Jika pengembangan memakan waktu lama dan perubahan dari orang lain terus menerus di-merge ke cabang &lt;code>main&lt;/code>, cabang &lt;code>feature&lt;/code> milik Anda akan menjadi usang. Dalam kasus ini, lakukan rebase cabang &lt;code>feature&lt;/code> Anda ke cabang &lt;code>main&lt;/code> terbaru agar tetap sinkron.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Dapatkan informasi terbaru dari main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git fetch origin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Pindahkan cabang feature ke atas main terbaru&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase origin/main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan cara ini, riwayat menjadi satu garis lurus dan dapat mencegah konflik pada merge selanjutnya. Selain itu, Anda juga mencegah pembuatan komit merge yang tidak perlu (seperti &amp;ldquo;Merge branch &amp;lsquo;main&amp;rsquo; into feature&amp;rdquo;).&lt;/p>
&lt;h2 id="83-skenario-3-mengintegrasikan-fitur-yang-telah-selesai-menggunakan-merge">8.3 【Skenario 3】 Mengintegrasikan Fitur yang Telah Selesai (Menggunakan Merge)
&lt;/h2>&lt;p>Pengembangan pada cabang &lt;code>feature&lt;/code> telah selesai, dan sekarang saatnya memasuki fase integrasi ke cabang &lt;code>main&lt;/code>. Di sini kita menggunakan &lt;strong>&lt;code>git merge --no-ff&lt;/code>&lt;/strong> (sama seperti memilih &amp;ldquo;Create a merge commit&amp;rdquo; di Pull Request pada GitHub, dll.).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git checkout main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git merge --no-ff feature -m &lt;span class="s2">&amp;#34;Merge feature: Implementasi fitur login pengguna&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git push origin main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan ini, sebuah titik sejarah (komit merge) yang menunjukkan &amp;ldquo;satu fitur digabungkan di sini&amp;rdquo; akan tertinggal pada DAG cabang &lt;code>main&lt;/code>. Saat Anda melihat riwayat di kemudian hari, akan lebih mudah untuk menelusuri kode berdasarkan unit fitur.&lt;/p>
&lt;hr>
&lt;h1 id="9-kesimpulan-ringkasan">9. Kesimpulan (Ringkasan)
&lt;/h1>&lt;p>Dalam pengoperasian Git, pendekatan ekstrem seperti &amp;ldquo;selesaikan semuanya dengan Merge&amp;rdquo; atau &amp;ldquo;buat semuanya lurus dengan Rebase&amp;rdquo; masing-masing memiliki kelebihan dan kekurangan.&lt;/p>
&lt;p>Praktik terbaik (best practice) dalam bekerja adalah pendekatan hibrida: &lt;strong>&amp;ldquo;Rapikan riwayat pribadi lokal dengan rebase, dan pertahankan konteks riwayat integrasi publik menggunakan merge &amp;ndash;no-ff.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Lokal (Ruang Kerja Pribadi)&lt;/strong>: Gunakan &lt;code>rebase&lt;/code> untuk membuang komit yang tidak perlu dan mengikuti mainline terbaru agar riwayat tetap lurus.&lt;/li>
&lt;li>&lt;strong>Global (Ruang Kerja Bersama)&lt;/strong>: Gunakan &lt;code>merge --no-ff&lt;/code> untuk mencatat keberadaan cabang fitur sebagai komit merge pada DAG, sehingga memudahkan revert dan pelacakan.&lt;/li>
&lt;/ul>
&lt;p>Dengan memahami latar belakang matematis dan arsitektural, seperti struktur DAG dan mekanisme fungsi hash, perintah Git akan meningkat dari sekadar hafalan menjadi &amp;ldquo;desain riwayat yang memiliki tujuan&amp;rdquo;. Sambil mematuhi aturan emas rebase, pilihlah perintah yang paling tepat sesuai situasi untuk membangun riwayat komit yang bersih, mudah dibaca, dan mudah dipelihara bagi seluruh tim.&lt;/p></description></item><item><title>Kumpulan Kesalahan Pemula Git dan Perintah Solusinya (Mengatasi Konflik, dll.)</title><link>http://kenji.blog/id/p/git-beginners-mistakes-and-solutions/</link><pubDate>Sat, 12 Sep 2026 17:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/git-beginners-mistakes-and-solutions/</guid><description>&lt;img src="http://kenji.blog/p/git-beginners-mistakes-and-solutions/img/eyecatch.jpg" alt="Featured image of post Kumpulan Kesalahan Pemula Git dan Perintah Solusinya (Mengatasi Konflik, dll.)" />&lt;h1 id="kumpulan-kesalahan-pemula-git-dan-perintah-solusinya-mengatasi-konflik-dll">Kumpulan Kesalahan Pemula Git dan Perintah Solusinya (Mengatasi Konflik, dll.)
&lt;/h1>&lt;h2 id="1-pendahuluan-mengapa-kita-melakukan-kesalahan-di-git">1. Pendahuluan: Mengapa Kita Melakukan Kesalahan di Git?
&lt;/h2>&lt;p>Dalam pengembangan perangkat lunak, Git telah menjadi hal yang sangat penting seperti udara atau air. Namun, bagi banyak pemula (dan bahkan terkadang bagi para ahli), Git bisa terasa seperti &amp;ldquo;kotak hitam ajaib yang menakutkan&amp;rdquo;. Komit yang menghilang, mendorong banyak perubahan ke cabang yang salah secara tidak sengaja, atau pesan kesalahan konflik yang belum pernah dilihat sebelumnya memenuhi layar&amp;hellip; Saat terjebak dalam &amp;ldquo;perangkap Git&amp;rdquo; ini, progres pekerjaan bisa terhenti sepenuhnya, dan dalam skenario terburuk, muncul ketakutan bahwa kode sumber mungkin akan hancur.&lt;/p>
&lt;p>Mengapa Git begitu sulit dan memicu kesalahan? Alasan utamanya adalah &amp;ldquo;kita menggunakannya dengan hanya menghafal perintah tanpa memahami apa yang terjadi di dalam Git&amp;rdquo;. Git dibangun berdasarkan filosofi desain yang kuat sebagai sistem kontrol versi terdistribusi (DVCS), namun antarmukanya (CLI) tidak selalu intuitif.&lt;/p>
&lt;p>Artikel ini mengklasifikasikan berbagai &amp;ldquo;kesalahan umum&amp;rdquo; yang sering dihadapi oleh pemula Git di lapangan ke dalam berbagai kasus, dan menyajikan perintah sebagai solusi spesifik untuk masing-masing kasus. Namun, ini tidak akan menjadi sekadar daftar perintah (cheat sheet). Kami akan menggali lebih dalam dengan menjelaskan &amp;ldquo;mengapa kesalahan itu terjadi&amp;rdquo; dan &amp;ldquo;bagaimana data bergerak di dalam Git saat perintah tersebut dijalankan&amp;rdquo;, menggunakan struktur direktori &lt;code>.git&lt;/code>, latar belakang matematis dari algoritma Diff yang berjalan di belakangnya, dan diagram Mermaid. Semuanya akan dibahas tuntas dalam lebih dari 10.000 karakter.&lt;/p>
&lt;p>Pada saat Anda selesai membaca artikel ini, Anda seharusnya dapat melepaskan diri dari perasaan &amp;ldquo;takut pada Git&amp;rdquo;, dan sebaliknya, Anda akan yakin bahwa &amp;ldquo;tidak ada rekan yang lebih bisa diandalkan daripada Git&amp;rdquo;. Sekarang, mari kita terjun ke dunia Git yang mendalam.&lt;/p>
&lt;hr>
&lt;h2 id="2-jurang-git-memahami-struktur-internal-direktori-git">2. Jurang Git: Memahami Struktur Internal Direktori &lt;code>.git&lt;/code>
&lt;/h2>&lt;p>Langkah pertama untuk mempermudah pemecahan masalah adalah mengetahui bagaimana Git menyimpan data. Folder tersembunyi &lt;code>.git&lt;/code> yang ada di direktori root proyek Anda adalah jantung dari Git. Git bukanlah sistem yang hanya merekam perbedaan file (patch) secara berurutan, melainkan mengelola data sebagai &lt;strong>aliran snapshot (snapshot stream)&lt;/strong>.&lt;/p>
&lt;h3 id="21-model-objek-blob-tree-commit">2.1 Model Objek: Blob, Tree, Commit
&lt;/h3>&lt;p>Git pada dasarnya menggunakan 3 objek untuk merepresentasikan keadaan repositori. Objek-objek ini disimpan di &lt;code>.git/objects&lt;/code>.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Blob (Binary Large Object)&lt;/strong>
Objek ini menyimpan isi file itu sendiri. Informasi tentang nama file atau izin tidak disertakan di sini. Urutan byte murni dikompresi dengan zlib dan diidentifikasi oleh nilai hash SHA-1 (40 karakter heksadesimal).&lt;/li>
&lt;li>&lt;strong>Tree&lt;/strong>
Objek ini merepresentasikan struktur direktori. Objek Tree berisi pointer (nilai hash SHA-1) ke objek Tree lainnya (subdirektori) atau objek Blob (file), beserta nama file dan izin aksesnya. Ini berfungsi mirip dengan direktori pada UNIX.&lt;/li>
&lt;li>&lt;strong>Commit&lt;/strong>
Menyimpan pointer ke objek Tree tingkat atas (top-level) dari seluruh repositori pada titik waktu tertentu, bersama dengan metadata (pembuat, tanggal dan waktu komit, pesan komit), dan pointer ke komit sebelumnya (komit induk).&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
graph TD
Commit1[&amp;#34;Komit (Hash: 9f8a)&amp;#34;] --&amp;gt; Tree1[&amp;#34;Tree (Hash: 4b82)&amp;#34;]
Tree1 --&amp;gt; Blob1[&amp;#34;Blob (Hash: 8d7e) : index.js&amp;#34;]
Tree1 --&amp;gt; Tree2[&amp;#34;Tree (Hash: 3a2c) : src/&amp;#34;]
Tree2 --&amp;gt; Blob2[&amp;#34;Blob (Hash: 5f1b) : app.js&amp;#34;]
&lt;/pre>
&lt;h3 id="22-identitas-asli-head-dan-referensi-refs">2.2 Identitas Asli HEAD dan Referensi (Refs)
&lt;/h3>&lt;p>Saat bekerja dengan Git, Anda akan sering melihat kata &lt;code>HEAD&lt;/code>. Ini adalah &lt;strong>referensi simbolik (Symbolic Reference)&lt;/strong> yang menunjuk ke cabang (atau komit) yang sedang di-checkout saat ini.
Jika Anda membuka file &lt;code>.git/HEAD&lt;/code> dengan teks editor, Anda akan melihat string seperti berikut:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ref: refs/heads/main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ini berarti &amp;ldquo;keadaan saat ini berada di ujung cabang &lt;code>main&lt;/code>&amp;rdquo;. Dan, jika Anda membuka &lt;code>.git/refs/heads/main&lt;/code>, Anda akan melihat hash SHA-1 sebanyak 40 karakter tertulis di sana, yang menunjuk ke objek Commit terbaru.
Cabang Git hanyalah pointer ringan (file) yang menunjuk ke komit tertentu. Hanya dengan mengetahui fakta ini, ketakutan bahwa &amp;ldquo;jika saya menghapus cabang, apakah semua file akan hilang?&amp;rdquo; akan sirna.&lt;/p>
&lt;hr>
&lt;h2 id="3-mengartikan-git-dengan-matematika-algoritma-diff-dan-fungsi-hash">3. Mengartikan Git dengan Matematika: Algoritma Diff dan Fungsi Hash
&lt;/h2>&lt;p>Ketika Git mendeteksi konflik atau menampilkan perbedaan pada file, algoritma tingkat lanjut sedang berjalan di latar belakang.&lt;/p>
&lt;h3 id="31-algoritma-diff-myers">3.1 Algoritma Diff Myers
&lt;/h3>&lt;p>Algoritma pendeteksi perbedaan default pada Git adalah algoritma yang dirancang oleh Eugene W. Myers. Ketika ada dua file teks $A$ dan $B$, masalah untuk menemukan &amp;ldquo;urutan pengeditan minimum (penyisipan dan penghapusan)&amp;rdquo; untuk mengubah $A$ menjadi $B$ dapat dimodelkan sebagai masalah jalur terpendek dalam teori graf.&lt;/p>
&lt;p>Misalkan panjang string masing-masing adalah $N$ dan $M$, dan totalnya adalah $V = N + M$. Dalam algoritma Myers, pencarian Jarak Edit (Edit Distance) $D$ dilakukan. Kompleksitas waktu algoritma ini dinyatakan dengan rumus berikut:&lt;/p>
$$ \mathcal{O}(V \cdot D) $$&lt;p>Di sini, jika perbedaan antar file kecil (artinya $D$ kecil), algoritma bekerja sangat cepat dengan $\mathcal{O}(V)$. Namun, jika filenya benar-benar berbeda, $D \approx V$, dan kompleksitas terburuknya menjadi $\mathcal{O}(V^2)$.&lt;/p>
&lt;h3 id="32-patience-diff-dan-histogram-diff">3.2 Patience Diff dan Histogram Diff
&lt;/h3>&lt;p>Meskipun algoritma Myers sangat baik, terkadang dapat menghasilkan perbedaan yang tidak intuitif (tidak bermakna) bagi manusia, misalnya ketika urutan fungsi atau kelas diubah secara signifikan. Untuk mengatasi hal ini, Git mengimplementasikan &lt;code>Patience Diff&lt;/code> dan &lt;code>Histogram Diff&lt;/code>.&lt;/p>
&lt;p>Patience Diff berfokus pada &amp;ldquo;baris unik yang muncul hanya sekali di kedua file&amp;rdquo;, dan menemukan Urutan Bagian Terpanjang Bersama (Longest Common Subsequence: LCS) dari baris-baris tersebut. Jika jumlah elemen unik adalah $U$, perhitungan LCS dapat diselesaikan dengan kompleksitas berikut:&lt;/p>
$$ \mathcal{O}(U \log U) $$&lt;p>Ketika Anda merasa sulit untuk menyelesaikan konflik, salah satu pendekatannya adalah dengan menggunakan &lt;code>git diff --histogram&lt;/code> atau menentukan algoritma ini dalam strategi penggabungan (merge) (&lt;code>git merge -s recursive -X histogram&lt;/code>).&lt;/p>
&lt;h3 id="33-sha-1-dan-probabilitas-tabrakan">3.3 SHA-1 dan Probabilitas Tabrakan
&lt;/h3>&lt;p>Git mengelola semua objek menggunakan nilai hash SHA-1. Ukuran ruang hash adalah $2^{160}$. Mengenai probabilitas tabrakan hash (di mana konten yang berbeda memiliki nilai hash yang sama), jika diperkirakan menggunakan Paradoks Ulang Tahun (Birthday Paradox), jumlah objek $k$ yang dibutuhkan agar probabilitas tabrakan $p$ menjadi 50% adalah sebagai berikut:&lt;/p>
$$ k \approx \sqrt{2 \ln(2)} \cdot 2^{80} \approx 1.2 \times 2^{80} $$&lt;p>Ini adalah angka astronomis, dan probabilitas tabrakan yang tidak disengaja terjadi dalam pengembangan perangkat lunak pada umumnya hampir nol. Oleh karena itu, Git beroperasi dengan mempercayai nilai hash sebagai &amp;ldquo;ID unik yang mutlak&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="4-studi-kasus-1-saya-melakukan-komit-ke-cabang-yang-salah">4. Studi Kasus 1: Saya Melakukan Komit ke Cabang yang Salah!
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Tanpa sadar bahwa saya sedang bekerja di cabang &lt;code>main&lt;/code>, saya menulis banyak kode untuk fitur baru, dan bahkan menjalankan &lt;code>git commit&lt;/code>. Padahal seharusnya saya membuat cabang &lt;code>feature/login&lt;/code> dan bekerja di sana!&lt;/p>
&lt;h3 id="solusi-git-reset-dan-membuat-cabang-baru">Solusi: &lt;code>git reset&lt;/code> dan Membuat Cabang Baru
&lt;/h3>&lt;p>Dalam Git, komit adalah objek independen, dan cabang hanyalah pointer. Oleh karena itu, Anda dapat langsung menyelesaikannya dengan operasi: &amp;ldquo;buat cabang baru, lalu mundurkan pointer dari cabang saat ini&amp;rdquo;.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Buat cabang baru yang menunjuk ke komit saat ini (komit yang dibuat secara tidak sengaja)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git branch feature/login
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Mundurkan pointer cabang main ke satu komit sebelumnya (HEAD~1)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Menggunakan --keep memungkinkan Anda melakukan reset dengan aman sambil mempertahankan perubahan yang belum dikomit di direktori kerja Anda.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git reset --keep HEAD~1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Beralih ke cabang yang benar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout feature/login
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="penjelasan-gambar-apa-yang-terjadi-di-dalam">Penjelasan Gambar: Apa yang Terjadi di Dalam?
&lt;/h3>&lt;p>Mari kita visualisasikan pergerakan pointer cabang pada saat ini menggunakan &lt;code>gitGraph&lt;/code> dari Mermaid.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;Komit awal&amp;#34;
commit id: &amp;#34;Perbaikan bug&amp;#34;
commit id: &amp;#34;Komit yang Salah&amp;#34; type: HIGHLIGHT
branch feature/login
checkout feature/login
checkout main
&lt;/pre>
&lt;p>Pada awalnya, &lt;code>main&lt;/code> dan &lt;code>HEAD&lt;/code> menunjuk ke &amp;ldquo;Komit yang Salah&amp;rdquo;, tetapi &lt;code>git branch feature/login&lt;/code> membuat pointer baru di sana. Setelah itu, karena &lt;code>git reset&lt;/code>, hanya pointer &lt;code>main&lt;/code> yang kembali ke posisi &amp;ldquo;Perbaikan bug&amp;rdquo;. Objeknya sendiri tidak ada yang dihapus.&lt;/p>
&lt;hr>
&lt;h2 id="5-studi-kasus-2-saya-ingin-membatalkan-komit-yang-sudah-di-push">5. Studi Kasus 2: Saya Ingin Membatalkan Komit yang Sudah Di-push!
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Mengerjakan koding larut malam membuat saya mengkomit kode yang penuh bug, dan bahkan mempublikasikannya ke repositori jarak jauh (remote) dengan &lt;code>git push origin main&lt;/code>. Saya menjadi panik saat menyadari adanya bug kritis.&lt;/p>
&lt;h3 id="solusi-1-membatalkan-sejarah-dengan-git-revert-disarankan--aman">Solusi 1: Membatalkan Sejarah dengan &lt;code>git revert&lt;/code> (Disarankan / Aman)
&lt;/h3>&lt;p>Dalam pengembangan tim, sangat dilarang untuk mengubah riwayat komit yang sudah di-push menggunakan perintah seperti &lt;code>git reset&lt;/code>. Ini akan menyebabkan inkonsistensi dengan repositori lokal pengembang lain. Pendekatan yang benar adalah &lt;strong>&amp;ldquo;membuat komit baru yang sepenuhnya membatalkan perubahan dari komit yang salah&amp;rdquo;&lt;/strong>. Ini adalah fungsi dari &lt;code>git revert&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Buat komit yang membatalkan komit terbaru&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git revert HEAD
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>main 7f3a8b2&lt;span class="o">]&lt;/span> Revert &lt;span class="s2">&amp;#34;Pesan komit yang salah&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> file changed, &lt;span class="m">1&lt;/span> insertion&lt;span class="o">(&lt;/span>+&lt;span class="o">)&lt;/span>, &lt;span class="m">10&lt;/span> deletions&lt;span class="o">(&lt;/span>-&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Push ke remote&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git push origin main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;Komit A&amp;#34;
commit id: &amp;#34;Komit B (Salah)&amp;#34;
commit id: &amp;#34;Revert Komit B&amp;#34; type: REVERSE
&lt;/pre>
&lt;p>Sejarah terus berlanjut, dan hanya status kodenya yang dikembalikan ke keadaan semula.&lt;/p>
&lt;h3 id="solusi-2-mengubah-sejarah-dengan-git-push---force-with-lease">Solusi 2: Mengubah Sejarah dengan &lt;code>git push --force-with-lease&lt;/code>
&lt;/h3>&lt;p>Jika Anda baru saja melakukan push ke cabang yang hanya digunakan oleh Anda sendiri, maka mengubah riwayat dapat ditoleransi.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Reset komit secara lokal dan perbaiki&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git reset --hard HEAD~1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git add .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git commit -m &lt;span class="s2">&amp;#34;Correct implementation&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Timpa riwayat jarak jauh secara paksa&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git push origin feature/login --force-with-lease
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>--force-with-lease&lt;/code> adalah push paksa yang aman untuk mencegah kecelakaan di mana Anda secara tidak sengaja menimpa pekerjaan orang lain.&lt;/p>
&lt;hr>
&lt;h2 id="6-studi-kasus-3-saya-ingin-beralih-ke-cabang-lain-saat-sedang-bekerja-keajaiban-stash">6. Studi Kasus 3: Saya Ingin Beralih ke Cabang Lain Saat Sedang Bekerja (Keajaiban Stash)
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Sedang mengimplementasikan fitur baru di cabang &lt;code>feature/A&lt;/code>, kode sumbernya masih berantakan dan belum bisa dikompilasi. Tiba-tiba atasan memberi instruksi: &amp;ldquo;Ada bug darurat di lingkungan produksi cabang &lt;code>main&lt;/code>, tolong perbaiki sekarang juga!&amp;rdquo;&lt;/p>
&lt;h3 id="solusi-menyimpan-sementara-dengan-git-stash">Solusi: Menyimpan Sementara dengan &lt;code>git stash&lt;/code>
&lt;/h3>&lt;p>&lt;code>git stash&lt;/code> adalah perintah untuk menyimpan sementara perubahan yang belum dikomit ke area sementara.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Simpan perubahan yang sedang dikerjakan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git stash push -m &lt;span class="s2">&amp;#34;WIP: feature A partially implemented&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Sekarang Anda dapat beralih ke cabang main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ...(melakukan perbaikan bug darurat, commit, dan push)...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Setelah pekerjaan selesai, kembali ke cabang semula&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout feature/A
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. Pulihkan perubahan yang telah disimpan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git stash pop
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ketika &lt;code>git stash&lt;/code> dijalankan, Git secara internal menghasilkan dua objek komit khusus dan menyimpannya di referensi bernama &lt;code>refs/stash&lt;/code>. Artinya, Stash pada dasarnya juga merupakan &amp;ldquo;komit sementara yang tidak memiliki nama&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="7-studi-kasus-4-keadaan-mengerikan-detached-head">7. Studi Kasus 4: Keadaan Mengerikan &amp;ldquo;Detached HEAD&amp;rdquo;
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Saya ingin memeriksa kode pada titik waktu tertentu di masa lalu, jadi saya menjalankan &lt;code>git checkout 9f8a7b6&lt;/code>. Kemudian muncul pesan &lt;code>You are in 'detached HEAD' state.&lt;/code>. Saya tetap melakukan komit, tetapi setelah berpindah cabang, komit tersebut menghilang!&lt;/p>
&lt;h3 id="mekanisme-detached-head">Mekanisme Detached HEAD
&lt;/h3>&lt;p>Biasanya &lt;code>HEAD&lt;/code> menunjuk ke cabang seperti &lt;code>refs/heads/main&lt;/code>. Namun, jika Anda melakukan checkout pada komit tertentu secara langsung, &lt;code>HEAD&lt;/code> akan menunjuk langsung ke objek komit tersebut. Ini disebut &lt;strong>Detached HEAD (HEAD yang terpisah)&lt;/strong>.&lt;/p>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Komit A&amp;#34;] --&amp;gt; B[&amp;#34;Komit B&amp;#34;]
B --&amp;gt; C[&amp;#34;Komit C&amp;#34;]
C --&amp;gt; D[&amp;#34;Komit D&amp;#34;]
BranchMain[&amp;#34;Cabang: main&amp;#34;] --&amp;gt; D
HEAD[&amp;#34;HEAD&amp;#34;] --&amp;gt; B
style HEAD fill:#f9f,stroke:#333,stroke-width:4px
&lt;/pre>
&lt;p>Dalam keadaan ini, jika Anda menambahkan komit, tidak ada cabang yang akan melacak komit baru tersebut. Saat Anda beralih ke cabang lain, komit baru itu akan tersesat.&lt;/p>
&lt;h3 id="solusi-simpan-sebagai-cabang-baru">Solusi: Simpan Sebagai Cabang Baru
&lt;/h3>&lt;p>Anda dapat menyelesaikannya dengan membuat cabang baru di posisi Anda saat ini.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Buat cabang baru di posisi HEAD saat ini dan beralih ke cabang tersebut&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout -b feature/recovered-work
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="8-studi-kasus-5-menyelesaikan-konflik-saat-merge-dan-rebase">8. Studi Kasus 5: Menyelesaikan Konflik Saat Merge dan Rebase
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Saat menjalankan &lt;code>git merge&lt;/code> atau &lt;code>git rebase&lt;/code>, muncul pesan &lt;code>CONFLICT (content)&lt;/code>, dan proses dihentikan.&lt;/p>
&lt;h3 id="perbedaan-antara-merge-penggabungan-dan-rebase-penyusunan-ulang">Perbedaan Antara Merge (Penggabungan) dan Rebase (Penyusunan Ulang)
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>Merge (Penggabungan)&lt;/strong>
Melakukan 3-way merge menggunakan komit terbaru dari kedua cabang dan leluhur bersamanya (common ancestor), serta membuat komit gabungan (merge commit).&lt;/li>
&lt;li>&lt;strong>Rebase (Penyusunan Ulang)&lt;/strong>
Menyimpan sementara komit dari cabang saat ini, lalu menerapkannya kembali di ujung target. Riwayatnya akan menjadi satu garis lurus.&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;M1&amp;#34;
commit id: &amp;#34;M2&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;F1&amp;#34;
commit id: &amp;#34;F2&amp;#34;
checkout main
commit id: &amp;#34;M3&amp;#34;
merge feature
&lt;/pre>
&lt;h3 id="cara-menyelesaikan-konflik">Cara Menyelesaikan Konflik
&lt;/h3>&lt;p>Penanda berikut akan disisipkan dalam file yang mengalami konflik.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span> &lt;span class="nx">HEAD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.production.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">=======&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.staging.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="nx">feature&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="k">new&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">api&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Langkah penyelesaiannya sangat sederhana.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Hapus penanda dan perbaiki kodenya.&lt;/strong>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">process&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">env&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">NODE_ENV&lt;/span> &lt;span class="o">===&lt;/span> &lt;span class="s1">&amp;#39;production&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">?&lt;/span> &lt;span class="s2">&amp;#34;https://api.production.example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://api.staging.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>&lt;strong>Tambahkan file yang sudah diperbaiki ke staging.&lt;/strong>
&lt;code>git add&lt;/code> memiliki peran &amp;ldquo;memberitahu Git bahwa konflik telah diselesaikan&amp;rdquo;.
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ git add index.js
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>&lt;strong>Selesaikan prosesnya.&lt;/strong>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Untuk merge&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git commit -m &lt;span class="s2">&amp;#34;Resolve merge conflict in index.js&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Untuk rebase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git rebase --continue
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Jika panik, Anda bisa membatalkannya kapan saja dengan &lt;code>$ git merge --abort&lt;/code> atau &lt;code>$ git rebase --abort&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="9-studi-kasus-6-riwayat-komit-berantakan-git-rebase--i">9. Studi Kasus 6: Riwayat Komit Berantakan! &lt;code>git rebase -i&lt;/code>
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
&amp;ldquo;Perbaikan typo&amp;rdquo;, &amp;ldquo;perbaikan lagi&amp;rdquo;, &amp;ldquo;tambah tes&amp;rdquo;, dan banyak komit kecil lainnya terkumpul. Jika di-merge ke &lt;code>main&lt;/code> seperti ini, riwayatnya akan terlihat kotor.&lt;/p>
&lt;h3 id="solusi-interactive-rebase-rebase-interaktif">Solusi: Interactive Rebase (Rebase Interaktif)
&lt;/h3>&lt;p>Dengan menggunakan &lt;code>git rebase -i&lt;/code> (interactive), Anda dapat mengubah urutan komit sebelumnya, menggabungkan beberapa komit menjadi satu (squash), atau mengubah pesan komit.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Rapikan 3 komit terakhir&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git rebase -i HEAD~3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Editor akan terbuka dan menampilkan hal berikut:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">pick 1a2b3c4 Perbaikan typo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pick 2b3c4d5 Perbaikan lagi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pick 3c4d5e6 Tambah tes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ubah ini menjadi seperti berikut:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">pick 1a2b3c4 Implementasi Fitur X
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">squash 2b3c4d5 Perbaikan lagi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">squash 3c4d5e6 Tambah tes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Setelah disimpan dan ditutup, ketiga komit ini akan digabungkan menjadi satu dengan rapi.&lt;/p>
&lt;hr>
&lt;h2 id="10-studi-kasus-7-tidak-tahu-kapan-bug-masuk-git-bisect">10. Studi Kasus 7: Tidak Tahu Kapan Bug Masuk! &lt;code>git bisect&lt;/code>
&lt;/h2>&lt;p>&lt;strong>[Situasi]&lt;/strong>
Terdapat bug pada cabang &lt;code>main&lt;/code> saat ini, namun saat rilis sebulan yang lalu semuanya normal. Saya ingin mencari komit mana yang memasukkan bug tersebut, tetapi ada lebih dari 100 komit sehingga tidak mungkin dilakukan secara manual!&lt;/p>
&lt;h3 id="solusi-identifikasi-bug-dengan-pencarian-biner">Solusi: Identifikasi Bug dengan Pencarian Biner
&lt;/h3>&lt;p>Git memiliki alat bawaan untuk menemukan komit penyebab bug dengan menggunakan pencarian biner matematis (Binary Search). Karena kompleksitasnya adalah $\mathcal{O}(\log N)$, meskipun ada 1000 komit, ia dapat mengidentifikasinya hanya dalam sekitar 10 pengujian.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Mulai pencarian&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect start
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Komit saat ini mengandung bug (bad)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect bad
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Sebulan lalu (misalnya hash a1b2c3d) masih normal (good)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect good a1b2c3d
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Git akan secara otomatis men-checkout komit di tengah-tengah, lalu jalankan pengujian&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Jika tes berhasil:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect good
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Jika tes gagal:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect bad
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan mengulangi ini, Git akan memberi tahu Anda dengan tepat, &amp;ldquo;Ini adalah komit Bad yang pertama&amp;rdquo;. Setelah selesai, kembalikan ke status awal dengan &lt;code>$ git bisect reset&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="11-jaring-pengaman-utama-git-reflog">11. Jaring Pengaman Utama: &lt;code>git reflog&lt;/code>
&lt;/h2>&lt;p>Jurus rahasia terakhir untuk mengatasi segala &amp;ldquo;kesalahan&amp;rdquo; di Git adalah &lt;code>git reflog&lt;/code>. Git mencatat semua riwayat operasi lokal (riwayat pergerakan HEAD) selama periode tertentu. Bahkan jika Anda menghapus cabang atau melakukan reset yang salah, Anda dapat menemukan hash sebelumnya dengan &lt;code>git reflog&lt;/code> dan memulihkannya hanya dengan melakukan &lt;code>git reset --hard&lt;/code> ke hash tersebut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ git reflog
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">9f8a7b6 &lt;span class="o">(&lt;/span>HEAD -&amp;gt; main&lt;span class="o">)&lt;/span> HEAD@&lt;span class="o">{&lt;/span>0&lt;span class="o">}&lt;/span>: commit: Add new feature
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1a2b3c4 HEAD@&lt;span class="o">{&lt;/span>1&lt;span class="o">}&lt;/span>: reset: moving to HEAD~1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="12-penutup">12. Penutup
&lt;/h2>&lt;p>Kami telah menjelaskan secara sangat rinci kesalahan yang sering dilakukan oleh pemula Git, mekanisme Git di baliknya, dan cara mengatasinya. Mulai dari melakukan komit ke cabang yang salah, membatalkan komit yang sudah di-push, memanfaatkan Stash, selamat dari Detached HEAD, hingga menyelesaikan konflik. Yang paling penting dalam semua hal ini adalah membayangkan &amp;ldquo;objek dan pointer apa yang sedang dimanipulasi Git di latar belakang&amp;rdquo;.&lt;/p>
&lt;p>Perbedaan file dihitung menggunakan algoritma Diff yang ketat yang dapat direpresentasikan oleh rumus matematika, dan konsistensi riwayat dijamin oleh fungsi hash kriptografi. Jika Anda memahami filosofi desain yang indah ini, Anda akan menyadari bahwa Git bukanlah &amp;ldquo;kotak hitam misterius&amp;rdquo;, melainkan perisai terkuat untuk melindungi kode sumber Anda dengan kuat.&lt;/p>
&lt;p>Lain kali Anda berpikir, &amp;ldquo;Oh tidak, saya mengacaukannya!&amp;rdquo;, jangan panik lalu menutup terminal. Tariklah napas dalam-dalam dan ketik &lt;code>git status&lt;/code>. Git pasti akan memberi Anda petunjuk untuk pemulihan.&lt;/p></description></item></channel></rss>