pengembangan-web-mp-pd.com

Hapus cabang pelacakan tidak lagi di remote

Apakah ada cara sederhana untuk menghapus semua cabang pelacakan yang setara jarak jauh tidak ada lagi?

Contoh:

Cabang (lokal dan jarak jauh)

  • menguasai
  • Asal/master
  • Asal/perbaikan bug-a
  • Asal/bug-fix-b
  • Asal/perbaikan bug-c

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)

  • menguasai
  • bug-fix-a
  • bug-fix-b
  • Asal/master
  • Asal/perbaikan bug-a
  • Asal/bug-fix-b
  • Asal/perbaikan bug-c

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)

  • menguasai
  • bug-fix-a
  • bug-fix-b
  • Asal/master
  • Asal/perbaikan bug-c

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.

798
Mailo Světel

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

905
aubreypwd

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
396
jason.rickman

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:

  1. Periksa cabang default Anda. Biasanya git checkout master
  2. Jalankan 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.

236
dlsso

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:


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).
  • Perhatikan semua cabang jarak jauh yang dilaporkan telah dihapus. Atau, untuk menemukannya nanti, git branch -v (cabang pelacakan yatim mana pun akan ditandai "[hilang]").
  • git branch -d [branch_name] pada setiap cabang pelacakan yatim

Jika 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.


Penjelasan latar belakang

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/Xcode 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.)

109
Andrew Spencer

Tampaknya ada solusi di sini - https://stackoverflow.com/a/1072178/133986

Singkatnya, git remote Prune melakukan keajaiban

51
Mailo Světel

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

Pastikan kita tetap menguasai

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

Jadikan ini sebagai alias

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
46
karlingen

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

27
cs01

Solusi Windows

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 $_}

Penjelasan

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

22
chris31389
git fetch -p

Ini akan menghapus semua cabang yang tidak dilacak dari jarak jauh.

17
ckirksey3

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.

14
Patrick Quirk

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
13
pabloa98

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 ...

12
Mark Longair

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
12
Francois

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.

6
Joost den Boer

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.

6
bxm

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.

5
Karl Wilbur
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

5
thiruclassic

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.

Catatan

  • Ekspresi reguler yang saya gunakan adalah "$BRANCH/.*: gone]" di mana $BRANCH biasanya Origin. Ini mungkin tidak akan berfungsi jika output Git Anda dilokalisasi ke bahasa Prancis dll.
  • Sebastian Wiesner juga mengirim portalnya ke Rust untuk pengguna Windows. Yang itu juga disebut git pergi .
2
Eugene Yokota

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).

1
gsnedders

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
}
1
BrunoLM

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
1

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 ;};
  1. Ambil semua remote
  2. Dapatkan hanya cabang yang digabungkan dari git
  3. Hapus dari daftar ini cabang "dilindungi/penting"
  4. 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)

0
Ben Cassinat

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

0
Mailo Světel

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!

0
lps