Hapus semua cabang git lokal

323

Saya mengikuti proses pengembangan di mana saya membuat cabang lokal baru untuk setiap fitur atau kartu cerita baru. Setelah selesai saya menggabungkan cabang menjadi master dan kemudian mendorong.

Apa yang cenderung terjadi dari waktu ke waktu karena kombinasi kemalasan atau kelupaan, adalah bahwa saya berakhir dengan daftar besar cabang lokal, beberapa di antaranya (seperti paku) mungkin belum digabung.

Saya tahu cara mendaftar semua cabang lokal saya dan saya tahu cara menghapus satu cabang tapi saya bertanya-tanya apakah ada perintah git yang memungkinkan saya untuk menghapus semua cabang lokal saya?

Di bawah ini adalah output dari git branch --mergedperintah.

user@machine:~/projects/application[master]$ git branch --merged
  STORY-123-Short-Description
  STORY-456-Another-Description
  STORY-789-Blah-Blah
* master

Semua upaya untuk menghapus cabang yang terdaftar dengan grep -v \*(sesuai jawaban di bawah) menghasilkan kesalahan:

error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.

Saya menggunakan:
git 1.7.4.1
ubuntu 10.04
GNU bash, versi 4.1.5 (1) -release
GNU grep 2.5.4

Mulut
sumber
7
Saya mohon Anda menerima jawaban @Andrew!
Robert Siemer
@GiulioCaccin Pertanyaannya juga berkaitan dengan cabang yang mungkin belum digabung dan saya telah memperbarui pertanyaan untuk secara eksplisit mencerminkan hal ini.
Louth

Jawaban:

384

Sub-perintah 'git branch -d' dapat menghapus lebih dari satu cabang. Jadi, sederhanakan jawaban @ sblom tetapi tambahkan xargs kritis:

git branch -D `git branch --merged | grep -v \* | xargs`

atau, selanjutnya disederhanakan untuk:

git branch --merged | grep -v \* | xargs git branch -D 

Yang penting, seperti dicatat oleh @AndrewC, menggunakan git branchuntuk skrip tidak disarankan. Untuk menghindarinya gunakan sesuatu seperti:

git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D

Perhatian dijamin pada penghapusan!

$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
  Story-123-a
  Story-123-b
  Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).
GoZoner
sumber
Perintah ini masih melaporkan kesalahan yang sama seperti yang disebutkan dalam komentar untuk jawaban di bawah ini. error:branch 'STORY-123-Short-Description' not found.untuk masing-masing cabang yang terdaftar.
Louth
1
Bekerja untuk saya; lihat di atas dengan rincian ditambahkan.
GoZoner
1
Jadi, apakah menggunakan git 1.7.10 menyelesaikan masalah Anda atau apakah Anda lebih suka bekerja langsung di repositori .git?
GoZoner
1
Jika Anda mendapatkan error:branch 'STORY-123-Short-Description' not found.kesalahan, ini mungkin karena pengaturan warna git. Ini bekerja untuk saya (perhatikan --no-coloropsi):git branch --no-color --merged | grep -v \* | xargs git branch -D
marcok
3
Satu-satunya jawaban pada SO saya telah menemukan yang berfungsi. Terima kasih!
Kevin Suttle
140

Saya menemukan cara yang lebih baik dalam mengomentari masalah ini di github :

git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d

sunting: menambahkan opsi tanpa warna dan mengecualikan cabang stabil (tambahkan cabang lain sesuai kebutuhan dalam kasus Anda)

mBardos
sumber
2
Akhirnya, solusi yang saya butuhkan
Code Whisperer
1
Saya sudah mencoba ini tetapi terus mendapatkan error: branch 'my-branch-name' not found.untuk setiap cabang. Menggunakan git versi 1.8.3.4 (Apple Git-47). Ada yang tahu kenapa?
wheresrhys
coba 'git branch --merged master | grep -v master | xargs echo 'untuk men-debug apa yang sebenarnya ingin dihapus? tidak punya ide yang lebih baik ...
mBardos
2
Begitu. git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
Павел Тявин
1
Pelajari penggunaan xargs bersama dengan ini. Terima kasih
Volem
105

Parsing output git branchtidak direkomendasikan, dan bukan jawaban yang baik untuk pembaca masa depan di Stack Overflow.

  1. git branchadalah apa yang dikenal sebagai perintah porselen. Perintah porselen tidak dirancang untuk diurai mesin dan output dapat berubah di antara berbagai versi Git.
  2. Ada opsi konfigurasi pengguna yang mengubah output git branchdengan cara yang membuatnya sulit untuk diurai (misalnya, pewarnaan). Jika pengguna telah menetapkan color.branchmaka Anda akan mendapatkan kode kontrol di output, ini akan mengarah ke error: branch 'foo' not found.jika Anda mencoba untuk memipakannya ke perintah lain. Anda dapat mem-bypass ini dengan --no-colorflag git branch, tetapi siapa yang tahu apa konfigurasi pengguna lain yang mungkin merusak barang.
  3. git branch dapat melakukan hal-hal lain yang mengganggu untuk diuraikan, seperti meletakkan tanda bintang di sebelah cabang yang saat ini diperiksa

The pemelihara git telah mengatakan tentang scripting sekitar git branchkeluaran

Untuk mengetahui apa cabang saat ini, pengguna biasa / ceroboh mungkin telah menulis di sekitar cabang git, yang salah. Kami secara aktif mencegah penggunaan perintah Porcelain, termasuk cabang git, dalam skrip, karena output dari perintah dapat berubah untuk membantu penggunaan kasus konsumsi manusia.

Jawaban yang menyarankan pengeditan file secara manual di .gitdirektori (seperti .git / refs / head) sama-sama bermasalah (sebagai gantinya mungkin terdapat dalam .git / packed-refs, atau Git dapat mengubah tata letak internal mereka di masa mendatang).

Git menyediakan for-each-refperintah untuk mengambil daftar cabang.

Git 2.7.X akan memperkenalkan --mergedopsi sehingga Anda bisa melakukan sesuatu seperti di bawah ini untuk menemukan dan menghapus semua cabang yang digabungkanHEAD

for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
    git branch -d ${mergedBranch}
done

Git 2.6.X dan yang lebih lama, Anda harus mendaftar semua cabang lokal dan kemudian mengujinya secara terpisah untuk melihat apakah mereka telah digabung (yang akan secara signifikan lebih lambat dan sedikit lebih rumit).

for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
    git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done
Andrew C
sumber
git branch --no-color 2>/dev/null?
nobar
5
Ini tentu saja merupakan peningkatan. Anda akan selalu memiliki masalah perlu menyaring *, dan itu memang hal-hal lucu jika seseorang menjalankannya dari kepala terpisah. Masalah utamanya adalah git branchperintah porselen, dan tidak ada jaminan bahwa output tidak akan berubah di beberapa versi git yang akan datang.
Andrew C
Terima kasih @AndrewC - ini adalah jawaban atas pertanyaan tentang kesalahan "branch not found" yang misterius dan memberikan solusi yang berfungsi menggunakan perintah yang lebih tepat! 👍
Jason
2
Bagaimana perintah GIT 'Porcelain' dan 'non-Porcelain' diidentifikasi?
GoZoner
1
Mungkin akan menjadi perangkat tambahan yang berguna untuk mengecualikan 'dev' dan 'master' secara default?
PandaWood
66

Cara yang lebih sederhana untuk menghapus semua cabang tetapi menjaga yang lain seperti "mengembangkan" dan "master" adalah sebagai berikut:

git branch | grep -v "develop" | grep -v "master" | xargs git branch -D

sangat berguna !

geoom
sumber
8
Anda telah menghidupkan kembali utas lama dan mengirimkan jawaban yang hampir identik dengan yang sudah ada, yaitu buggy dan kehilangan perubahan keamanan yang dimilikinya. Ini bukan jawaban yang bagus.
Andrew C
6
Jawaban ini jelas di piping output dari git branch, memodifikasinya, dan meneruskan ke git branch -D. Tidak perlu kejam.
Pam
Solusi ini berhasil untuk saya. Menghapus semua cabang lokal.
Prad
1
Ini tidak akan menghapus cabang apa pun yang mengandung kata develop atau master seperti 'develop_feature' atau 'master_feature'.
Django
INI ADALAH JAWABAN SAYA MENCARI 👆🏻
Konrad G
62

Untuk menghapus setiap cabang kecuali cabang yang saat ini Anda periksa:

for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

Saya akan merekomendasikan perubahan git branch -D $bke echo $bbeberapa kali pertama untuk memastikan bahwa itu menghapus cabang yang Anda inginkan.

sblom
sumber
1
dengan perintah ini saya mengerti, error:branch 'a_branch_name' not found.saya bisa melihat apa yang Anda coba lakukan dan saya sudah bermain-main dengan perintah itu tetapi untuk beberapa alasan git sepertinya tidak suka nama cabang yang disediakan ...
Louth
hmmm. untuk membantu memecahkan masalah, akan berguna untuk melihat beberapa contoh keluaran darigit branch --merged
sblom
nama cabang saya adalah formatSTORY-123-Short-Description
Louth
dan ketika Anda menjalankan git branch --merged, Anda mendapatkan daftar dengan salah satu dari mereka di setiap baris?
sblom
1
apakah secara harfiah dikatakan error:branch 'a_branch_name' not found.? Atau apakah ia mengeluh tentang salah satu nama cabang dari git branchoutput Anda di atas?
sblom
52

Perintah di bawah ini akan menghapus semua cabang lokal kecuali cabang master.

git branch | grep -v "master" | xargs git branch -D

Perintah di atas

  1. daftar semua cabang
  2. Dari daftar abaikan cabang master dan ambil sisa cabang
  3. hapus cabang
Pemburu
sumber
4
Saya akan menggunakan git branch | grep -v "master" | xargs git branch -ddulu jadi saya tidak menghapus cabang yang tidak dihapus, hanya untuk aman. Tapi jawaban yang bagus!
Jonas Lomholdt
3
Ini adalah versi PowerShell,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
Jonas Lomholdt
1
@baklazan ini hanya akan berfungsi di baris perintah Windows 10 jika Anda memiliki beberapa alat yang diinstal. Anda mungkin memiliki MINGW atau semacamnya dan Anda tidak mengetahuinya.
KthProg
42

Sekedar catatan, saya akan meningkatkan ke git 1.7.10. Anda mungkin mendapatkan jawaban di sini yang tidak akan berfungsi pada versi Anda. Dugaan saya adalah bahwa Anda harus mengawali nama cabang dengan refs/heads/.

PERHATIAN, lanjutkan dengan yang berikut ini hanya jika Anda membuat salinan folder kerja dan direktori .git Anda.

Saya terkadang hanya melanjutkan dan menghapus cabang yang tidak saya inginkan langsung .git/refs/heads. Semua cabang ini adalah file teks yang berisi 40 karakter sha-1 dari komit yang mereka tuju. Anda akan memiliki informasi asing di Anda .git/configjika Anda memiliki pelacakan khusus yang diatur untuk salah satu dari mereka. Anda dapat menghapus entri-entri itu secara manual juga.

Adam Dymitruk
sumber
Akhirnya pilihan yang sederhana dan pragmatis. Saya suka: D
Melvyn
2
Ini tidak akan berfungsi jika Anda telah mengemas referensi, atau bahkan jika Anda kadang-kadang diklon dari server jauh (yang akan memberi Anda file yang sudah dikemas). Jika Anda ref dikemas, maka ref tidak akan disimpan dalam .git / ref / head, mereka akan disimpan dalam file yang disebut "packed-refs". Lihat git-scm.com/docs/git-pack-refs .
Alexander Bird
1
Sepertinya ide buruk untuk menghapus cabang yang telah Anda periksa saat ini
Moberg
@Moberg Cukup checkout komit sebelumnya, dan KEPALA Anda yang terlepas akan mengapung dengan baik.
RomainValeri
34

Coba perintah shell berikut:

git branch | grep -v "master" | xargs git branch -D

Penjelasan:

  • 🛒 Dapatkan semua cabang melalui git branch | grep -v "master"perintah
  • 👇 Pilih setiap cabang dengan xargsperintah
  • 💦 Hapus cabang dengan xargs git branch -D
Pravin
sumber
3
Meskipun ini mungkin jawaban yang benar. Satu baris kode tidak terlalu berguna tanpa penjelasan tentang apa dan bagaimana cara memecahkan pertanyaan awal. Harap berikan perincian untuk jawaban Anda.
RyanNerd
28

Untuk menghapus semua cabang lokal di linux kecuali yang Anda aktifkan

// hard delete

git branch -D $(git branch)
Ashish Yadav
sumber
2
Yang ini terasa lebih aman daripada masuk ke .git dan menghapus barang.
nelsontruran
25

Saya merasa lebih mudah menggunakan editor teks dan shell.

  1. Ketik git checkout <TAB>shell. Akan menampilkan semua cabang lokal.
  2. Salin ke editor teks, hapus yang perlu Anda simpan.
  3. Ganti jeda baris dengan spasi. (Dalam SublimeText sangat mudah.)
  4. Buka shell, ketik git branch -D <PASTE THE BRANCHES NAMES HERE>.

Itu dia.

culebrón
sumber
Saya tidak berpikir Anda dapat menghapus cabang tempat Anda berdiri.
Dong Thang
@Dong Ada * di sebelah cabang itu sehingga Anda cukup menghapusnya dari daftar yang disalin!
Melanie
12

Saya memiliki situasi yang serupa dan baru-baru ini menemukan perintah berikut berguna.

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

Jika Anda ingin menyimpan beberapa cabang, maka

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

Semoga ini bisa membantu seseorang.

4u.Ans
sumber
1
Bagus tapi saya perlu backticks untuk membuatnya bekerja - git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` Sebenarnya saya pikir Anda memang memilikinya tetapi mereka tersesat dalam format SO.
tassinari
10

Dari Windows Command Line, hapus semua kecuali cabang yang diperiksa saat ini menggunakan:

for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f
kiewik
sumber
7

Jika Anda tidak perlu melalui Git itu sendiri, Anda juga dapat menghapus head di bawah .git / refs / head secara manual atau terprogram. Berikut ini akan berfungsi dengan mengutak-atik minimal di bawah Bash:

shopt -s extglob
rm -rf .git/refs/heads/!(master)

Ini akan menghapus setiap cabang lokal kecuali cabang master Anda. Karena cabang hulu Anda disimpan di .git / ref / remote , mereka akan tetap tidak tersentuh.

Jika Anda tidak menggunakan Bash, atau ingin mengulang banyak repositori Git sekaligus, Anda dapat melakukan sesuatu yang mirip dengan GNU find:

find . \
    -path remotes -path logs -prune -o \
    -wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf

Solusi find mungkin lebih portabel, tetapi jalur pemangkasan dan nama file rumit dan berpotensi lebih rentan kesalahan.

Todd A. Jacobs
sumber
Keren. Hapus visual :)
sandalone
5

Tidak ada jawaban yang memuaskan kebutuhan saya sepenuhnya, jadi inilah dia:

git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

Ini akan menghapus semua cabang lokal yang digabungkan dan dimulai dengan feature/, bugfix/atau hotfix/. Setelah itu hulu remoteorigin dipangkas (Anda mungkin harus memasukkan kata sandi).

Bekerja pada Git 1.9.5.

pengguna4401817
sumber
5

Berdasarkan kombinasi sejumlah jawaban di sini - jika Anda ingin menjaga semua cabang yang ada pada jarak jauh tetapi menghapus sisanya , oneliner berikut akan melakukan trik:

git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D
Srishan Bhattarai
sumber
3

Meskipun ini bukan solusi baris perintah, saya terkejut bahwa Git GUI belum disarankan.

Saya menggunakan baris perintah 99% dari waktu, tetapi dalam hal ini yang baik untuk memperlambat (maka pertanyaan aslinya), atau Anda tidak tahu apa yang akan Anda hapus ketika beralih ke beberapa manipulasi shell panjang, tapi pintar.

UI memecahkan masalah ini karena Anda dapat dengan cepat memeriksa cabang yang ingin Anda hapus, dan diingatkan pada yang ingin Anda pertahankan, tanpa harus mengetikkan perintah untuk setiap cabang.

Dari UI, buka Cabang -> Hapus dan Ctrl + Klik cabang yang ingin Anda hapus sehingga disorot. Jika Anda ingin memastikan mereka digabung menjadi cabang (seperti dev), di bawah Hapus Hanya jika Digabungkan Ke setel Cabang Lokal ke dev. Kalau tidak, atur ke Selalu untuk mengabaikan pemeriksaan ini.

GitUI: hapus cabang lokal

Dane Bouchie
sumber
1

Untuk PowerShell, ini akan berhasil:

git branch --format '%(refname:lstrip=2)' --merged `
    | Where-Object { $_ -ne 'master' } `
    | ForEach-Object { git branch -d $_ }
Lucas
sumber
0

Script berikut menghapus cabang. Gunakan dan modifikasi dengan risiko Anda sendiri, dll. Dll

Berdasarkan jawaban lain dalam pertanyaan ini, saya akhirnya menulis skrip bash cepat untuk saya sendiri. Saya menyebutnya "gitbd" (cabang git -D) tetapi jika Anda menggunakannya, Anda dapat mengubah nama itu menjadi apa pun yang Anda inginkan.

gitbd() {
if [ $# -le 1 ]
  then
    local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
    printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
    read -n 1 -r # Immediately continue after getting 1 keypress
    echo # Move to a new line
    if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
      then
        echo $branches_to_delete | xargs git branch -D
    fi
else
  echo "This command takes one arg (match pattern) or no args (match all)"
fi
}

Ini akan menawarkan untuk menghapus cabang apa pun yang cocok dengan argumen pola, jika diteruskan, atau semua cabang lokal saat dipanggil tanpa argumen. Ini juga akan memberi Anda langkah konfirmasi, karena, Anda tahu, kami menghapus banyak hal, jadi itu bagus.

Agak bodoh - jika tidak ada cabang yang cocok dengan polanya, itu tidak menyadarinya.

Contoh output run:

$ gitbd test
Matching branches:

dummy+test1
dummy+test2
dummy+test3

Delete? [Y/n] 
dherman
sumber
0

Saya menulis skrip shell untuk menghapus semua cabang lokal kecuali develop

branches=$(git branch | tr -d " *")
output=""
for branch in $branches 
do
  if [[ $branch != "develop" ]]; then
    output="$output $branch"
  fi
done
git branch -d $output
nhp
sumber
0

Jawaban di atas berfungsi dengan baik. Berikut adalah pendekatan lain ketika kami memiliki banyak cabang di repo lokal dan kami harus menghapus banyak cabang kecuali beberapa yang terletak di mesin lokal.

Pertama git branchakan mendaftar semua cabang lokal.

Untuk memindahkan kolom nama cabang menjadi satu baris dalam file dengan menjalankan perintah unix
git branch > sample.txt
Ini akan menyimpannya dalam file sample.txt . Dan jalankan
awk 'BEGIN { ORS = " " } { print }' sample.txt
perintah di shell. Ini akan mengubah kolom menjadi baris dan menyalin daftar nama cabang dalam satu baris.

Dan kemudian jalankan
git branch -D branch_name(s).
Ini akan menghapus semua cabang terdaftar yang ada di lokal

Deepak G
sumber
0

Cara yang paling pragmatis: pastikan Anda tidak memiliki pekerjaan yang belum dikomit master, komit / dorong jika perlu, klon salinan repositori baru, dan hapus yang lama.

Patrick Sanan
sumber
0

Untuk tujuan ini, Anda dapat menggunakan git-ekstra

$ git delete-merged-branches
Deleted feature/themes (was c029ab3).
Deleted feature/live_preview (was a81b002).
Deleted feature/dashboard (was 923befa).
Andriy Orehov
sumber
0

Saya tidak punya grep atau unix lain di komputer saya, tetapi ini berfungsi dari terminal VSCode:

git branch -d $(git branch).trim()

Saya menggunakan huruf kecil d sehingga tidak akan menghapus cabang yang tidak dihapus.

Saya juga menjadi master ketika saya melakukannya, jadi * mastertidak ada sehingga tidak berusaha menghapus master.

Ron Newcomb
sumber
Dikonfirmasi: Jika tidak aktif master, perintah ini AKAN dihapus master.
Brett Rowberry
-1

Pastikan Anda melakukan ini dulu

git fetch

Setelah Anda memiliki semua informasi cabang jarak jauh, gunakan perintah berikut untuk menghapus setiap cabang tunggal kecuali master

 git branch -a | grep -v "master" | grep remotes | sed 's/remotes\/origin\///g' | xargs git push origin --delete
Meng
sumber