Open source menjaga gerbang ketat karena penyumbangnya orang asing. Tim kecil — dua sampai lima orang satu repository — kebalikannya: rekan saling kenal, kecepatan mata uang utama, dan setiap upacara dibayar dari waktu anggota. Bahayanya datang dari dua arah: tanpa aturan, main rusak dan saling menimpa; dengan aturan tim besar, pekerjaan tenggelam di bawah birokrasi. Workflow tim kecil berdiri di tengah dengan lima aturan secukupnya — cukup untuk kualitas, cukup ringan untuk tidak terasa.
Lima Aturan Secukupnya #
maindiproteksi. Push langsung ditolak platform; semua perubahan lewat pull request — mekanismenya dibahas di Protected Branches .- PR wajib, review satu orang cukup. Satu pasang mata kedua menangkap sebagian besar galat; dua approvals hanya memperlambat.
- Branch pendek. Hidup kurang dari tiga hari; lebih dari itu, pecah pekerjaannya — utang konflik tumbuh per hari, pelajarannya di Menjaga Branch Tetap Sinkron .
- Squash merge. Satu PR menjadi satu commit di
main— riwayat linear yang enak dibaca dan dibisect. - Rilis menyusul saat dibutuhkan. Mengikuti pola Workflow Release begitu ada pengguna nyata — bukan sejak hari pertama.
Pilihan squash di aturan keempat punya pesaing yang sah:
| Strategi merge | Bentuk riwayat | Cocok saat |
|---|---|---|
merge --no-ff | gelembung per fitur | fitur besar yang ditelusuri sebagai satu unit |
squash | satu commit per PR, linear | PR kecil harian; main tetap pendek |
rebase merge | commit asli berjejer lurus | kontributor berdisiplin commit logis |
| fast-forward | tanpa jejak merge | branch privat sendirian |
Squash menang karena PR tim kecil memang kecil: commit “perbaiki typo” dan “lagi” tidak memperkaya main. Perilaku tombolnya di platform dijelaskan di dokumentasi merge pull request
.
Sesi Nyata: Dua PR Paralel, Satu Berkas Bersama #
Panggungnya model shared: bare pusat, dua meja:
mkdir tim-kecil && cd tim-kecil
mkdir budi && cd budi
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Toko Budi\n\n- [Produk](produk.md)\n' > beranda.md
printf '# Produk\n' > produk.md
git add .
git commit -m "Buat kerangka toko"
git init --bare ../toko-bersama.git
git remote add origin ../toko-bersama.git
git push -u origin main
cd ..
git clone toko-bersama.git siti
git -C siti remote set-url origin ../toko-bersama.git
git -C siti config user.name "Siti Rahma"
git -C siti config user.email "[email protected]"Output yang Dihasilkan (git commit dan git push):
[main (root-commit) 4ab526a] Buat kerangka toko
2 files changed, 4 insertions(+)
create mode 100644 beranda.md
create mode 100644 produk.mdTo ../toko-bersama.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.Dua fitur dikerjakan paralel: Budi menambah footer, Siti menambah kontak. Keduanya menautkan fiturnya di navigasi beranda.md — berkas bersama, tabrakan kecil menunggu di tikungan:
# meja Budi
cd budi
git switch -c fitur/footer
printf '# Footer\n' > footer.md
printf '# Toko Budi\n\n- [Produk](produk.md)\n- [Footer](footer.md)\n' > beranda.md
git add -A
git commit -m "Tambah footer"
git push -u origin fitur/footerOutput yang Dihasilkan (dua perintah terakhir):
[fitur/footer e1cb20c] Tambah footer
2 files changed, 2 insertions(+)
create mode 100644 footer.mdTo ../toko-bersama.git
* [new branch] fitur/footer -> fitur/footer
branch 'fitur/footer' set up to track 'origin/fitur/footer'.# meja Siti
cd ../siti
git switch -c fitur/kontak
printf '# Kontak\n' > kontak.md
printf '# Toko Budi\n\n- [Produk](produk.md)\n- [Kontak](kontak.md)\n' > beranda.md
git add -A
git commit -m "Tambah kontak"
git push -u origin fitur/kontakDi platform, dua pull request terbuka bersebelahan. PR Budi ditimbang lebih dulu: review satu orang, disetujui. Integrator menjalankan squash merge dari terminal:
cd ../budi
git switch main
git fetch origin
git merge --squash origin/fitur/footer
git commit -m "Tambah footer (#1)"
git push origin main
git push origin --delete fitur/footerOutput yang Dihasilkan (git merge –squash, git commit, dan penghapusan remote branch):
Updating 4ab526a..e1cb20c
Fast-forward
Squash commit -- not updating HEAD
beranda.md | 1 +
footer.md | 1 +
2 files changed, 2 insertions(+)
create mode 100644 footer.md[main 5081a1c] Tambah footer (#1)
2 files changed, 2 insertions(+)
create mode 100644 footer.mdTo ../toko-bersama.git
- [deleted] fitur/footerPerhatikan Squash commit -- not updating HEAD: perubahan hanya dipentaskan ke staging area tanpa menggerakkan main — commit dibuat terpisah dengan pesan yang kita tulis sendiri, lengkap nomor PR. Nomor (#1) bukan hiasan: git log --grep="#1" dan tautan otomatis platform saling menemukan.
Saat PR Siti tiba giliran, main sudah berisi tautan footer di beranda.md — dan branch Siti juga menambah tautannya di baris yang sama:
git merge --squash origin/fitur/kontakOutput yang Dihasilkan:
Auto-merging beranda.md
CONFLICT (content): Merge conflict in beranda.md
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.Konfliknya kecil dan lokasinya terbaca langsung dari isi beranda.md:
# Toko Budi
- [Produk](produk.md)
<<<<<<< HEAD
- [Footer](footer.md)
=======
- [Kontak](kontak.md)
>>>>>>> origin/fitur/kontakDua sisi sama-sama benar — keduanya menambah satu tautan. Penyelesaiannya menyimpan keduanya, prosedur lengkapnya dibahas di Menyelesaikan Merge Conflicts :
printf '# Toko Budi\n\n- [Produk](produk.md)\n- [Footer](footer.md)\n- [Kontak](kontak.md)\n' > beranda.md
git add beranda.md
git commit -m "Tambah kontak (#2)"
git push origin main
git push origin --delete fitur/kontak
git log --oneline --decorateOutput yang Dihasilkan (git commit dan git log):
[main e2cef12] Tambah kontak (#2)
2 files changed, 2 insertions(+)
create mode 100644 kontak.mde2cef12 (HEAD -> main, origin/main) Tambah kontak (#2)
5081a1c Tambah footer (#1)
4ab526a Buat kerangka tokoHash di mesin pembaca berbeda, bentuknya tidak: tiga baris lurus tanpa satu pun gelembung merge — inilah wajah riwayat squash. Siti menutup siklus dengan menarik hasil integrasi:
cd ../siti
git switch main
git pull --ff-onlyOutput yang Dihasilkan (perintah terakhir):
From ../toko-bersama
4ab526a..e2cef12 main -> origin/main
Updating 4ab526a..e2cef12
Fast-forward
beranda.md | 2 ++
footer.md | 1 +
kontak.md | 1 +
3 files changed, 4 insertions(+)
create mode 100644 footer.md
create mode 100644 kontak.mdSatu kejutan menunggu saat merapikan branch lokal. git branch -d Budi menolak menghapus fitur/footer:
error: the branch 'fitur/footer' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D fitur/footer'
hint: Disable this message with "git config advice.forceDeleteBranch false"Penolakan itu jujur: commit Tambah footer memang tidak pernah ada di main — squash hanya menyalin isinya ke commit baru. Setelah terverifikasi isinya sudah tergabung di main, penghapusan dilanjutkan dengan git branch -D fitur/footer.
Komunikasi yang Murah #
Konflik beranda.md di atas bisa dicegah dengan tiga puluh detik percakapan. Ritual tim kecil yang bekerja bukan rapat, melainkan satu putaran tiap pagi: siapa mengerjakan apa. Jawaban “aku ubah navigasi beranda” membuat Siti memilih menunggu atau menyelaraskan — bukan menabrak. Tabrakan yang diketahui lebih dulu dipecahkan dengan urutan merge atau pemecahan berkas; tabrakan yang mengejutkan baru terasa saat konflik menyala. Pola yang sama berlaku untuk wilayah: satu orang memegang api/, satu memegang web/.
Right-Sizing: Jangan Membeli Jas untuk Anak #
Aturan paling sering dilanggar tim kecil bukan kekurangan aturan, melainkan kelebihannya — biasanya GitFlow lengkap yang disalin dari blog tim ratusan orang. Tabel ini memetakan perangkat ke ukurannya:
| Ukuran tim | Perangkat yang cukup | Yang jadi berlebihan |
|---|---|---|
| 1 orang | main-only, commit berkala, tag | PR, review, develop |
| 2-5 orang | main terproteksi, PR, review 1 orang, squash | GitFlow penuh: develop, release/*, dua jalur merge |
| 6-15 orang | CI wajib di PR, CODEOWNERS per wilayah | review 5 orang untuk semua PR |
| lintas zona / rilis terjadwal | protokol eksplisit ala GitFlow | trunk-based tanpa disiplin tes |
Tim kecil ini satu repository berisi satu produk. Berikutnya skala berubah arah: satu tim, banyak produk, satu repository — monorepo. Disiplinnya bergeser dari branch ke direktori: commit yang menyebut wilayahnya, riwayat yang terbaca per aplikasi, dan pemilik berkas yang ditulis dalam berkas kecil bernama CODEOWNERS.