Riwayat commit adalah dokumen tertulis paling sering dibaca sebuah tim: dibuka saat git bisect, diringkas saat menyusun changelog, ditelusuri saat mencari kapan sebuah galat lahir. Masalahnya, Git tidak punya pendapat tentang gaya — lima kontributor berarti lima dialek: ada yang menulis “update”, ada yang menulis paragraf, ada yang lupa subjeknya sama sekali. Di proyek sendirian itu hanya estetika; di tim itu menjadi friksi. Chapter ini menyusun kesepakatan gaya menjadi tiga lapis yang saling menguatkan: kontrak tertulis di CONTRIBUTING.md, kerangka pesan lewat git config commit.template, dan penegak otomatis di hook serta CI.

Kontrak Tertulis: CONTRIBUTING.md #

Konvensi yang hidup di kepala satu orang hilang bersama liburannya. Karena itu lapis pertama adalah berkas CONTRIBUTING.md di akar repository — dokumen yang secara umum memuat cara menyiapkan lingkungan, aturan gaya, dan proses kontribusi; pada toko kita, bagiannya menyempit ke pesan commit. Budi menuliskannya sebelum kontributor kedua datang:

bash
mkdir konvensi && cd konvensi
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
cat > CONTRIBUTING.md <<'EOF'
# Kontribusi ke Toko

## Pesan commit

- Format Conventional Commits: `type(scope): deskripsi`.
- Subjek bahasa Indonesia, kalimat imperatif, tanpa titik akhir.
- Subjek maksimal 50 karakter termasuk prefiks; body maksimal 72 karakter per baris.
- Satu commit membawa satu perubahan logis.

## Sebelum commit pertama

Jalankan `git config commit.template pesan-commit.txt`
agar kerangka pesan muncul setiap kali editor terbuka.
EOF
git add CONTRIBUTING.md
git commit -m "docs: tulis aturan pesan commit"

Output yang Dihasilkan (perintah terakhir):

text
[main (root-commit) 65db580] docs: tulis aturan pesan commit
 1 file changed, 13 insertions(+)
 create mode 100644 CONTRIBUTING.md

Isi berkasnya bisa dibaca utuh — dan perhatikan bahwa commit pertamanya sudah mematuhi aturan yang barusan ditulisnya:

bash
cat CONTRIBUTING.md

Output yang Dihasilkan:

text
# Kontribusi ke Toko

## Pesan commit

- Format Conventional Commits: `type(scope): deskripsi`.
- Subjek bahasa Indonesia, kalimat imperatif, tanpa titik akhir.
- Subjek maksimal 50 karakter termasuk prefiks; body maksimal 72 karakter per baris.
- Satu commit membawa satu perubahan logis.

## Sebelum commit pertama

Jalankan `git config commit.template pesan-commit.txt`
agar kerangka pesan muncul setiap kali editor terbuka.

Format yang Dipilih: Conventional Commits #

Lapis kedua adalah isi kesepakatannya. Pilihan yang paling luas diadopsi adalah Conventional Commits — prefiks type(scope): pada subjek — karena formatnya enak dibaca manusia sekaligus bisa diurai mesin untuk changelog dan penentuan versi. Formatnya dibedah tuntas di chapter Conventional Commits , dan spesifikasi lengkapnya — termasuk terjemahan resmi bahasa Indonesia — terdokumentasi di conventionalcommits.org . Yang perlu diputuskan tim adalah hal-hal di sekitarnya:

AspekAturan tim kitaAlasan
Bahasa subjekbahasa Indonesiaseluruh tim berbahasa sama; git log --grep jadi andal
Bentuk kalimatimperatif — “tambah”, bukan “menambahkan”paralel dengan pola subjek-body dari Menulis Commit Message
Prefikstype Conventional Commits wajib; scope opsionalriwayat bisa disaring per kelas perubahan
Panjang subjekmaksimal 50 karakter termasuk prefikstidak terpotong di git log --oneline
Bodydipisah baris kosong, maksimal 72 karakter per barisnyaman dibaca di terminal

Tabel semacam ini sebaiknya ditempelkan apa adanya ke CONTRIBUTING.md — keputusan yang tidak ditulis akan dilanggar tanpa sadar, bukan karena jahat, tetapi karena tidak ada yang mengingatnya.

Kerangka di Setiap Editor: commit.template #

Aturan yang tertulis masih harus dicari; kerangka yang muncul sendiri di editor jauh lebih dekat ke jari-jari. commit.template mengarahkan Git ke sebuah berkas yang isinya dituangkan ke buffer editor setiap kali git commit tanpa -m dijalankan. Kerangkanya di-commit agar seluruh tim memakai versi yang sama:

bash
printf '# <type>(<scope>): <deskripsi singkat>\n#\n# type wajib salah satu:\n#   feat fix docs style refactor perf test build ci chore revert\n# scope opsional, contoh: fitur keranjang -> feat(keranjang): ...\n' > pesan-commit.txt
git add pesan-commit.txt
git commit -m "chore: tambah kerangka pesan commit"
git config commit.template pesan-commit.txt
git config commit.template

Output yang Dihasilkan (dua perintah terakhir):

text
[main 1ddaf37] chore: tambah kerangka pesan commit
 1 file changed, 5 insertions(+)
 create mode 100644 pesan-commit.txt
text
pesan-commit.txt

Kerangka disimpan sengaja sebagai berkas biasa — bukan tersembunyi — supaya bisa masuk repository; konfigurasinya sendiri bersifat lokal, maka setiap anggota baru menjalankan satu baris git config itu sekali seumur clone, persis instruksi yang tertulis di CONTRIBUTING.md. Isi kerangkanya:

bash
cat pesan-commit.txt

Output yang Dihasilkan:

text
# <type>(<scope>): <deskripsi singkat>
#
# type wajib salah satu:
#   feat fix docs style refactor perf test build ci chore revert
# scope opsional, contoh: fitur keranjang -> feat(keranjang): ...

Seluruh baris diawali # — baris berawalan pagar diabaikan Git saat membaca pesan, jadi kerangka ini murni pengingat, bukan isi. Perilakunya bisa disaksikan tanpa editor interaktif dengan menempatkan cat sebagai editor — cat menampilkan buffer lalu keluar tanpa menyimpan suntingan, sehingga pesan tetap kosong dan commit dibatalkan:

bash
printf 'beranda\n' > situs.md
git add situs.md
GIT_EDITOR=cat git commit

Output yang Dihasilkan (perintah terakhir):

text
# <type>(<scope>): <deskripsi singkat>
#
# type wajib salah satu:
#   feat fix docs style refactor perf test build ci chore revert
# scope opsional, contoh: fitur keranjang -> feat(keranjang): ...

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Changes to be committed:
#	new file:   situs.md
#
Aborting commit due to empty commit message.

Di editor sungguhan, itulah tampilan pertama yang menyambut: kerangka tim di atas, petunjuk Git di bawah, dan kursor menunggu di baris pertama. Penulis pesan tinggal mengisi subjek lalu menyimpan. Dengan -m, kerangka tidak dipakai — tapi kebiasaan mengetik langsung pun sudah dijaga tabel aturan. Commitnya sendiri tetap harus ditulis sesuai konvensi:

bash
git commit -m "feat: tampilkan beranda toko"
git log --oneline

Output yang Dihasilkan (perintah terakhir):

text
f07739a feat: tampilkan beranda toko
1ddaf37 chore: tambah kerangka pesan commit
65db580 docs: tulis aturan pesan commit

Hash di mesin pembaca berbeda; pola tiga subjeknya tidak — dan justru pola itulah tujuan seluruh upacara ini.

Penegak Otomatis: Hook dan commitlint #

Kontrak dan kerangka mengingatkan yang lupa; penegak menolak yang bandel. Lapis ketiga ada dua. Pertama, hook commit-msg: hook sisi klien di .git/hooks/commit-msg yang menerima berkas berisi pesan calon commit — skrip kecil di dalamnya memeriksa pola type(scope): deskripsi dan keluar dengan kode satu bila pesan melanggar, sehingga commit gagal sebelum lahir. Cara pasang dan ujinya dibedah di chapter Commit-Msg Hook . Kedua, untuk gerbang yang tidak bisa dilewati walau hook lokal dihapus, pemeriksaan dipindah ke CI : alat seperti commitlint memeriksa pesan commit pada setiap pull request, dan riwayat yang tidak konsisten tertahan sebelum menyatu ke main.

Konvensi pesan menyeragamkan apa yang ditulis anggota tim. Proteksi berikutnya menyeragamkan apa yang boleh dilakukan terhadap branch bersama — dan proteksi itu tidak lagi berdiri di laptop masing-masing, melainkan di server tempat semua push berakhir. Protected Branches, chapter berikutnya, membangun gerbang itu.