Git di Claude Code: Commit, PR, dan Aturan Push yang Aman
Alur git Claude Code yang menjaga main bersih: atribusi commit dan PR, feature branch, serta aturan deny atau hook yang menahan git push dan force-push.
Oleh Matthews WongDitinjau pada Dicek dengan Claude Code v2.1.301
Poin utama
Claude Code bisa membuat commit dan membuka pull request untuk Anda, dan secara default menambahkan trailer Co-Authored-By di commit serta baris generated-with di deskripsi PR. Untuk menjaga main tetap bersih, kerjakan di feature branch. Agar aturan benar-benar berlaku, tegakkan: baris CLAUDE.md hanyalah permintaan, sedangkan aturan deny atau hook PreToolUse diperiksa oleh Claude Code sendiri.
Setelah pelajaran ini, Anda bisa
- Menyebutkan apa yang ditambahkan Claude Code ke commit dan PR, lalu mengubah atau menyembunyikannya.
- Menjaga main tetap bersih dengan feature branch dan merge yang direview manusia.
- Memilih antara baris CLAUDE.md, aturan deny, dan hook untuk menahan sebuah push.
Ikuti diagramnya langkah demi langkah
Tekan Putar, atau melangkah dengan panah. Setiap langkah juga ditulis di bawah diagram.
Di mana git push ditahan
Aturan deny memblokir git push origin main berdasarkan teksnya tetapi melewatkan git -C . push; hook PreToolUse membaca seluruh perintah dan keluar dengan exit 2; push dari feature branch lolos; baris CLAUDE.md hanya meminta.
Ditinjau pada 17 Oktober 2026 · Claude Code v2.1.301
Tombol: ← → langkah · Home / End · K putar atau jeda
Claude menjalankan git lewat tool Bash. Setiap panggilan diperiksa dulu oleh hook, lalu aturan izin. CLAUDE.md berdiri sendiri: ia konteks yang dibaca Claude, bukan sesuatu yang diperiksa Claude Code.
Claude menjalankan git push origin main. Teksnya cocok dengan aturan deny Bash(git push *), jadi Claude Code menolak panggilan itu sebelum berjalan, apa pun isi CLAUDE.md.
"deny": ["Bash(git push *)"]Tebak langkah berikutnya Claude mencoba lagi dengan git -C . push origin main. Apakah aturan deny yang sama menahannya? (Ya, tetap sebuah git push · Tidak, teksnya berbeda, jadi aturan itu melewatkannya)Aturan Bash mencocokkan teks perintah yang ditulis Claude. git -C . push tidak cocok dengan Bash(git push *), jadi aturan lain dan mode izin yang menentukan. Aturan deny bukan batas keamanan.
git -C . push origin mainHook PreToolUse menerima perintah lengkap sebagai JSON. Exit 2 menghentikan panggilan sebelum aturan izin dievaluasi, jadi blokir tetap berlaku walau aturan allow mengizinkan push itu.
echo "Blocked: no pushes from main" >&2 exit 2Tebak langkah berikutnya Sekarang Claude mem-push dari sebuah feature branch. Apa yang dilakukan hook yang sama? (Memblokirnya, karena setiap push mencurigakan · Keluar dengan exit 0 dan meloloskannya)Dari feature branch, hook keluar dengan exit 0 dan tidak ada aturan yang cocok, jadi push berjalan. Review terjadi di PR; workflow deploy repo ini berjalan saat push ke main, jadi merge adalah rilisnya.
Baris CLAUDE.md memengaruhi apa yang dicoba Claude, tetapi Claude Code tidak memeriksanya. Untuk aturan yang harus selalu berlaku, pakai aturan deny untuk bentuk umum dan hook untuk sisanya.
Apa yang ditambahkan Claude Code ke commit dan pull request?
Anda bisa meminta Claude membuat commit atau membuka pull request: dokumentasi menunjukkan cara langsung memintanya, misalnya create a pr for my changes. Claude Code memuat instruksi alur commit dan pull request bawaan di konteksnya, dan pengaturan includeGitInstructions, bernilai true secara default, mengendalikannya. Ubah ke false hanya kalau Anda membawa skill alur git sendiri. Apa pun yang disusun Claude, baca dulu PR-nya sebelum dikirim; dokumentasi menyarankan untuk mereviu dan meminta Claude menyorot risikonya.
Baca selengkapnya (2)Tutup
Secara default, commit mendapat git trailer, Co-Authored-By dengan nama model, dan deskripsi PR mendapat baris generated-with biasa. Pengaturan attribution mengubah keduanya: attribution.commit dan attribution.pr menerima teks Anda sendiri, string kosong menyembunyikan bagian itu, dan attribution bernilai false menyembunyikan semuanya. Nilai false butuh Claude Code v2.1.281 atau lebih baru; versi lama menolaknya dan melewati seluruh file settings yang memuatnya. Key lama includeCoAuthoredBy sudah deprecated, dan begitu commit atau pr diatur, Claude Code mengabaikannya.
Claude Code menautkan sesi ke PR ketika Claude membuatnya dengan gh pr create atau glab mr create. Kemudian, claude --from-pr diikuti nomor PR membuka pemilih sesi yang difilter ke PR itu. Itulah jalan kembali ketika reviewer bertanya mengapa sebuah perubahan dibuat.
Bagaimana menjaga main tetap bersih saat Claude menulis commit?
Beri setiap tugas branch-nya sendiri dan biarkan pull request menjadi gerbangnya. Claude commit di feature branch, Anda mereviu diff-nya, dan hanya merge yang menyentuh main. Di repo seperti ini hal itu bukan basa-basi: workflow deploy berjalan pada setiap push ke main, jadi push ke sana adalah rilis, bukan titik simpan.
Baca selengkapnya (2)Tutup
Git worktree berguna saat dua tugas berjalan bersamaan. claude --worktree feature-auth memulai sesi di checkout terpisah pada branch-nya sendiri, dibuat dari commit yang sudah ada, jadi repositori butuh minimal satu commit lebih dulu. Jalankan perintah yang sama dengan nama lain di terminal kedua dan kedua sesi tidak bisa saling menimpa file. Pelajaran worktree membahas kerja paralel secara lengkap; di sini intinya adalah branch-nya dibuatkan untuk Anda.
Git biasa tetap menjadi pengaman di balik layar. Kalau sebuah commit salah, pelajaran rewind membahas cara membatalkan edit Claude, dan revert di branch tidak berbiaya apa-apa. Force-push ke branch bersama adalah satu-satunya langkah yang tidak bisa dibatalkan dengan membaca log, karena itu ia pantas diberi aturan, bukan sekadar janji.
Sebaiknya meminta di CLAUDE.md, menambah aturan deny, atau menulis hook?
Pakai ketiganya untuk hal yang menjadi keunggulan masing-masing. Dokumentasi menyatakannya terang-terangan: aturan izin ditegakkan oleh Claude Code, bukan oleh model, sedangkan instruksi di prompt atau CLAUDE.md memengaruhi apa yang dicoba Claude tetapi tidak mengubah apa yang diizinkan Claude Code. Jadi baris seperti never force-push cocok sebagai perilaku default, tetapi lemah sebagai pengaman.
Baca selengkapnya (3)Tutup
Aturan izin adalah gerbang yang murah dan mudah dibaca. Aturan diperiksa deny dulu, lalu ask, lalu allow, dan kecocokan pertama menang, jadi tidak ada aturan allow yang bisa membuat pengecualian dari sebuah deny. Contoh di dokumentasi mengizinkan Bash(git commit *) dan menolak Bash(git push *). Pasang aturan ask pada Bash(git push *) kalau Anda ingin pertanyaan, bukan penolakan. Letakkan bintang setelah subcommand: Bash(git *) akan mengizinkan semua perintah git.
Namun aturan Bash mencocokkan teks, dan dokumentasi mendaftar apa yang terlewat: git -C . push origin main, git -c push.default=current push origin main, dan git 'push' origin main semuanya lolos dari Bash(git push *). Kalau aturan itu harus berlaku, tambahkan hook PreToolUse. Hook menerima perintah sebagai JSON, keluar dengan exit 2 untuk memblokir, dan blokirnya berlaku bahkan ketika aturan allow akan mengizinkan panggilan itu. Hook juga bisa melihat hal yang tidak bisa dilihat aturan, seperti branch yang sedang Anda pakai. Uji dengan mengirim contoh JSON lewat pipe sebelum Anda mempercayainya.
Satu mode butuh peringatan. Pada mode bypassPermissions, Claude Code melewati prompt izin, dan dokumentasi menyatakan mode itu hanya untuk lingkungan terisolasi seperti container atau VM. Kalau Anda tidak berada di sana, biarkan mode itu mati dan biarkan prompt menjalankan tugasnya.
Konfigurasi nyata di balik pelajaran ini
Kutipan dari repositori yang membangun dan men-deploy situs ini, apa adanya.
**Always run `npx tsc --noEmit && npm run build` before pushing.** The build runs `assertBlogParity()` from `lib/blog-meta.ts` which fails if a blog post is registered in `BLOG_POSTS_STATIC` but missing from `BLOG_META` (or vice versa).Satu-satunya aturan repo ini soal push, dan bentuknya permintaan. Claude membacanya dan biasanya mengikutinya, tetapi tidak ada yang di Claude Code memeriksa bahwa build sudah dijalankan. Aturan ini cukup karena kegagalan yang dijaganya juga tertangkap oleh build itu sendiri, sehingga ini pemakaian CLAUDE.md yang baik: panduan dengan lapisan pertahanan kedua di belakangnya.
on:
push:
branches: [main]
workflow_dispatch:Alasan main layak dijaga di sini. Workflow berjalan pada setiap push ke main, membangun image, lalu men-deploy-nya, jadi push ke main adalah rilis. Menjaga pekerjaan Claude di feature branch dan menggabungkannya lewat pull request menaruh keputusan manusia di depan pemicu itu.
{
"hooks": {
"PostToolUse": [Apa yang tidak dimiliki repo ini. File settings bersama hanya berisi satu hook PostToolUse untuk gambar blog dan tidak punya key permissions, jadi tidak ada aturan atau hook di sini yang menahan git push atau force-push. Perlindungan saat ini adalah kebiasaan ditambah CI. Latihan di bawah menunjukkan wujudnya kalau ditambahkan, ditulis sebagai hook PreToolUse di samping hook ini.
Kesalahan yang benar-benar membuang waktu
Aturan deny yang hanya cocok dengan satu penulisan
Bash(git push *) menahan git push origin main tetapi tidak git -C . push origin main atau git 'push' origin main. Dokumentasi menyebut aturan deny sebagai penutup untuk bentuk yang biasa ditulis Claude, bukan batas keamanan. Tambahkan hook yang memeriksa seluruh perintah, dan pakai sandbox bila Anda butuh penegakan yang tidak bergantung pada teks perintah.
Hook yang keluar dengan exit 1, bukan 2
Hanya exit 2 yang memblokir panggilan PreToolUse. Exit 1 adalah non-blocking error, jadi push tetap jalan padahal skripnya tampak menolak. Uji hook dengan mengirim contoh JSON lewat pipe lalu mencetak exit code-nya, seperti di latihan.
Mengandalkan baris CLAUDE.md agar berlaku
Never push to main di CLAUDE.md adalah permintaan, dan Claude Code tidak memeriksanya. Kalau kesalahannya mahal, dukung kalimat itu dengan aturan atau hook. Kalau murah diperbaiki, kalimat saja sudah cukup.
Hook yang tidak bisa membedakan branch dari kata biasa
Hook contoh mencocokkan teks git lalu push, jadi pesan commit yang kebetulan memuat kata push bisa memicunya. Hook juga memblokir setiap push dari main, termasuk yang Anda inginkan. Persempit polanya sebelum memperluas kepercayaan, dan baca alasan blokir yang diterima Claude.
Nilai attribution yang ditolak CLI lama
attribution bernilai false butuh Claude Code v2.1.281 atau lebih baru. Versi lama menolaknya dan melewati seluruh file settings yang memuatnya, sehingga semua aturan lain di file itu diam-diam berhenti berlaku. Periksa versinya dengan claude --version sebelum tim memakainya.
| Cara | Siapa yang memeriksa | Apa yang bisa terlewat |
|---|---|---|
| Satu baris di CLAUDE.md | Claude, atas kemauannya | Apa pun yang terlewat oleh Claude |
| Aturan deny | Claude Code, pada teks perintah | Penulisan lain dari push yang sama |
| Hook PreToolUse | Skrip Anda, pada perintah lengkap | Apa pun yang tidak dicari skrip Anda |
Lakukan di komputer Anda sendiri
Anda butuh Claude Code, jq, dan satu repositori git untuk latihan. Tambahkan aturan deny untuk bentuk umum dan hook untuk sisanya, lalu buktikan keduanya bekerja sebelum Claude menyentuhnya.
Izinkan commit, tanya dulu sebelum push, dan belum menolak apa pun, di .claude/settings.json. Letakkan bintang setelah subcommand.
{ "permissions": { "allow": ["Bash(git commit *)"], "ask": ["Bash(git push *)"] } }Simpan penjaganya sebagai .claude/hooks/git-push-guard.sh. Skrip ini keluar dengan exit 2 saat push dijalankan dari main, atau saat perintah membawa flag force.
#!/bin/bash COMMAND=$(jq -r '.tool_input.command // empty') if echo "$COMMAND" | grep -Eq '(^|[;&|] *)git( .*)? push( |$)'; then BRANCH=$(git branch --show-current) if [[ "$BRANCH" == "main" || "$COMMAND" =~ (--force|[[:space:]]-f([[:space:]]|$)) ]]; then echo "Blocked: no pushes from main and no force pushes. Use a feature branch." >&2 exit 2 fi fi exit 0Jadikan executable lalu daftarkan sebagai hook PreToolUse untuk Bash, di samping hook yang sudah Anda miliki.
chmod +x .claude/hooks/git-push-guard.sh "PreToolUse": [ { "matcher": "Bash", "hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/git-push-guard.sh" }] } ]Ujilah secara manual, di main dan di feature branch. Main dan dua penulisan ganjil harus mencetak exit 2; push dari feature branch harus mencetak exit 0.
echo '{"tool_input":{"command":"git -C . push"}}' | .claude/hooks/git-push-guard.sh echo "exit $?" git switch -c feature/try-hook echo '{"tool_input":{"command":"git push -u origin feature/try-hook"}}' | .claude/hooks/git-push-guard.sh echo "exit $?"Minta Claude membuat commit kecil lalu mem-push-nya. Periksa bahwa commit membawa trailer, lalu sembunyikan dengan attribution bernilai false setelah CLI Anda v2.1.281 atau lebih baru, dan commit lagi.
claude --version git log -1 --format=%B { "attribution": false }
Tiga pertanyaan sebelum lanjut
Pilih jawaban untuk melihat kenapa benar atau salah. Tidak ada yang disimpan atau dinilai, jadi tebak saja dengan bebas.
Jawab dalam hati, lalu cek
1.Mengapa repo ini menjauhkan pekerjaan Claude dari main?Lihat jawabannya
Jawaban:Workflow deploy-nya berjalan pada setiap push ke main, jadi push ke sana adalah rilis. Feature branch dan pull request yang direview menaruh keputusan manusia di depannya.
2.Sebuah hook dan sebuah aturan allow berselisih soal satu push. Mana yang menang?Lihat jawabannya
Jawaban:Hook, kalau ia exit 2. Hook yang memblokir menghentikan panggilan sebelum aturan izin dievaluasi, jadi blokir berlaku walau aturan allow akan mengizinkannya. Aturan deny sendiri diperiksa sebelum ask dan allow.
3.Bagaimana menemukan sesi Claude di balik sebuah pull request nanti?Lihat jawabannya
Jawaban:Jalankan claude --from-pr dengan nomor PR, atau tempel URL PR ke pemilih resume. Claude Code menautkan sesi ketika Claude membuat PR dengan gh pr create atau glab mr create.
Bahasan mendalam terkait di situs ini
Sumber
Sumber primer yang diperiksa pada tanggal riset. Ikuti tautannya untuk versi terbaru.