Ana Sayfa / Blog / Git commit mesaj disiplini: neden önemli, nasıl uygulanır?

Git commit mesaj disiplini: neden önemli, nasıl uygulanır?

Commit mesajları sadece tarih değil, kod tabanının hafızası. Disciplin'i nasıl kurduğum ve neden değerli.

Git log açıp son 100 commit’e bakın. Ne kadarını hatırlıyorsunuz? “fix bug”, “update”, “wip”, “stuff” gibi commit’ler tarih kaybı. İyi commit mesajları kod tabanının hafızası.

19 yıllık developer olarak çeşitli takımlarda bu disciplin’i kurmaya çalıştım. Bu yazıda pratik yaklaşımı paylaşacağım.

Commit mesajı neden önemli?

1. Future debugging. 6 ay sonra “bu satır neden böyle” sorusunun cevabı commit mesajında.

2. Code review context. Reviewer sadece diff’i değil, commit mesajını da okuyor. “Bu değişikliği neden yaptın” cevabı.

3. Release notes generation. Commit’lerden release notes auto-generate edilebiliyor.

4. Bisect debugging. git bisect ile bug’ın ne zaman girdiğini bulurken commit mesajları yol gösteriyor.

5. Yeni developer onboarding. Git log kod tabanının evolution hikayesi.

Kötü commit mesajları bu 5 fayda’yı kaybediyor.

Conventional commits format

En yaygın standart: Conventional Commits.

<type>(<scope>): <subject>

<body>

<footer>

Types:
feat: yeni feature
fix: bug fix
docs: documentation change
style: code style (whitespace, formatting, no logic change)
refactor: code restructure, no behavior change
perf: performance improvement
test: adding/updating tests
chore: maintenance task (dependency update, config)

Example:

feat(checkout): add Apple Pay option

Implement Apple Pay as alternative payment method alongside
credit card. Uses Stripe's PKPaymentRequest API.

Closes #234

Bu format machine-parseable. Changelog generation, semantic versioning automation.

Subject line rules

First line (subject) en kritik. Rules:

  1. Max 72 karakter. Git tool’ları bunu truncate ediyor.
  2. Imperative mood. “add feature” değil “added feature”.
  3. No period at end.
  4. Capitalize first letter after type. Actually lowercase is preferred in conventional commits.
  5. Concise but descriptive.

Good subjects:

feat(auth): add two-factor authentication
fix(api): prevent duplicate order creation on network retry
refactor(db): extract query builder into separate class
perf(list): memoize expensive filter computation

Bad subjects:

update  (ne update?)
fix bug  (hangi bug?)
wip  (kimin umrunda)
misc changes  (vague)

Body: why, not what

Body’de “ne değiştirdim” yazmak gereksiz. Diff zaten gösteriyor. Body “niye değiştirdim” için.

Bad body:

Changed line 45 in UserService.swift.
Updated the validation logic.
Added a new parameter.

Good body:

The existing validation allowed empty emails to pass through,
causing NULL values in the database. This led to the bug #412
where notification emails failed silently.

Now requires @ symbol and non-empty domain.

Body “why” + “impact” ile reviewer context kazanıyor.

Atomic commits

Bir commit tek bir logical change. Mixed commits disiplinsiz.

Bad (mixed):

feat: add user profile, fix login bug, update deps

Üç farklı thing tek commit’te. Revert zor (sadece login fix’i revert edilemiyor). Review zor.

Good (atomic):

commit 1: feat(profile): add user profile page
commit 2: fix(auth): prevent login loop after token expiry
commit 3: chore(deps): update lodash to 4.17.21

Üç ayrı commit. Her biri self-contained, revertable, reviewable.

Branch naming

Commit disciplin branch naming ile birlikte:

feature/checkout-apple-pay
bugfix/email-validation-nil-check
hotfix/payment-timeout
chore/update-firebase-sdk

Branch tipi prefix, kebab-case descriptive name. GitHub/GitLab issue integration için issue number ekle:

feature/234-apple-pay-checkout

Amend ve squash

git commit --amend son commit’i düzeltmek için. Mesaj typo, forgotten file.

git rebase -i HEAD~5 multiple commits’i interactive olarak düzenle:
– reword: commit mesajı değiştir
– squash: multiple commits’i birleştir
– fixup: squash ama mesajı atla
– drop: commit’i sil

Squash kullanım senaryosu: PR review sırasında 5 commit’le “fix typo”, “fix another typo”, “actually fix” gibi commitler birikti. Merge öncesi squash:

git rebase -i main
# "squash" marker ile birleştir

Result: tek clean commit PR merge’de.

Git hook’larıyla enforce

Team disciplin için git hook’lar:

commit-msg hook: Commit mesajı format’ı check ediyor.

#!/bin/sh
# .git/hooks/commit-msg

commit_regex='^(feat|fix|docs|style|refactor|perf|test|chore)(\([a-z-]+\))?: .{1,72}'

if ! grep -qE "$commit_regex" "$1"; then
    echo "Commit message format invalid."
    echo "Format: type(scope): subject"
    exit 1
fi

Husky (Node.js projects) veya pre-commit (Python) gibi tool’lar hook management’ı kolaylaştırıyor.

Team onboarding

Yeni developer’a commit discipline açıklamak:

  1. README’de commit convention. Link: Conventional Commits spec.
  2. PR template. Body’de “How should reviewer judge this?” sorusu.
  3. Pair commit writing. İlk hafta senior review commit messages.
  4. Reject PR with bad commits. “Please squash into meaningful commits” feedback.

3-4 hafta sonra pattern internalize oluyor.

Multi-commit PR vs single-commit

PR approach:

Option A: One commit per PR. PR merge’de squash. Final history clean.

Option B: Multi-commit PR. Her commit mantıklı unit. Merge commit veya rebase merge.

Ben Option B tercih ediyorum büyük PR’larda. 5-10 commit logical breakdown easier to review. Small PR’larda (100 satır altı) Option A OK.

Tools: git log visualization

Git log’u okumanın yolları:

git log --oneline
git log --graph --oneline --all
git log --pretty=format:'%h %s (%an)' --abbrev-commit

Visual tool’lar: GitLens (VS Code), Fork, Tower. Commit history’yi visualize.

Sonuç

Commit discipline uzun vadede team productivity’sinin core’u. İlk başta “fazla disciplin” gibi görünüyor, 6 ay sonra code archaeology yaparken değeri anlaşılıyor.

Conventional Commits + atomic commits + meaningful subject/body. Hook’larla enforce, PR review’da enforce, onboarding’de öğret. 1 ay disciplin’den sonra herkes için natural hale geliyor.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç