Git worktree adalah fitur yang sangat berguna ketika kamu perlu bekerja di beberapa branch sekaligus tanpa harus melakukan clone berulang. Namun, fitur ini membawa konsekuensi: branch yang terikat ke sebuah worktree tidak bisa dihapus sembarangan. Ketika kamu mencoba menghapus branch tersebut, Git akan menolak dan melempar error yang cukup spesifik. Artikel ini akan membahas error tersebut secara tuntas—mulai dari memahami pesannya, mengenali penyebabnya, menyelesaikannya langkah demi langkah, hingga mencegahnya terulang di kemudian hari.


Pesan error & artinya

Ketika kamu mencoba menghapus sebuah branch yang sedang digunakan oleh sebuah worktree, Git akan mengeluarkan pesan error berikut secara verbatim:

error: cannot delete branch 'nama-branch' used by worktree at '/path/to/worktree'

Pesan ini muncul ketika kamu menjalankan perintah seperti git branch -d nama-branch atau git branch -D nama-branch. Bahkan flag -D (force delete) tidak akan bisa menghapus branch ini karena Git secara eksplisit melarang penghapusan branch yang masih menjadi branch aktif di salah satu worktree.

Dalam bahasa Indonesia, pesan ini berarti: "Tidak dapat menghapus branch 'nama-branch' karena branch tersebut masih digunakan oleh worktree yang berlokasi di '/path/to/worktree'." Sederhananya, Git sedang melindungi kamu dari aksi yang bisa merusak konsistensi repository. Branch yang masih dipakai oleh sebuah worktree memiliki HEAD yang menunjuk ke commit tertentu di branch tersebut. Jika branch dihapus, worktree yang mengacunya akan kehilangan posisi HEAD-nya—sebuah kondisi yang disebut dangling HEAD dan bisa membuat worktree berada dalam keadaan broken atau corrupt.

Kenapa error ini muncul? Jawabannya ada di mekanisme internal Git. Setiap worktree menyimpan referensi ke branch yang di-checkout di dalam direktori .git/worktrees/. File HEAD di dalam direktori tersebut berisi nama branch yang sedang aktif. Ketika kamu meminta Git menghapus branch, Git akan memeriksa semua worktree yang terdaftar. Jika ada salah satu worktree yang HEAD-nya menunjuk ke branch yang ingin dihapus, Git akan memblokir aksi tersebut. Ini adalah mekanisme proteksi bawaan yang tidak bisa di-bypass dengan flag apapun, termasuk -D atau --force.

Perhatikan contoh skenario berikut. Kamu membuat worktree baru untuk mengerjakan fitur tertentu:

git worktree add ../fitur-auth fitur-auth

Perintah di atas membuat direktori baru ../fitur-auth yang berisi working tree untuk branch fitur-auth. Setelah selesai bekerja, kamu kembali ke worktree utama dan mencoba menghapus branch tersebut:

git branch -d fitur-auth

Maka Git akan merespons dengan:

error: cannot delete branch 'fitur-auth' used by worktree at '../fitur-auth'

Ini terjadi karena worktree di ../fitur-auth masih ada dan branch fitur-auth masih menjadi branch aktif di sana. Git tidak akan mengizinkan penghapusan sampai keterikatan antara worktree dan branch tersebut diputus terlebih dahulu.

Poin penting yang perlu dipahami: error ini bukan bug, melainkan fitur keamanan Git. Tanpa proteksi ini, kamu bisa secara tidak sengaja menghapus branch yang masih menjadi fondasi bagi worktree lain, yang akan mengakibatkan worktree tersebut tidak bisa melakukan operasi Git apapun dengan benar—bahkan git status bisa gagal dijalankan.


Penyebab umum

Error ini selalu berakar pada satu kondisi fundamental: adanya worktree yang masih terikat ke branch yang ingin dihapus. Namun, dalam praktiknya, ada beberapa skenario yang menyebabkan kondisi tersebut terjadi. Berikut penyebab-penyebab umumnya, diurutkan dari yang paling sering ditemui di lapangan:

1. Lupa menghapus worktree sebelum menghapus branch. Ini adalah penyebab paling sering, terutama di kalangan developer yang baru mulai menggunakan fitur worktree. Alur kerja yang umum adalah: membuat worktree untuk branch fitur, bekerja di sana, lalu kembali ke worktree utama dan langsung mencoba menghapus branch. Langkah krusial yang terlewat adalah menghapus (prune) worktree tersebut terlebih dahulu. Tanpa langkah itu, worktree tetap terdaftar di Git dan branch tetap terikat.

2. Worktree yang sudah dihapus dari filesystem tapi belum di-remove dari catatan Git. Ini terjadi ketika kamu menghapus direktori worktree secara manual menggunakan file explorer, rm -rf, atau cara lain di luar perintah git worktree remove. Ketika direktori dihapus secara manual, Git tidak mendapatkan notifikasi bahwa worktree tersebut sudah tidak ada. Referensi worktree tetap tersimpan di .git/worktrees/, dan Git masih menganggap branch tersebut sedang digunakan. Ini adalah kondisi yang cukup membingungkan karena secara fisik worktree sudah tidak terlihat, tapi secara logis masih ada.

3. Terdapat worktree yang terdampak (stale) setelah operasi yang tidak sempurna. Misalnya, proses git worktree add terinterupsi di tengah jalan, atau ada crash saat operasi Git sedang berlangsung. Dalam kasus ini, Git bisa meninggalkan entri worktree yang tidak valid tapi masih tercatat. Branch yang terkait dengan worktree stale ini tidak bisa dihapus sampai entri stale tersebut dibersihkan.

4. Menggunakan script atau CI/CD pipeline yang tidak mengelola worktree secara lengkap. Dalam environment otomatis, script bisa membuat worktree untuk menjalankan tugas tertentu (misalnya build atau test di branch tertentu) tapi lupa membersihkan worktree setelah selesai. Ketika pipeline berjalan kembali dan mencoba menghapus branch lama, error ini muncul.

5. Ada beberapa worktree yang menggunakan branch yang sama (meskipun jarang). Secara teknis, satu branch bisa menjadi target checkout di lebih dari satu worktree. Jika kamu membuat worktree dengan git worktree add --detach lalu secara manual mengatur HEAD-nya ke branch tertentu, kondisi ini bisa terjadi dan membuat branch lebih sulit dihapus karena harus melepaskan ikatan dari beberapa worktree sekaligus.

Untuk memastikan penyebab mana yang sedang kamu alami, jalankan perintah berikut:

git worktree list

Outputnya akan menampilkan semua worktree yang terdaftar, lengkap dengan lokasi path dan branch yang di-checkout di masing-masing worktree. Contoh output:

/home/user/projek         abc1234 [main]
/home/user/fitur-auth     def5678 [fitur-auth]
/home/user/fitur-payment  ghi9012 [fitur-payment]

Dari output ini, kamu bisa langsung melihat branch mana yang terikat ke worktree mana. Jika kamu melihat worktree yang path-nya sudah tidak ada di filesystem (kamu sudah menghapus foldernya secara manual), maka penyebabnya adalah nomor 2. Jika semua path masih ada dan branch yang ingin dihapus memang masih terdaftar, maka penyebabnya adalah nomor 1. Jika kamu melihat entri worktree yang aneh atau tidak valid, bisa jadi penyebabnya nomor 3.

Untuk pengecekan lebih lanjut terhadap worktree yang sudah tidak memiliki direktori fisik (stale), gunakan:

git worktree list --verbose

Atau cek secara manual apakah path yang terdaftar masih ada:

ls -la /home/user/fitur-auth

Jika direktori tidak ditemukan tapi masih muncul di git worktree list, kamu sudah menghapusnya secara manual dan perlu menjalankan git worktree prune.


Solusi step-by-step

Bagian ini membahas tiga solusi utama: solusi langsung untuk mengatasi error saat ini, solusi berdasarkan root cause untuk memperbaiki sumber masalah, dan fix permanen agar masalah serupa tidak muncul lagi. Setiap langkah disertai perintah yang bisa di-copy-paste dan output yang diharapkan.

Solusi Langsung: Hapus Worktree Terlebih Dahulu

Langkah paling straightforward adalah menghapus worktree yang mengikat branch, baru kemudian menghapus branch-nya.

Langkah 1 — Identifikasi worktree yang mengikat branch:

git worktree list

Output yang diharapkan:

/home/user/projek         abc1234 [main]
/home/user/fitur-auth     def5678 [fitur-auth]

Dari sini kamu tahu bahwa branch fitur-auth digunakan oleh worktree di /home/user/fitur-auth.

Langkah 2 — Hapus worktree:

git worktree remove /home/user/fitur-auth

Output yang diharapkan:

( tidak ada output jika berhasil — command berjalan tanpa error )

Jika worktree memiliki perubahan yang belum di-commit, Git akan menolak penghapusan. Dalam kasus itu, kamu punya dua opsi: commit atau stash perubahan terlebih dahulu, atau gunakan flag --force:

git worktree remove --force /home/user/fitur-auth

Langkah 3 — Hapus branch:

git branch -d fitur-auth

Output yang diharapkan:

Deleted branch fitur-auth (was def5678).

Langkah 4 — Verifikasi:

git branch

Pastikan branch fitur-auth tidak lagi muncul dalam daftar. Juga verifikasi bahwa worktree sudah hilang:

git worktree list

Output seharusnya hanya menampilkan worktree utama:

/home/user/projek  abc1234 [main]

Root Cause Fix: Worktree yang Sudah Dihapus Manual dari Filesystem

Jika kamu sudah menghapus direktori worktree menggunakan rm -rf atau file explorer, perintah git worktree remove akan gagal karena direktori sudah tidak ada:

git worktree remove /home/user/fitur-auth

Output error:

fatal: '/home/user/fitur-auth' is not a working tree

Dalam kasus ini, kamu perlu menggunakan git worktree prune untuk membersihkan entri worktree yang sudah tidak memiliki direktori fisik:

Langkah 1 — Prune worktree stale:

git worktree prune

Perintah ini tidak menghasilkan output jika berhasil, tapi efeknya bisa diverifikasi.

Langkah 2 — Verifikasi bahwa entri sudah dibersihkan:

git worktree list

Worktree yang direktorinya sudah dihapus seharusnya tidak lagi muncul.

Langkah 3 — Hapus branch:

git branch -d fitur-auth

Output:

Deleted branch fitur-auth (was def5678).

Fix Permanen: Pastikan Cleanup Selalu Dilakukan

Untuk memastikan masalah ini tidak terulang, buat sebuah fungsi shell yang menghapus worktree dan branch sekaligus:

# Tambahkan ke ~/.bashrc atau ~/.zshrc
git-worktree-cleanup() {
    local branch="$1"
    local worktree_path

    if [ -z "$branch" ]; then
        echo "Usage: git-worktree-cleanup <branch-name>"
        return 1
    fi

    # Cari worktree yang menggunakan branch ini
    worktree_path=$(git worktree list --porcelain | grep -A1 "branch refs/heads/${branch}" | head -1 | sed 's/worktree //')

    if [ -n "$worktree_path" ]; then
        echo "Removing worktree at: $worktree_path"
        git worktree remove "$worktree_path" --force
    fi

    # Prune worktree stale
    git worktree prune

    # Hapus branch
    echo "Deleting branch: $branch"
    git branch -D "$branch"
}

Penggunaan:

git-worktree-cleanup fitur-auth

Dengan fungsi ini, seluruh proses cleanup—mulai dari menghapus worktree, membersihkan entri stale, hingga menghapus branch—dilakukan dalam satu perintah yang aman dan konsisten.


Supaya tidak terulang

Mencegah error ini terulang membutuhkan kombinasi antara konfigurasi Git yang tepat, best practice dalam alur kerja, dan kesadaran akan perbedaan perilaku di berbagai sistem operasi. Bagian ini membahas ketiga aspek tersebut secara mendalam.

Konfigurasi yang Mencegah Error Kembali

Git memiliki beberapa konfigurasi yang bisa membantu menjaga kebersihan worktree dan mencegah kondisi yang memicu error ini. Pertama, aktifkan pruning otomatis. Secara default, Git menjalankan git worktree prune secara implisit pada beberapa operasi seperti git worktree add, tapi tidak pada semua operasi. Kamu bisa memastikan pruning selalu dilakukan dengan membuat Git alias:

git config --global alias.cocheckout '!git worktree prune && git checkout'

Alias ini memastikan bahwa setiap kali kamu berpindah branch, entri worktree yang stale akan dibersihkan terlebih dahulu.

Konfigurasi kedua yang berguna adalah membuat Git selalu menampilkan informasi worktree saat menjalankan git status atau git branch. Meskipun tidak ada konfigurasi bawaan untuk ini, kamu bisa membuat alias yang menampilkan informasi tambahan:

git config --global alias.branches '!git worktree list && echo "---" && git branch'

Dengan alias ini, setiap kali kamu menjalankan git branches, kamu akan melihat daftar worktree dan daftar branch secara berurutan, sehingga lebih mudah melihat keterikatan antara keduanya sebelum menghapus branch apapun.

Best Practice

Selalu hapus worktree sebelum menghapus branch. Ini adalah aturan emas yang paling fundamental. Urutan operasi yang benar adalah: (1) selesaikan pekerjaan di branch, (2) merge atau rebase branch tersebut ke branch target, (3) hapus worktree dengan git worktree remove, (4) baru hapus branch dengan git branch -d. Jangan pernah membalik urutan langkah 3 dan 4.

Jangan pernah menghapus direktori worktree secara manual. Selalu gunakan git worktree remove untuk menghapus worktree. Menghapus direktori menggunakan rm -rf atau file explorer akan meninggalkan entri stale di .git/worktrees/ yang intinya menyebabkan error ini. Jika kamu sudah secara tidak sengaja menghapus direktori secara manual, segera jalankan git worktree prune untuk membersihkan entri yang tersisa.

Buatlah script cleanup sebagai bagian dari workflow. Dalam proyek yang menggunakan worktree secara intensif, buatlah script yang otomatis membersihkan worktree dan branch yang sudah di-merge. Contoh script:

#!/bin/bash
# cleanup-merged.sh — hapus worktree dan branch yang sudah di-merge ke main

TARGET_BRANCH="main"

# Daftar branch yang sudah di-merge, kecuali main itu sendiri
MERGED_BRANCHES=$(git branch --merged "$TARGET_BRANCH" | grep -v "^\*\|$TARGET_BRANCH" | sed 's/^ *//')

For branch in $MERGED_BRANCHES; do
    echo "Processing branch: $branch"

    # Cari dan hapus worktree yang menggunakan branch ini
    WORKTREE_PATH=$(git worktree list --porcelain | grep -A1 "branch refs/heads/${branch}" | head -1 | sed 's/worktree //')

    if [ -n "$WORKTREE_PATH" ]; then
        echo "  Removing worktree: $WORKTREE_PATH"
        git worktree remove --force "$WORKTREE_PATH"
    fi

    # Hapus branch
    echo "  Deleting branch: $branch"
    git branch -d "$branch"
done

# Prune sisa entri stale
git worktree prune
echo "Cleanup complete."

Script ini bisa dijalankan secara berkala atau di-integrasi ke dalam CI/CD pipeline sebagai post-build step.

Gunakan konvensi penamaan worktree yang konsisten. Misalnya, selalu buat worktree di direktori yang namanya sama dengan branch-nya, dan simpan di lokasi yang terprediksi (misalnya ../worktrees/<branch-name>). Ini memudahkan identifikasi dan cleanup.

Perbedaan OS

Ada beberapa perbedaan penting antar sistem operasi yang perlu diperhatikan.

Di Linux dan macOS, path worktree menggunakan format POSIX dan git worktree list akan menampilkan path dalam format yang bisa langsung digunakan di terminal. Perintah rm -rf tersedia dan bisa digunakan untuk menghapus direktori (meskipun, sekali lagi, ini bukan cara yang disarankan). Pruning bekerja tanpa masalah.

Di Windows, ada beberapa quirks yang perlu diperhatikan. Pertama, path menggunakan backslash dan bisa menyertakan drive letter (misalnya C:\Users\...). Git di Windows (baik Git Bash maupun Git melalui PowerShell) umumnya menangani path dengan baik, tapi ada kasus di mana path yang ditampilkan oleh git worktree list menggunakan format yang berbeda dari yang diharapkan shell. Kedua, Windows memiliki file locking yang lebih agresif—jika ada proses yang masih mengakses file di dalam worktree (misalnya IDE atau process build), penghapusan worktree bisa gagal dengan pesan "directory not empty" atau semacamnya. Dalam kasus ini, tutup semua proses yang mengakses direktori tersebut sebelum menjalankan git worktree remove.

Contoh di Windows (PowerShell):

# List worktree
git worktree list

# Hapus worktree — perhatikan path format Windows
git worktree remove "C:\Users\developer\worktrees\fitur-auth"

# Jika gagal karena file terkunci, tutup IDE/process dulu, lalu:
git worktree remove --force "C:\Users\developer\worktrees\fitur-auth"

Di WSL (Windows Subsystem for Linux), path bisa menjadi sumber kebingungan karena filesystem Windows dan Linux di-mount secara berbeda. Jika kamu membuat worktree dari Git yang berjalan di WSL, path akan menggunakan format Linux (/mnt/c/...), dan worktree harus dikelola dari dalam WSL juga. Jangan mencampur operasi Git antara WSL dan Windows untuk repository yang sama, karena bisa menyebabkan inkonsistensi yang sulit di-debug.


Langkah lanjutan

Kadang-kadang, solusi standar yang dibahas di atas tidak langsung berhasil. Bagian ini membahas apa yang harus dilakukan ketika solusi dasar gagal, cara membaca log untuk mendapatkan informasi lebih, dan sumber resmi untuk deep-dive lebih lanjut.

Kalau Solusi di Atas Tidak Work

Kasus 1: git worktree remove gagal dengan pesan "failed to delete"

Ini biasanya disebabkan oleh file yang masih terkunci oleh proses lain (umum di Windows) atau permission issue (umum di Linux/macOS). Solusinya:

# Di Linux/macOS: cek proses yang mengakses direktori
lsof +D /path/to/worktree

# Kill proses yang mengunci, lalu coba lagi
git worktree remove --force /path/to/worktree

# Jika masih gagal, hapus secara manual lalu prune
rm -rf /path/to/worktree
git worktree prune

Kasus 2: git worktree prune tidak menghapus entri stale

Ini bisa terjadi jika Git menganggap direktori worktree masih ada (misalnya karena ada mount point atau symlink). Dalam kasus ini, kamu bisa secara manual menghapus entri worktree dari .git/worktrees/:

# Lihat entri worktree yang terdaftar
ls -la .git/worktrees/

# Hapus entri yang bermasalah secara manual
rm -rf .git/worktrees/fitur-auth

# Verifikasi
git worktree list

Kasus 3: Branch tetap tidak bisa dihapus meskipun worktree sudah di-remove

Ini bisa terjadi jika ada lebih dari satu worktree yang menggunakan branch yang sama. Periksa kembali dengan git worktree list dan pastikan tidak ada entri lain yang mengikat branch tersebut. Juga periksa apakah branch tersebut adalah branch aktif di worktree saat ini (HEAD). Kamu tidak bisa menghapus branch yang sedang di-checkout—harus pindah ke branch lain dulu:

git checkout main
git branch -d fitur-auth

Kasus 4: Repository dalam keadaan corrupt

Dalam kasus yang sangat jarang, file-file di .git/worktrees/ bisa menjadi corrupt, menyebabkan Git tidak bisa mengenumerasi worktree dengan benar. Solusi yang lebih agresif:

# Backup dulu
cp -r .git/worktrees .git/worktrees.backup

# Hapus semua entri worktree
rm -rf .git/worktrees/*

# Prune untuk membersihkan
git worktree prune

# Restore jika diperlukan — tapi biasanya tidak perlu
# Hanya lakukan ini jika kamu masih memiliki direktori worktree yang aktif

Cara Baca Log

Git tidak menyimpan log operasi worktree secara default, tapi kamu bisa mendapatkan informasi dari beberapa sumber:

Git reflog bisa menunjukkan riwayat operasi yang pernah dilakukan:

git reflog

Ini menunjukkan riwayat perpindahan HEAD, yang bisa memberi petunjuk kapan branch terakhir kali di-checkout atau di-modifikasi.

File log di .git/worktrees/ sendiri bisa diperiksa:

# Isi direktori worktrees
ls -la .git/worktrees/

# Untuk setiap entri, periksa file HEAD dan linked worktree
cat .git/worktrees/fitur-auth/HEAD
cat .git/worktrees/fitur-auth/gitdir

File HEAD berisi referensi ke branch (misalnya ref: refs/heads/fitur-auth), dan file gitdir berisi path ke direktori .git dari worktree tersebut. Jika path di gitdir menunjuk ke direktori yang tidak ada, worktree tersebut stale dan bisa dibersihkan.

Di environment CI/CD, periksa log output dari pipeline. Banyak CI runner yang menjalankan git worktree add secara implisit saat checkout dan bisa meninggalkan worktree yang tidak dibersihkan. Log pipeline biasanya menunjukkan perintah Git apa yang dijalankan dan di mana proses gagal.

Sumber Resmi untuk Deep-Dive

Untuk pemahaman yang lebih mendalam tentang Git worktree dan mekanisme internalnya, berikut adalah sumber-sumber resmi yang direkomendasikan:

  1. Git Documentation — git-worktree: Dokumentasi resmi untuk perintah git worktree, mencakup semua flag, opsi, dan perilaku detail. Diakses melalui git help worktree atau git-scm.com/docs/git-worktree.

  2. Git Internals — Worktrees: Bab tentang internal Git di Pro Git book yang membahas bagaimana Git menyimpan data worktree di bawah .git/worktrees/. Tersedia gratis di git-scm.com/book.

  3. Git Source Code: Untuk yang benar-benar ingin memahami implementasinya, kode sumber Git (khususnya file worktree.c dan worktree.h) menunjukkan bagaimana Git memeriksa keterikatan worktree sebelum mengizinkan penghapusan branch.

  4. Git Community Forum dan Stack Overflow: Tag git-worktree di Stack Overflow memiliki banyak diskusi tentang edge case dan solusi untuk masalah spesifik yang mungkin tidak tercakup dalam dokumentasi resmi.

Dengan pemahaman yang solid tentang mekanisme worktree dan disiplin dalam mengikuti alur kerja yang benar, error "cannot delete branch used by worktree at" seharusnya tidak pernah muncul lagi dalam workflow kamu. Kunci utamanya sederhana: selalu kelola worktree secara eksplisit, jangan pernah menghapus sesuatu secara manual di luar perintah Git, dan pastikan cleanup selalu menjadi bagian dari rutinitas penutupan branch.