Apakah ada cara sederhana untuk menghapus semua cabang pelacakan yang setara jarak jauh tidak ada lagi?
Contoh:
Cabang (lokal dan jarak jauh)
Secara lokal, saya hanya memiliki cabang master. Sekarang saya harus bekerja pada bug-fix-a , jadi saya memeriksanya, mengerjakannya, dan mendorong perubahan ke remote. Selanjutnya saya melakukan hal yang sama dengan bug-fix-b .
Cabang (lokal dan jarak jauh)
Sekarang saya memiliki cabang lokal master , bug-fix-a , bug-fix-b . Pemelihara cabang Master akan menggabungkan perubahan saya ke master dan menghapus semua cabang yang telah digabung.
Jadi keadaan saat ini sekarang:
Cabang (lokal dan jarak jauh)
Sekarang saya ingin memanggil beberapa perintah untuk menghapus cabang (dalam hal ini bug-fix-a , bug-fix-b ), yang tidak lagi terwakili dalam repositori jarak jauh.
Itu akan menjadi sesuatu seperti perintah git remote Prune Origin
yang ada, tetapi lebih seperti git local Prune Origin
.
git remote Prune Origin
memangkas pelacakan cabang yang bukan pada remote.
git branch --merged
daftar cabang yang telah digabung ke cabang saat ini.
xargs git branch -d
menghapus cabang yang terdaftar pada input standar.
Hati-hati menghapus cabang yang terdaftar oleh git branch --merged
. Daftar ini dapat menyertakan master
atau cabang lain yang Anda tidak ingin hapus.
Untuk memberi diri Anda kesempatan untuk mengedit daftar sebelum menghapus cabang, Anda dapat melakukan hal berikut dalam satu baris:
git branch --merged >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
Setelah perintah
git fetch -p
menghapus referensi jarak jauh, saat Anda menjalankan
git branch -vv
itu akan menunjukkan 'hilang' sebagai status jarak jauh. Sebagai contoh,
$ git branch -vv
master b900de9 [Origin/master: behind 4] Fixed bug
release/v3.8 fdd2f4e [Origin/release/v3.8: behind 2] Fixed bug
release/v3.9 0d680d0 [Origin/release/v3.9: behind 2] Updated comments
bug/1234 57379e4 [Origin/bug/1234: gone] Fixed bug
Jadi, Anda dapat menulis skrip sederhana untuk menghapus cabang lokal yang menjadi remote:
git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
Sebagian besar jawaban ini sebenarnya tidak menjawab pertanyaan awal. Saya melakukan banyak penggalian dan ini adalah solusi terbersih yang saya temukan. Ini adalah versi yang sedikit lebih menyeluruh dari jawaban itu:
git checkout master
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Penjelasan:
Bekerja dengan memangkas cabang pelacakan Anda kemudian menghapus yang lokal yang menunjukkan mereka "hilang" dalam git branch -vv
.
Catatan:
Jika bahasa Anda diatur ke sesuatu selain bahasa Inggris, Anda perlu mengubah gone
ke Word yang sesuai. Cabang yang bersifat lokal saja tidak akan disentuh. Cabang yang telah dihapus pada jarak jauh tetapi tidak digabung akan menampilkan pemberitahuan tetapi tidak dihapus di lokal. Jika Anda ingin menghapusnya, ubah -d
menjadi -D
.
Saya biasanya tidak akan menjawab pertanyaan yang sudah memiliki 16 jawaban, tetapi semua jawaban lainnya salah, dan jawaban yang benar sangat sederhana. Pertanyaannya mengatakan, "Apakah ada cara sederhana untuk menghapus semua cabang pelacakan yang setara jarak jauh tidak ada lagi?"
Jika "sederhana" berarti tidak rapuh, tidak berbahaya, dan tanpa bergantung pada alat yang tidak dimiliki semua pembaca, maka jawaban yang tepat adalah: tidak.
Beberapa jawaban sederhana, tetapi mereka tidak melakukan apa yang diminta. Yang lain melakukan apa yang diminta, tetapi tidak sederhana: semua bergantung pada penguraian output Git melalui perintah manipulasi teks atau bahasa scripting, yang mungkin tidak ada pada setiap sistem. Selain itu, sebagian besar saran menggunakan perintah porselen, yang outputnya tidak dirancang untuk diuraikan dengan skrip ("porselen" mengacu pada perintah yang dimaksudkan untuk operasi manusia; skrip harus menggunakan perintah "pipa ledeng" tingkat rendah).
Bacaan lebih lanjut:
git remote Prune
, git Prune
, git fetch --Prune
git branch
output dalam skrip .Jika Anda ingin melakukan ini dengan aman, untuk kasus penggunaan dalam pertanyaan (cabang pelacakan pengumpulan sampah yang telah dihapus pada server tetapi masih ada sebagai cabang lokal) dan dengan perintah Git tingkat tinggi saja, Anda harus
git fetch --Prune
(atau git fetch -p
, yang merupakan alias, atau git Prune remote Origin
yang melakukan hal yang sama tanpa mengambil, dan mungkin bukan yang Anda inginkan sebagian besar waktu).git branch -v
(cabang pelacakan yatim mana pun akan ditandai "[hilang]").git branch -d [branch_name]
pada setiap cabang pelacakan yatimJika Anda ingin membuat skrip solusi, maka for-each-ref
adalah titik awal Anda, seperti pada jawaban Mark Longair di sini dan jawaban untuk pertanyaan lain , tapi saya tidak bisa melihat cara untuk mengeksploitasinya tanpa menulis Lingkaran skrip shell, atau menggunakan xargs atau sesuatu.
Untuk memahami apa yang terjadi, Anda perlu menghargai itu, dalam situasi melacak cabang, Anda tidak memiliki satu cabang, tetapi tiga. (Dan ingat bahwa "cabang" berarti hanya pointer ke komit.)
Diberi cabang pelacakan feature/X
, repositori jarak jauh (server) akan memiliki cabang ini dan menyebutnya feature/X
. Repositori lokal Anda memiliki remotes/Origin/feature/X
cabang yang artinya, "Ini adalah remote yang memberitahuku fitur/cabang X-nya, terakhir kali kami berbicara," dan akhirnya, repositori lokal memiliki cabang feature/X
yang menunjuk ke komit terbaru Anda, dan dikonfigurasi untuk "melacak" remotes/Origin/feature/X
, yang berarti bahwa Anda dapat menarik dan mendorong untuk tetap selaras.
Pada titik tertentu, seseorang telah menghapus feature/X
pada remote. Sejak saat itu, Anda memiliki feature/X
lokal Anda (yang mungkin tidak Anda inginkan lagi, karena pekerjaan pada fitur X mungkin selesai), dan remotes/Origin/feature/X
Anda yang tentu saja tidak berguna karena satu-satunya tujuannya adalah untuk mengingat keadaan negara. cabang server.
Dan Git akan membiarkan Anda secara otomatis membersihkan remotes/Origin/feature/X
yang redundan - itulah yang git fetch --Prune
lakukan - tetapi untuk beberapa alasan, itu tidak memungkinkan Anda secara otomatis menghapus feature/X
code Anda sendiri ... meskipun feature/X
Anda masih berisi informasi pelacakan yatim, jadi ia memiliki informasi untuk mengidentifikasi cabang pelacakan sebelumnya yang telah sepenuhnya digabung. (Bagaimanapun, ini dapat memberikan Anda informasi yang memungkinkan Anda melakukan operasi sendiri.)
Tampaknya ada solusi di sini - https://stackoverflow.com/a/1072178/133986
Singkatnya, git remote Prune
melakukan keajaiban
Saya menemukan jawabannya di sini: Bagaimana saya bisa menghapus semua cabang git yang telah digabung?
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Anda dapat memastikan bahwa master
, atau cabang lainnya dalam hal ini, tidak dihapus dengan menambahkan grep
lainnya setelah yang pertama. Dalam hal ini Anda akan pergi:
git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d
Jadi jika kita ingin menjaga master
, develop
dan staging
misalnya, kita akan pergi:
git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d
Karena agak panjang, Anda mungkin ingin menambahkan alias ke .zshrc
atau .bashrc
Anda. Milik saya disebut gbpurge
(untuk git branches purge
):
alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'
Kemudian muat ulang .bashrc
atau .zshrc
Anda:
. ~/.bashrc
atau
. ~/.zshrc
Hapus semua cabang yang telah digabungkan menjadi master, tetapi jangan mencoba untuk menghapus master itu sendiri:
git checkout master && git pull Origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)
atau tambahkan alias:
alias gitcleanlocal="git checkout master && git pull Origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"
Penjelasan:
git checkout master
checkout cabang utama
git pull Origin master
memastikan cabang lokal memiliki semua perubahan jarak jauh digabungkan
git fetch -p
menghapus referensi ke cabang jauh yang telah dihapus
git branch -d $(git branch master --merged | grep master -v)
menghapus semua cabang yang telah digabungkan menjadi master, tetapi jangan mencoba untuk menghapus master itu sendiri
Untuk Microsoft Windows Powershell:
git checkout master; git remote update Origin --Prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}
git checkout master
beralih ke cabang master
git remote update Origin --Prune
memangkas cabang-cabang jarak jauh
git branch -vv
mendapatkan output verbose dari semua cabang ( referensi git )
Select-String -Pattern ": gone]"
hanya mendapatkan catatan di mana mereka telah dihapus dari jarak jauh.
% { $_.toString().Trim().Split(" ")[0]}
mendapatkan nama cabang
% {git branch -d $_}
menghapus cabang
git fetch -p
Ini akan menghapus semua cabang yang tidak dilacak dari jarak jauh.
Pencocokan pola untuk "hilang" di sebagian besar solusi lain agak menakutkan bagi saya. Agar lebih aman, ini menggunakan bendera --format
untuk mengeluarkan status pelacakan hulu masing-masing cabang.
Saya membutuhkan versi Windows-friendly, jadi ini menghapus semua cabang yang terdaftar sebagai "hilang" menggunakan Powershell:
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" |
? { $_ -ne "" } |
% { git branch -D $_ }
Baris pertama berisi nama cabang lokal yang cabang hulunya "hilang". Baris berikutnya menghapus baris kosong (yang merupakan output untuk cabang yang tidak "hilang"), kemudian nama cabang diteruskan ke perintah untuk menghapus cabang.
Ini akan menghapus semua gabungan lokal bercabang kecuali referensi master lokal dan yang saat ini sedang digunakan:
git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d
Dan ini akan menghapus semua cabang yang telah dihapus dari repositori jauh yang dirujuk oleh " Origin ", tetapi masih tersedia secara lokal di " remote/Origin ".
git remote Prune Origin
Saya tidak berpikir ada perintah bawaan untuk melakukan ini, tetapi aman untuk melakukan hal berikut:
git checkout master
git branch -d bug-fix-a
Ketika Anda menggunakan -d
, git akan menolak untuk menghapus cabang kecuali jika benar-benar digabungkan menjadi HEAD
atau cabang pelacakan jarak jauh hulu. Jadi, Anda selalu bisa mengulang-ulang keluaran git for-each-ref
dan mencoba menghapus setiap cabang. Masalah dengan pendekatan itu adalah saya menduga Anda mungkin tidak ingin bug-fix-d
dihapus hanya karena Origin/bug-fix-d
berisi sejarahnya. Sebagai gantinya, Anda dapat membuat skrip sesuatu seperti berikut:
#!/bin/sh
git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
then
if [ "$r" != "master" ]
then
git branch -d "$r"
fi
fi
done
Peringatan: Saya belum menguji skrip ini - gunakan hanya dengan hati-hati ...
Mungkin bermanfaat untuk beberapa, satu baris sederhana untuk menghapus semua cabang lokal kecuali menguasai dan mengembangkan
git branch | grep -v "master" | grep -v "develop" | xargs git branch -D
Berdasarkan info di atas, ini bekerja untuk saya:
git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs`
Ini menghapus semua cabang lokal dengan ': gone] '
pada remote.
Namun-jawaban lain untuk tumpukan, menarik banyak dari https://stackoverflow.com/a/48411554/2858703 (yang saya suka karena tampaknya menghilangkan ambiguitas tentang di mana gone]
akan cocok dengan git branch
output) tetapi menambahkan bengkok * nix:
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
| sed 's,^refs/heads/,,;/^$/d' \
| xargs git branch -D
Saya sudah membungkus skrip git-gone
ini di jalur saya:
#!/usr/bin/env bash
action() {
${DELETE} && xargs git branch -D || cat
}
get_gone() {
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
| sed 's,^refs/heads/,,;/^$/d'
}
main() {
DELETE=false
while [ $# -gt 0 ] ; do
case "${1}" in
(-[dD] | --delete) DELETE=true ;;
esac
shift
done
get_gone | action
}
main "${@}"
NB - Opsi --format tampaknya cukup baru; Saya perlu meningkatkan git dari 2.10.sesuatu ke 2.16.3 untuk mendapatkannya.
Tidak ada yang benar-benar cocok untuk saya. Saya menginginkan sesuatu yang akan membersihkan semua cabang lokal yang melacak cabang jarak jauh, pada Origin
, di mana cabang terpencil telah dihapus (gone
). Saya tidak ingin menghapus cabang lokal yang tidak pernah disetel untuk melacak cabang jauh (yaitu: cabang dev lokal saya). Saya juga menginginkan satu kalimat sederhana yang hanya menggunakan git
, atau alat CLI sederhana lainnya, daripada menulis skrip khusus. Saya akhirnya menggunakan sedikit grep
dan awk
untuk membuat perintah sederhana ini.
Inilah yang akhirnya berakhir di ~/.gitconfig
saya:
[alias]
Prune-branches = !git remote Prune Origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D
Berikut adalah perintah git config --global ...
untuk dengan mudah menambahkan ini sebagai git Prune-branches
:
git config --global alias.Prune-branches '!git remote Prune Origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'
CATATAN: Dalam perintah config, saya menggunakan opsi -d
untuk git branch
daripada -D
, seperti yang saya lakukan pada konfigurasi aktual saya. Saya menggunakan -D
karena saya tidak ingin mendengar Git mengeluh tentang cabang yang tidak di-emergasi. Anda mungkin menginginkan fungsi ini juga. Jika demikian, cukup gunakan -D
alih-alih -d
di akhir perintah konfigurasi itu.
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d
Perintah di atas dapat digunakan untuk mengambil cabang yang digabungkan dan dihapus di remote dan menghapus cabang lokal yang tidak lagi tersedia di
Berdasarkan Tip Git: Menghapus Cabang Lokal Lama , yang mirip dengan solusi jason.rickman Saya menerapkan perintah kustom untuk tujuan ini yang disebut git hilang menggunakan Bash:
$ git gone
usage: git gone [-pndD] [<branch>=Origin]
OPTIONS
-p Prune remote branch
-n dry run: list the gone branches
-d delete the gone branches
-D delete the gone branches forcefully
EXAMPLES
git gone -pn Prune and dry run
git gone -d delete the gone branches
git gone -pn
menggabungkan pemangkasan dan daftar cabang yang "hilang":
$ git gone -pn
bport/fix-server-broadcast b472d5d2b [Origin/bport/fix-server-broadcast: gone] Bump modules
fport/rangepos 45c857d15 [Origin/fport/rangepos: gone] Bump modules
Kemudian Anda dapat menarik pelatuk menggunakan git gone -d
atau git gone -D
.
"$BRANCH/.*: gone]"
di mana $BRANCH
biasanya Origin
. Ini mungkin tidak akan berfungsi jika output Git Anda dilokalisasi ke bahasa Prancis dll.Menarik banyak dari angkadarilainnyajawaban di sini, saya telah berakhir dengan yang berikut (git 2.13 dan di atas saja, saya percaya), yang seharusnya bisa digunakan pada Shell seperti UNIX:
git for-each-ref --Shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done
Ini terutama menggunakan for-each-ref
alih-alih branch
(karena branch
adalah perintah "porselen" yang dirancang untuk keluaran yang dapat dibaca manusia, bukan pemrosesan mesin) dan menggunakan argumen --Shell
untuk mendapatkan keluaran yang keluar dengan benar (ini memungkinkan kita untuk tidak khawatir tentang karakter apa pun di nama ref).
Saya datang dengan skrip bash ini. Selalu menjaga cabang develop
, qa
, master
.
git-clear() {
git pull -a > /dev/null
local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
branches=(${branches//;/ })
if [ -z $branches ]; then
echo 'No branches to delete...'
return;
fi
echo $branches
echo 'Do you want to delete these merged branches? (y/n)'
read yn
case $yn in
[^Yy]* ) return;;
esac
echo 'Deleting...'
git remote Prune Origin
echo $branches | xargs git branch -d
git branch -vv
}
Ini bekerja untuk saya:
git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep Origin) | awk '{print $1}' | xargs git branch -d
Saya menggunakan metode singkat untuk melakukan trik, saya sarankan Anda untuk melakukan hal yang sama karena dapat menghemat beberapa jam & memberi Anda lebih banyak visibilitas
Cukup tambahkan cuplikan berikut ke .bashrc Anda (.bashprofile di macos).
git-cleaner() { git fetch --all --Prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
- Ambil semua remote
- Dapatkan hanya cabang yang digabungkan dari git
- Hapus dari daftar ini cabang "dilindungi/penting"
- Hapus sisanya (mis., Cabang bersih dan gabungan)
Anda harus mengedit grep regex agar sesuai dengan kebutuhan Anda (di sini, itu mencegah master, preprod dan dmz dari penghapusan)
Saya tidak yakin untuk berapa lama, tapi saya menggunakan git-up sekarang, yang menangani itu.
Saya melakukan git up
dan mulai melacak cabang baru dan menghapus yang lama.
Hanya untuk membuatnya jelas, itu bukan perintah git out-of-box - https://github.com/aanand/git-up
BTW juga menyembunyikan pohon kotor dan membuat rebases masih hanya dengan git up
.
Semoga bermanfaat bagi seseorang
Inilah solusi yang saya gunakan untuk Shell ikan. Diuji pada Mac OS X 10.11.5
, fish 2.3.0
dan git 2.8.3
.
function git_clean_branches
set base_branch develop
# work from our base branch
git checkout $base_branch
# remove local tracking branches where the remote branch is gone
git fetch -p
# find all local branches that have been merged into the base branch
# and delete any without a corresponding remote branch
set local
for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print $1}')
set local $local $f
end
set remote
for f in (git branch -r | xargs basename)
set remote $remote $f
end
for f in $local
echo $remote | grep --quiet "\s$f\s"
if [ $status -gt 0 ]
git branch -d $f
end
end
end
Beberapa catatan:
Pastikan untuk mengatur base_branch
yang benar. Dalam hal ini saya menggunakan develop
sebagai cabang dasar, tetapi bisa berupa apa saja.
Bagian ini sangat penting: grep -v "\(master\|$base_branch\|\*\)"
. Ini memastikan bahwa Anda tidak menghapus master atau cabang dasar Anda.
Saya menggunakan git branch -d <branch>
sebagai tindakan pencegahan ekstra, agar tidak menghapus cabang apa pun yang belum sepenuhnya digabung dengan HEAD hulu atau saat ini.
Cara mudah untuk menguji adalah mengganti git branch -d $f
dengan echo "will delete $f"
.
Saya kira saya juga harus menambahkan: GUNAKAN AT RISIKO ANDA SENDIRI!