GitHub Flow mengorbankan segala protokol demi kecepatan sampai pengguna — pilihan yang tepat untuk web yang bisa dideploy kapan saja, dan salah untuk perangkat lunak yang penggunanya menunggu nomor versi. Aplikasi desktop yang dirilis per kuartal, library publik yang menjaga kompatibilitas, firmware yang terkunci jadwal: semuanya butuh bagan yang mengatur bukan hanya bagaimana fitur masuk, tetapi juga bagaimana ia dibekukan, diuji, ditandai, dan diperbaiki setelah rilis. GitFlow — model yang dirumuskan Vincent Driessen pada 2010 — adalah bagan itu: lima jenis branch dengan tugas yang dibakukan seperti pos-pos di lini produksi.

Lima Jenis Branch dan Tugasnya #

BranchDilahirkan dariMenyatu kembali keTugas
main——cermin produksi; hanya menerima merge dan tag
developmainmain lewat releaseintegrasi fitur jadi satu calon rilis
feature/*developdevelopsatu fitur terisolasi hingga matang
release/*developmain dan developpembekuan calon rilis: hanya perbaikan
hotfix/*mainmain dan developdarurat produksi, secepat mungkin

Dua hal membedakan model ini dari workflow sebelumnya. Pertama, main dan develop berdiri sebagai dua garis paralel yang panjang umur: main hanya bergerak saat rilis resmi (setiap gerakannya berpasangan tag), sementara fitur-fitur berintegrasi di develop yang boleh sesekali tidak sempurna. Kedua, branch release/* dan hotfix/* menghubungkan kedua dunia itu dengan arah yang berlawanan: release membawa hasil develop turun ke main secara terjadwal, hotfix memanjat dari main kembali ke develop secara darurat.

Peta Lengkap Model #

Seluruh model dalam satu bagan (dibaca dari kiri ke kanan; setiap merge terlihat sebagai penyatuan jalur):

Ceritanya dibaca empat babak. main berangkat dari kerangka bertanda v1.0.0; develop bercabang dari sana dan menjadi tempat fitur/keranjang bergabung — persis pola feature branch, hanya pindah rumah ke develop. Saat calon rilis dianggap siap, release/1.1.0 dibekukan dari develop, menerima commit penomoran versi, lalu menyatu ke main dengan tag v1.1.0 — dan menyatu sekali lagi ke develop supaya pekerjaan berikutnya tidak kehilangan isi rilisnya. Babak keempat adalah darurat: bug pembayaran ditemukan di produksi; hotfix/pembayaran berangkat dari main — bukan dari develop — diperbaiki, ditandai v1.1.1, lalu dibawa pulang ke develop juga.

Demo Mini di Sandbox #

Kerangka latihan berdiri di main dan langsung ditandai rilis pertama — tag annotated, pola dari section Tags dan Releases :

bash
mkdir toko-gitflow && cd toko-gitflow
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'beranda\n' > situs.md
git add situs.md
git commit -m "Buat kerangka toko"
git tag -a v1.0.0 -m "Rilis pertama"

Output yang Dihasilkan (git commit):

text
[main (root-commit) d0a67e6] Buat kerangka toko
 1 file changed, 1 insertion(+)
 create mode 100644 situs.md

Garis integrasi lahir, lalu fitur pertama bercabang darinya:

bash
git switch -c develop
git switch -c fitur/keranjang

Output yang Dihasilkan (perintah terakhir):

text
Switched to a new branch 'fitur/keranjang'
bash
printf 'keranjang\n' > keranjang.md
git add keranjang.md
git commit -m "Tambah keranjang belanja"
printf 'keranjang\ntotal\n' > keranjang.md
git add keranjang.md
git commit -m "Tambah hitung total"

Output yang Dihasilkan (dua commit):

text
[fitur/keranjang 4098a60] Tambah keranjang belanja
 1 file changed, 1 insertion(+)
 create mode 100644 keranjang.md
text
[fitur/keranjang d9b0f52] Tambah hitung total
 1 file changed, 1 insertion(+)

Fitur kembali menyatu ke develop — selalu --no-ff agar batas fitur terlihat, persis kebiasaan Feature Branch Workflow :

bash
git switch develop
git merge --no-ff fitur/keranjang
git branch -d fitur/keranjang

Output yang Dihasilkan (git merge):

text
Merge made by the 'ort' strategy.
 keranjang.md | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 keranjang.md

Output yang Dihasilkan (git branch -d):

text
Deleted branch fitur/keranjang (was d9b0f52).
bash
git log --oneline --graph --all --decorate

Output yang Dihasilkan:

text
*   fff455b (HEAD -> develop) Merge branch 'fitur/keranjang' into develop
|\  
| * d9b0f52 Tambah hitung total
| * 4098a60 Tambah keranjang belanja
|/  
* d0a67e6 (tag: v1.0.0, main) Buat kerangka toko

Pesan merge-nya berbunyi into develop — Git menambahkan nama branch tujuan bila yang menerima bukan main; hash di mesin pembaca berbeda, bentuknya tidak. Graf ini adalah wajah khas GitFlow pada pertengahan siklus: main diam di v1.0.0, develop menampung gelembung merge fitur.

Waktunya rilis. release/1.1.0 dibekukan dari develop — sejak titik ini ia hanya boleh menerima perbaikan kecil, dan perubahan yang masuk adalah penomoran versi:

bash
git switch -c release/1.1.0
printf '1.1.0\n' > VERSION
git add VERSION
git commit -m "Siapkan rilis 1.1.0"

Output yang Dihasilkan (perintah terakhir):

text
[release/1.1.0 dd98646] Siapkan rilis 1.1.0
 1 file changed, 1 insertion(+)
 create mode 100644 VERSION

Rilis menyatu ke main, ditandai tag, lalu dibawa pulang ke develop — tiga gerakan penutup siklus:

bash
git switch main
git merge --no-ff release/1.1.0
git tag -a v1.1.0 -m "Rilis 1.1.0"
git switch develop
git merge --no-ff release/1.1.0
git branch -d release/1.1.0

Output yang Dihasilkan (merge ke main):

text
Merge made by the 'ort' strategy.
 VERSION | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 VERSION

Output yang Dihasilkan (merge ke develop):

text
Merge made by the 'ort' strategy.
 VERSION | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 VERSION

Output yang Dihasilkan (git branch -d):

text
Deleted branch release/1.1.0 (was dd98646).

Tag diam tanpa keluaran — perilaku biasa git tag. Peta akhirnya:

bash
git log --oneline --graph --all --decorate
git tag

Output yang Dihasilkan (dua perintah):

text
*   cb44452 (HEAD -> develop) Merge branch 'release/1.1.0' into develop
|\  
| | *   e102c00 (tag: v1.1.0, main) Merge branch 'release/1.1.0'
| | |\  
| | |/  
| |/|   
| * | dd98646 Siapkan rilis 1.1.0
|/ /  
* |   fff455b Merge branch 'fitur/keranjang' into develop
|\ \  
| |/  
|/|   
| * d9b0f52 Tambah hitung total
| * 4098a60 Tambah keranjang belanja
|/  
* d0a67e6 (tag: v1.0.0) Buat kerangka toko
text
v1.0.0
v1.1.0

Dua tag, dua dunia: main berhenti di e102c00 bertanda v1.1.0 — persis apa yang berjalan di produksi — sementara develop sudah lebih maju dan siap menampung fitur berikutnya. Bila bug darurat muncul besok, jalur hotfix-nya mengikuti babak keempat bagan di atas: cabang dari main, satu perbaikan, tag patch, dua penyatuan. Prosesnya identik dengan siklus release yang barusan kita jalankan, hanya arah keberangkatannya yang dipindah ke main.

Kapan GitFlow Tepat — dan Kapan Tidak #

SituasiKecocokanAlasan
Aplikasi desktop dengan rilis terjadwalsangat cocokbranch rilis memberi ruang freeze dan stabilisasi
Library publik berversi semantiksangat cocokmain = versi terbaru yang dirilis, tag = kontrak API
Tim besar lintas zona waktucocokprotokol eksplisit mengurangi koordinasi ad-hoc
Perangkat dan firmwarecocokrilis terkunci jadwal dan perlu jejak per versi
Web / SaaS dengan deploy kontinutidak cocokjarak merge-ke-produksi mesti satu langkah — GitHub Flow
Startup prototype cepattidak cocokupacara lima branch melampaui ukuran tim

Sudut pandang penulisnya sendiri menegarkan batas ini: Vincent Driessen menambahkan refleksi pada tulisan aslinya bahwa GitFlow dirancang untuk perangkat lunak yang dirilis bernomor versi, bukan untuk proyek yang terus-menerus men-deploy — modelnya tetap berumur panjang justru karena mengaku wilayahnya dengan jujur. Tulisan aslinya bisa dibaca di nvie.com/posts/a-successful-git-branching-model/ , dan perbandingannya dengan workflow lain dirangkum Pro Git di bab pola percabangan . Alat bantu git flow — ekstensi yang membungkus seluruh upacara ini menjadi subperintah — tersedia di banyak distribusi bila tim ingin memperpendek ketikannya.

Di ujung spektrum yang berlawanan menunggu kebalikan total dari seluruh protokol ini: tanpa branch panjang, tanpa upacara rilis, hampir semua commit langsung ke jalur utama. Trunk-Based Development, chapter berikutnya, membuktikan bahwa disiplin bisa juga dicapai dengan jalan yang lebih pendek.