Saya telah menggunakan jawaban Adam selama bertahun-tahun sekarang. Yang mengatakan, bahwa ada beberapa kasus di mana itu tidak berperilaku seperti yang saya harapkan:
- cabang yang berisi kata "master" diabaikan, mis. "notmaster" atau "masterful", daripada hanya cabang master
- cabang-cabang yang berisi kata "dev" diabaikan, misalnya "dev-test", bukan hanya cabang dev
- menghapus cabang yang dapat dijangkau dari KEPALA cabang saat ini (yaitu, belum tentu menguasai)
- dalam keadaan HEAD terpisah, menghapus setiap cabang yang dapat dijangkau dari komit saat ini
1 & 2 langsung ditangani, hanya dengan perubahan pada regex. 3 tergantung pada konteks yang Anda inginkan (yaitu hanya menghapus cabang yang belum digabungkan menjadi master atau melawan cabang Anda saat ini). 4 berpotensi menjadi bencana (walaupun dapat dipulihkan dengan git reflog
), jika Anda menjalankannya secara tidak sengaja dalam kondisi HEAD yang terlepas.
Akhirnya, saya ingin semua ini berada dalam satu liner yang tidak memerlukan skrip (Bash | Ruby | Python) terpisah.
TL; DR
Buat alias git "sapuan" yang menerima -f
bendera opsional :
git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'
dan memohonnya dengan:
git sweep
atau:
git sweep -f
Jawaban panjang dan terperinci
Itu yang paling mudah bagi saya untuk membuat contoh git repo dengan beberapa cabang dan berkomitmen untuk menguji perilaku yang benar:
Buat git repo baru dengan komit tunggal
mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"
Buat beberapa cabang baru
git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
bar
develop
foo
* master
masterful
notmaster
Perilaku yang diinginkan: pilih semua cabang digabung kecuali: master, mengembangkan atau saat
Regex asli melewatkan cabang "masterful" dan "notmaster":
git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
bar
Dengan regex yang diperbarui (yang sekarang tidak termasuk "berkembang" daripada "dev"):
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Beralih ke foo cabang, buat komit baru, lalu checkout cabang baru, foobar, berdasarkan foo:
echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"
Cabang saya saat ini adalah foobar, dan jika saya menjalankan kembali perintah di atas untuk mendaftar cabang yang ingin saya hapus, cabang "foo" dimasukkan walaupun belum digabung menjadi master:
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
masterful
notmaster
Namun, jika saya menjalankan perintah yang sama pada master, cabang "foo" tidak termasuk:
git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Dan ini hanya karena git branch --merged
default ke KEPALA cabang saat ini jika tidak ditentukan. Setidaknya untuk alur kerja saya, saya tidak ingin menghapus cabang lokal kecuali mereka telah digabungkan untuk dikuasai, jadi saya lebih suka varian berikut:
git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Keadaan HEAD terlepas
Mengandalkan perilaku default git branch --merged
memiliki konsekuensi yang bahkan lebih signifikan dalam keadaan HEAD terpisah:
git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
foobar
masterful
notmaster
Ini akan menghapus cabang saya, "foobar" bersama dengan "foo", yang hampir pasti bukan hasil yang diinginkan. Namun, dengan perintah revisi kami:
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Satu baris, termasuk penghapusan aktual
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d
Semua dibungkus menjadi alias git "sapuan":
git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'
Alias menerima -f
bendera opsional . Perilaku default adalah hanya menghapus cabang yang telah digabungkan ke master, tetapi -f
bendera akan menghapus cabang yang telah digabungkan ke cabang saat ini.
git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).
git branch -D
menghapus cabang apa pun apakah itu telah digabung atau tidak.