Làm cách nào để xóa tất cả các nhánh Git đã được hợp nhất?


1935

Tôi có nhiều chi nhánh Git. Làm cách nào để xóa các nhánh đã được hợp nhất? Có cách nào dễ dàng để xóa tất cả thay vì xóa từng cái một không?


46
Cụ thể hơn một chút git branch -Dsẽ xóa bất kỳ nhánh nào cho dù nó có được hợp nhất hay không.
PhilT

12
Bạn cũng có thể thực hiện việc này trực tiếp từ GitHub, nếu bạn đi đến phần 'chi nhánh' trong repo của mình (ví dụ: github.com/<username>/<repo_name>/branches ). Cần có một danh sách tất cả các chi nhánh của bạn, với biểu tượng thùng rác màu đỏ ở bên sẽ xóa chi nhánh đã chọn. Nhanh hơn nhiều so với làm trong thiết bị đầu cuối! Cũng sẽ cho thấy phía trước / phía sau mastermỗi chi nhánh là bao xa . Tuy nhiên, máy khách cục bộ của bạn vẫn sẽ liệt kê các nhánh cũ nếu bạn chạy git branch -a; sử dụng git fetch --pruneđể loại bỏ chúng (theo câu trả lời này ).
dùng5359531

3
Tập lệnh để thực hiện việc này cục bộ hoặc từ xa - với kiểm tra an toàn và "các nhánh an toàn" được định cấu hình trước: github.com/fatso83/dotfiles/tree/master/utils/ù git delete-merged --doit origin hoặcgit delete-merged --doit --local
oligofren

Bạn cũng có thể sử dụng ứng dụng này để tự động xóa các chi nhánh hợp nhất.
Sabass van Boxel

rm -fr work && git clone http://example.com/work.gittrong những năm qua đã trở thành cách dễ nhất để thoát khỏi một món dưa muối với git.
Phản ứng

Câu trả lời:


3115

CẬP NHẬT:

Bạn có thể thêm các nhánh khác để loại trừ như master và dev nếu quy trình công việc của bạn có những nhánh như tổ tiên có thể. Thông thường tôi phân nhánh từ thẻ "sprint-start" và master, dev và qa không phải là tổ tiên.

Đầu tiên, liệt kê tất cả các chi nhánh được hợp nhất từ ​​xa.

git branch --merged

Bạn có thể thấy một vài chi nhánh bạn không muốn xóa. chúng ta có thể thêm một vài đối số để bỏ qua các nhánh quan trọng mà chúng ta không muốn xóa như chủ hoặc phát triển. Lệnh sau sẽ bỏ qua nhánh chủ và bất cứ thứ gì có dev trong đó.

git branch --merged| egrep -v "(^\*|master|dev)"

Nếu bạn muốn bỏ qua, bạn có thể thêm nó vào lệnh egrep như sau. Chi nhánh skip_branch_namesẽ không bị xóa.

git branch --merged| egrep -v "(^\*|master|dev|skip_branch_name)"

Để xóa tất cả các nhánh cục bộ đã được sáp nhập vào nhánh hiện đang được kiểm tra:

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Bạn có thể thấy rằng chủ và dev được loại trừ trong trường hợp họ là tổ tiên.


Bạn có thể xóa một chi nhánh địa phương được hợp nhất với:

git branch -d branchname

Nếu nó không được hợp nhất, sử dụng:

git branch -D branchname

Để xóa nó khỏi điều khiển từ xa:

git push --delete origin branchname

git push origin :branchname    # for really old git

Khi bạn xóa chi nhánh khỏi điều khiển từ xa, bạn có thể cắt tỉa để thoát khỏi các chi nhánh theo dõi từ xa bằng:

git remote prune origin

hoặc cắt tỉa các nhánh theo dõi từ xa riêng lẻ, như câu trả lời khác cho thấy, với:

git branch -dr branchname

Hi vọng điêu nay co ich.


46
CẢNH BÁO: Nếu bạn vừa tạo một nhánh, nó cũng sẽ xóa chi nhánh đó. Đảm bảo không có một nhánh mới được tạo trong danh sách trước khi bạn chạy lệnh hàng đầu.
Gary Haran

153
OPPOSITE CẢNH BÁO: reflog sẽ tiết kiệm thịt xông khói của bạn. Vì vậy, đừng lo lắng.
Adam Dymitruk

33
Hãy nhớ rằng lệnh đầu tiên chỉ xóa các nhánh cục bộ, vì vậy nó không "nguy hiểm" như một số người đã chỉ ra.
ifightcrime

79
Biến thể PowerShell, để tôi có thể tìm thấy nó ở đây vào lần tới khi tôi git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
goog

23
Điều này tạo ra một lỗi fatal: branch name requirednếu bạn không có các nhánh nên bị xóa. Để tránh điều đó, bạn có thể vượt qua -rđể xargsnó không chạy git branch -dnếu stdin trống. (Đây là phần mở rộng GNU xargs, theo trang man).
Marius Gedminas

457

Để xóa tất cả các chi nhánh trên điều khiển từ xa đã được hợp nhất:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

Trong các phiên bản gần đây hơn của Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

CẬP NHẬT (bởi @oliver; vì không phù hợp với nhận xét, nhưng đã có đủ câu trả lời) : nếu bạn ở nhánh ABC thì ABC sẽ xuất hiện trong kết quả git branch -r --mergedvì nhánh không được chỉ định, vì vậy nhánh mặc định cho nhánh hiện tại và nhánh. luôn luôn đủ điều kiện là hợp nhất với chính nó (vì không có sự khác biệt giữa một nhánh và chính nó!).

Vì vậy, hoặc chỉ định chi nhánh:

git branch -r --merged master | grep -v master ...

HOẶC chủ thanh toán đầu tiên:

git checkout master | git branch -r --merged | grep -v ...

18
Câu trả lời tốt nhất cho đến nay. Chỉ cần một lưu ý, chi nhánh chính của tôi được đặt tên devvì vậy tôi đã phải thay đổi điều đó
Dorian

41
Tôi đã phải thêm | grep originsau grep -v masterđể ngăn chặn các nhánh từ xa khác về nguồn gốc. Rất khuyến khích kiểm tra đầu ra trước, sử dụnggit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4

9
Tôi sửa đổi một chút để loại trừ developchi nhánh là tốt. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Bây giờ điều này hóa ra là bí danh của tôi.
sarat

8
Điều làm cho đây là câu trả lời hay nhất mà tôi đã đọc, là -rlập luận mà tôi chưa thấy đề cập đến ở bất kỳ nơi nào khác. Nó được coi là chỉ các chi nhánh địa phương có giá trị làm một số vệ sinh trên. Nhưng điều khiển từ xa cũng đầy rác.
Asbjørn Ulsberg

19
Thận trọng - chỉ cần nhận ra: điều này rõ ràng sẽ tìm thấy các nhánh được hợp nhất với nhánh hiện tại , không phải là chủ, vì vậy nếu bạn ở trên myFeatureBranchnó sẽ xóa sạch origin/myFeatureBranch. Có lẽ tốt nhất là git checkout masterđầu tiên.
jakub.g 5/2/2016

190

Chỉ cần mở rộng câu trả lời của Adam một chút:

Thêm phần này vào cấu hình Git của bạn bằng cách chạy git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

Và sau đó bạn có thể xóa tất cả các chi nhánh hợp nhất cục bộ làm một cách đơn giản git cleanup.


11
Không nên lệnh đầu tiên là: git branch --merged mastervì bạn muốn xem xét những gì đã được hợp nhất thành chủ, hiện chưa được kiểm tra chi nhánh?
Joe Phillips

@JoePhilllips Một số người có nhánh chính không phải là chủ nhưng thay vào đó develophoặc devtrong trường hợp đó, lệnh sẽ thất bại với fatal: malformed object namelệnh chung hơn và bạn có trách nhiệm chạy nó
smohamed 13/8/2016

1
@JoePhilllips điểm của câu trả lời này là đóng gói câu trả lời của Adam (câu trả lời hàng đầu cho câu hỏi này) trong bí danh git hữu ích. Câu trả lời của Adam không có những gì bạn đang đề xuất và rất nhiều người đã thấy rằng nó hữu ích vì vậy tôi sẽ có xu hướng không thay đổi của tôi. Tôi sẽ khuyên bạn nên mở cuộc thảo luận về câu trả lời của Adam nếu bạn cảm thấy mạnh mẽ về nó
real_ate

13
Thêm -rvào xargssẽ ngăn các lỗi không cần thiết ( branch name required) khi chạy bí danh này nhiều lần hoặc khi không còn nhánh nào bị xóa. Bí danh của tôi trông như thế này:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta

1
Lệnh hiện tại không lọc ra chủ và phát triển các nhánh
Andriy F.

83

Điều này cũng hoạt động để xóa tất cả các chi nhánh hợp nhất trừ chủ.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d

3
Bây giờ nó sẽ không xóa bất kỳ chi nhánh nào mastertrong đó. Cố gắng grep -v ^master$cho giữa.
wchargein

Tôi cũng | grep -v '^\*'sẽ tránh để xóa chi nhánh hiện tại nếu bạn không làm chủ
svassr

5
Điều này thật tuyệt, cảm ơn! Một cảnh báo cho bất cứ ai sử dụng điều này: lưu ý rằng có hai khoảng trắng trong grep -v '^ master$'. Nếu bạn tự gõ nó và bỏ lỡ một cái, bạn sẽ xóa masternếu bạn không sử dụng nó.
styger

3
@ Mr.Polywhirl bản chỉnh sửa của bạn phá vỡ lệnh và bạn nên hoàn nguyên nó. Hai khoảng trắng là cần thiết, vì git branchsẽ liệt kê từng tên nhánh trên một dòng mới với hai khoảng trắng ở bên trái nếu nó không phải là nhánh được kiểm tra hiện tại. Về cơ bản, bạn đã đảm bảo rằng bất kỳ ai chạy lệnh này sẽ xóa nhánh chính của họ trừ khi đó là nhánh được kiểm tra hiện tại.
styger

79

Bạn sẽ muốn loại trừ các nhánh master& developkhỏi các lệnh đó.

Git địa phương rõ ràng:

git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d

Xóa git từ xa:

git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

Đồng bộ hóa đăng ký cục bộ của các chi nhánh từ xa:

git fetch -p

3
+1 cho phiên bản từ xa là tốt (nhưng ít cần thiết hơn vì chúng tôi có remote --prune). Cũng đáng chú ý rằng thoose sẽ không hoạt động với phiên bản git cũ hơn
malko

4
git config --global --add fetch.prune trueđể tự động cắt tỉa trên lấy hoặc kéo.
T3rm1

1
Tâm trí bạn, tỉa không giống như từ xa rõ ràng. Xóa từ xa thực sự xóa các nhánh từ xa được hợp nhất hoàn toàn với nhánh hiện tại của bạn. Prune chỉ dọn sạch registry cục bộ của bạn các chi nhánh từ xa đã bị xóa.
Guido Bouman

Từ này hoàn toàn sai lệch một chút, vì một nhánh sẽ được coi là hợp nhất, khi nó được sáp nhập trước đó, nhưng có các cam kết mới sau khi hợp nhất, không được hợp nhất.
bánh nướng

Để xóa tất cả các điều khiển từ xa gốc trong một cuộc gọi, tôi đã sử dụng cách này:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley

48

Đối với những bạn ở trên Windows và thích các tập lệnh PowerShell, đây là một trong đó xóa các nhánh được hợp nhất cục bộ:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}

13
Vì tò mò, điều này có thể được rút ngắn thành git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard

5
@IainBallard Chắc chắn, tôi có thể đã sử dụng bí danh. Điều đó không được khuyến khích khi bạn muốn tối đa hóa khả năng đọc. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn

1
chắc chắn rồi. Tôi thấy câu trả lời của bạn rất hữu ích :-) Tuy nhiên, đôi khi cú pháp powershell dạng dài cản trở những gì đang diễn ra trong các khối. Nhưng chủ yếu, tôi đã đưa ra một cái gì đó bạn có thể sao chép / dán hoặc gõ một lần. Cảm ơn một lần nữa.
Iain Ballard

4
Đây là một lớp lót cho vỏ cmd của Windows để bảo vệ chủ và nhánh hiện tại của bạn: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(thở dài, thay thế các backquote kép bằng đơn, tôi không chắc chắn làm thế nào để định dạng một chữ có chứa backquote)
yoyo

42

Tôi đã sử dụng câu trả lời của Adam trong nhiều năm nay. Điều đó nói rằng, có một số trường hợp nó không hoạt động như tôi mong đợi:

  1. các nhánh có chứa từ "master" đã bị bỏ qua, ví dụ "notmaster" hoặc "masterful", thay vì chỉ nhánh chính
  2. các nhánh có chứa từ "dev" đã bị bỏ qua, ví dụ "dev-test", thay vì chỉ nhánh dev
  3. xóa các nhánh có thể truy cập từ đầu của nhánh hiện tại (nghĩa là không nhất thiết phải là chủ)
  4. ở trạng thái CHÍNH tách rời, xóa mọi nhánh có thể truy cập khỏi cam kết hiện tại

1 & 2 rất đơn giản để giải quyết, chỉ cần thay đổi biểu thức chính quy. 3 phụ thuộc vào ngữ cảnh của những gì bạn muốn (nghĩa là chỉ xóa các nhánh chưa được sáp nhập thành chủ hoặc chống lại chi nhánh hiện tại của bạn). 4 có khả năng trở thành thảm họa (mặc dù có thể phục hồi được git reflog), nếu bạn vô tình chạy nó trong trạng thái CHÍNH tách rời.

Cuối cùng, tôi muốn tất cả điều này nằm trong một lớp lót không yêu cầu một tập lệnh (Bash | Ruby | Python) riêng biệt.

TL; DR

Tạo một bí danh git "quét" chấp nhận một -fcờ tùy chọn :

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

và gọi nó bằng:

git sweep

hoặc là:

git sweep -f

Câu trả lời dài và chi tiết

Dễ dàng nhất đối với tôi để tạo một ví dụ git repo với một số nhánh và cam kết kiểm tra hành vi chính xác:

Tạo một repo git mới với một cam kết duy nhất

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

Tạo một số chi nhánh mới

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
  bar
  develop
  foo
* master
  masterful
  notmaster

Hành vi mong muốn: chọn tất cả các nhánh được hợp nhất ngoại trừ: chính, phát triển hoặc hiện tại

Regex ban đầu bỏ lỡ các nhánh "masterful" và "notmaster":

git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
  bar

Với regex được cập nhật (hiện không bao gồm "phát triển" thay vì "dev"):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster

Chuyển sang nhánh foo, tạo một cam kết mới, sau đó kiểm tra một nhánh mới, foobar, dựa trên foo:

echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"

Nhánh hiện tại của tôi là foobar và nếu tôi chạy lại lệnh trên để liệt kê các nhánh tôi muốn xóa, nhánh "foo" được bao gồm ngay cả khi nó chưa được sáp nhập vào master:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  masterful
  notmaster

Tuy nhiên, nếu tôi chạy cùng một lệnh trên master, nhánh "foo" không được bao gồm:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Và điều này chỉ đơn giản là vì git branch --mergedmặc định là ĐẦU của nhánh hiện tại nếu không có quy định khác. Ít nhất là đối với quy trình làm việc của tôi, tôi không muốn xóa các chi nhánh địa phương trừ khi chúng được hợp nhất thành chủ, vì vậy tôi thích biến thể sau:

git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Tách bang

Dựa vào hành vi mặc định của git branch --mergedthậm chí còn có hậu quả quan trọng hơn trong trạng thái CHÍNH bị tách ra:

git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  foobar
  masterful
  notmaster

Điều này sẽ xóa chi nhánh tôi vừa mới mở, "foobar" cùng với "foo", gần như chắc chắn không phải là kết quả mong muốn. Tuy nhiên, với lệnh sửa đổi của chúng tôi:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Một dòng, bao gồm xóa thực tế

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

Tất cả được gói gọn trong một bí danh "quét":

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

Bí danh chấp nhận một -fcờ tùy chọn . Hành vi mặc định là chỉ xóa các nhánh đã được hợp nhất thành chủ, nhưng -fcờ sẽ xóa các nhánh đã được sáp nhập vào nhánh hiện tại.

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

Tại sao bạn cần tạo một chức năng? Không phải là git confignguyên tử sao?
VasiliNovikov

Để đối phó với các tùy chọn '-f' tranh luận (nếu tôi hiểu câu hỏi của bạn một cách chính xác)
xoáy

1
nhưng nó giúp như thế nào? Tôi có nghĩa là bắt đầu của biểu thức !f(){ git branch ...,. Đó là một khai báo chức năng, phải không? Tại sao không bắt đầu trực tiếp với git branch ...?
VasiliNovikov

1
Bạn hoàn toàn đúng. Chỉnh sửa câu trả lời của tôi cho phù hợp. Cảm ơn con trỏ!
eddies

Điều sau đây sẽ không làm giống như chế độ không lực? git checkout master && git branch -d `git branch --merged` && git checkout - Ngoại trừ việc nó sẽ xóa develop, nhưng có thể là một cách tiếp cận đơn giản hơn.
Guido Bouman


18

Sử dụng phiên bản Git 2.5.0:

git branch -d `git branch --merged`

16
Điều này có thể xóa masterchi nhánh btw!
Wazery

4
Thật. Tôi chỉ sử dụng nó khi tôi chắc chắn rằng tôi đang bật master.
Drainutb

11
git branch -d $(git branch --merged | grep -v master)
alexg

1
Điều này rất nguy hiểm nếu bạn có một luồng, hãy tưởng tượng bạn có chủ <- giai đoạn <- dev. Imo vẫn là giải pháp đơn giản nhất
Joseph Briggs

14

Bạn có thể thêm cam kết vào tùy chọn --merged. Bằng cách này, bạn có thể đảm bảo chỉ xóa các nhánh được hợp nhất thành gốc / gốc

Lệnh sau sẽ loại bỏ các chi nhánh hợp nhất từ ​​nguồn gốc của bạn.

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete 

Bạn có thể kiểm tra những nhánh nào sẽ bị xóa thay thế nguồn gốc git đẩy - xóa bằng tiếng vang

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo

2
Tôi thích tùy chọn kiểm tra
iwein

12

Tôi sử dụng tập lệnh Ruby sau để xóa các nhánh cục bộ và từ xa đã hợp nhất của mình. Nếu tôi đang làm điều đó cho một kho lưu trữ có nhiều điều khiển từ xa và chỉ muốn xóa từ một, tôi chỉ cần thêm một câu lệnh chọn vào danh sách điều khiển từ xa để chỉ nhận được điều khiển từ xa mà tôi muốn.

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

puts "Fetching merged branches..."
remote_branches= `git branch -r --merged`.
  split("\n").
  map(&:strip).
  reject {|b| b =~ /\/(#{current_branch}|master)/}

local_branches= `git branch --merged`.
  gsub(/^\* /, '').
  split("\n").
  map(&:strip).
  reject {|b| b =~ /(#{current_branch}|master)/}

if remote_branches.empty? && local_branches.empty?
  puts "No existing branches have been merged into #{current_branch}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end

Có phiền nếu tôi ăn cắp miếng ngon này cho một thư viện trợ giúp git nhỏ không? github.com/yupiq/git-branch-util
logan

1
Tiếp tục, tôi sẽ không đặt nó ở đây nếu tôi quan tâm đến việc mọi người sử dụng lại mã theo một cách nào đó
mmrobins

@mmrobins Bạn có thêm \/vào đầu câu lệnh từ chối cho remote_branchesdòng. Đó có phải là một lỗi đánh máy hay nó phục vụ một mục đích?
Jawwad

@mmrobins, ồ, đừng bận tâm, tôi thấy b.split(/\//)dòng này ngay bây giờ
Jawwad

Nếu bạn muốn làm điều này về cơ bản nhưng thông qua vanilla bash chứ không phải ruby: stackoverflow.com/a/37999948/430128
Raman

11

Cách xóa các nhánh được hợp nhất trong bảng điều khiển PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Nếu bạn muốn loại trừ tên chính hoặc bất kỳ tên nhánh nào khác, bạn có thể đặt ống với Chuỗi chọn PowerShell như thế này và chuyển kết quả cho git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})

1
Câu trả lời cao hơn đang đề xuất lọc chủ hoặc các nhánh khác. Đối với những người tìm kiếm để làm điều đó trong powershell: git chi nhánh - kết hợp | findstr / v "chủ" | % {git chi nhánh -d $ _. trim ()}
tredzko

@tredzko Điểm tốt. FTR câu trả lời cao hơn là stackoverflow.com/questions/6127328/ trên - bạn có thể đăng lại nhận xét của mình với liên kết đó và sau đó tôi sẽ xóa câu này
Ruben Bartelink

nó cũng cố xóa * master:)
iesen

9

Câu trả lời của kuboon đã bỏ qua việc xóa các nhánh có từ chủ trong tên nhánh. Sau đây cải thiện câu trả lời của mình:

git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin

Tất nhiên, nó không xóa chi nhánh "chính" :)


8

Không có lệnh nào trong Git sẽ tự động làm điều này cho bạn. Nhưng bạn có thể viết một tập lệnh sử dụng các lệnh Git để cung cấp cho bạn những gì bạn cần. Điều này có thể được thực hiện theo nhiều cách tùy thuộc vào mô hình phân nhánh bạn đang sử dụng.

Nếu bạn cần biết nếu một nhánh đã được sáp nhập vào master, lệnh sau sẽ không mang lại đầu ra nếu myTopicBranch đã được hợp nhất (tức là bạn có thể xóa nó)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

Bạn có thể sử dụng lệnh nhánh Git và phân tích tất cả các nhánh trong Bash và thực hiện một forvòng lặp trên tất cả các nhánh. Trong vòng lặp này, bạn kiểm tra bằng lệnh trên nếu bạn có thể xóa chi nhánh hay không.



7

Lưu ý : Tôi không hài lòng với các câu trả lời trước đó, (không hoạt động trên tất cả các hệ thống, không hoạt động trên điều khiển từ xa, không chỉ định nhánh - đã trộn, không lọc chính xác). Vì vậy, tôi thêm câu trả lời của riêng tôi.

Có hai trường hợp chính:

Địa phương

Bạn muốn xóa các chi nhánh địa phương được đã sáp nhập vào một chi nhánh địa phương . Trong quá trình xóa, bạn muốn giữ một số nhánh quan trọng, như chủ, phát triển, v.v.

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

Ghi chú :

  • git branch output --format ".." là loại bỏ khoảng trắng và cho phép kết hợp chính xác grep
  • grep -Eđược sử dụng thay vì egrep , vì vậy nó cũng hoạt động trong các hệ thống không có egrep (ví dụ: git cho windows).
  • grep -E -v '^master$|^feature/develop$' là chỉ định các chi nhánh địa phương mà tôi không muốn xóa
  • xargs -n 1 git branch -d: thực hiện xóa các chi nhánh địa phương (nó sẽ không hoạt động cho những người ở xa)
  • tất nhiên bạn sẽ gặp lỗi nếu bạn cố gắng xóa chi nhánh hiện đang thanh toán. Vì vậy, tôi đề nghị chuyển sang làm chủ trước.

Xa xôi

Bạn muốn xóa chi nhánh từ xa được đã sáp nhập vào một chi nhánh từ xa . Trong quá trình xóa, bạn muốn giữ một số nhánh quan trọng, như CHÍNH, chủ, phát hành, v.v.

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

Ghi chú :

  • đối với điều khiển từ xa, chúng tôi sử dụng -rtùy chọn và cung cấp tên chi nhánh đầy đủ :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' là để phù hợp với các chi nhánh từ xa mà chúng tôi không muốn xóa.
  • cut -d/ -f2-: loại bỏ tiền tố 'origin /' không cần thiết mà mặt khác được in ra bằng git branchlệnh.
  • xargs -n 1 git push --delete origin : thực hiện xóa các nhánh từ xa.

7

Nếu bạn đang ở trên Windows, bạn có thể sử dụng Windows Powershell hoặc Powershell 7 với Out-GridView để có một danh sách các nhánh đẹp và chọn bằng chuột mà bạn muốn xóa:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

nhập mô tả hình ảnh ở đây sau khi nhấp vào OK Powershell sẽ chuyển tên nhánh này để ra git branch -dlệnh và xóa chúng nhập mô tả hình ảnh ở đây


6

Bạn có thể sử dụng git-del-br công cụ .

git-del-br -a

Bạn có thể cài đặt nó thông qua pipviệc sử dụng

pip install git-del-br

PS: Tôi là tác giả của công cụ. Bất kỳ đề xuất / phản hồi đều được chào đón.


1
@ stackoverflow.com/users/100297/martijn-pieters : Tại sao câu trả lời này bị xóa và bỏ xuống?
tusharmakkar08

1
Câu trả lời và công cụ của bạn không hoạt động. Tôi dành một vài giờ cho nó. Không có gì.
SpoiledTechie.com

@ SpoiledTechie.com: Bạn có thể cho tôi biết chính xác vấn đề bạn đang gặp phải không? Tôi đang sử dụng nó một cách thường xuyên.
tusharmakkar08

Tôi có thể chia sẻ ảnh chụp màn hình nếu bạn muốn chụp ảnh ngoại tuyến này? spoiledtechie tại điều google mail. :)
SpoiledTechie.com

5

Nếu bạn muốn xóa tất cả các chi nhánh địa phương đã được hợp nhất vào chi nhánh mà bạn hiện đang hoạt động, thì tôi đã đưa ra một lệnh an toàn để làm như vậy, dựa trên các câu trả lời trước đó:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

Lệnh này sẽ không ảnh hưởng đến chi nhánh hiện tại của bạn hoặc chi nhánh chính của bạn. Nó cũng sẽ cho bạn biết những gì nó đang làm trước khi thực hiện nó, sử dụng cờ -t của xargs.



5

Tôi sử dụng sơ đồ đặt tên esque git-Flow, vì vậy cách này hoạt động rất an toàn đối với tôi:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Về cơ bản, nó tìm kiếm các cam kết hợp nhất bắt đầu bằng chuỗi fix/hoặc feature/.


4

Hãy thử lệnh sau:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Bằng cách sử dụng git rev-parsesẽ có được tên chi nhánh hiện tại tại để loại trừ nó. Nếu bạn gặp lỗi, điều đó có nghĩa là không có chi nhánh địa phương để loại bỏ.

Để thực hiện tương tự với các nhánh từ xa (thay đổi originbằng tên từ xa của bạn), hãy thử:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Trong trường hợp bạn có nhiều điều khiển từ xa, hãy thêm grep origin |trước cutđể chỉ lọc origin.

Nếu lệnh trên không thành công, hãy thử xóa các nhánh theo dõi từ xa đã hợp nhất trước:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Sau đó git fetchđiều khiển từ xa một lần nữa và sử dụng git push -vdlệnh trước đó một lần nữa.

Nếu bạn đang sử dụng nó thường xuyên, hãy xem xét thêm dưới dạng bí danh vào ~/.gitconfigtệp của bạn .

Trong trường hợp bạn đã xóa một số chi nhánh do nhầm lẫn, hãy sử dụng git reflogđể tìm các cam kết bị mất.


4

Dựa trên một số câu trả lời này, tôi đã tạo ra kịch bản Bash của riêng mình để làm điều đó !

Nó sử dụng git branch --mergedgit branch -dxóa các nhánh đã được hợp nhất và nhắc bạn cho từng nhánh trước khi xóa.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}

4

Dưới đây truy vấn làm việc cho tôi

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

và điều này sẽ lọc bất kỳ nhánh nào trong ống grep.

Hoạt động tốt trên http clone, nhưng không tốt cho kết nối ssh.


4

Tính đến 2018,07

Thêm phần này vào [alias]phần của bạn ~/.gitconfig:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Bây giờ bạn chỉ có thể gọi git sweepđể thực hiện việc dọn dẹp cần thiết.


Đối với tôi, gọi git quét chỉ liệt kê các nhánh cần được dọn sạch, nhưng nó không xóa chúng
Victor Moraes

4

Trên Windows có cài đặt git bash egrep -v sẽ không hoạt động

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

nơi grep -E -vtương đương vớiegrep -v

Sử dụng -dđể loại bỏ đã sáp nhập chi nhánh hoặc -Dđể loại bỏ Đã hủy hợp nhất chi nhánh


egrep -v làm việc cho tôi. Tôi đang sử dụng gitbash từ trình cài đặt gitextensions
Joe Phillips

4

Tôi đã sử dụng phương pháp sau để xóa các nhánh cục bộ VÀ từ xa được hợp nhất trong một cmd.

Tôi có những điều sau đây trong bashrctập tin của mình :

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
  local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
  if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

ban đầu nguồn

Điều này không xóa nhánh chính, nhưng loại bỏ các nhánh cục bộ VÀ từ xa đã hợp nhất . Khi bạn có tệp này trong tệp RC, chỉ cần chạy rmb, bạn sẽ thấy một danh sách các nhánh được hợp nhất sẽ được làm sạch và yêu cầu xác nhận về hành động. Bạn có thể sửa đổi mã để không yêu cầu xác nhận, nhưng có lẽ tốt để giữ nó.


3

Viết một kịch bản trong đó Git kiểm tra tất cả các nhánh đã được hợp nhất thành chủ.

Rồi làm git checkout master.

Cuối cùng, xóa các chi nhánh hợp nhất.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done

3

Giải pháp được chấp nhận là khá tốt, nhưng có một vấn đề là nó cũng xóa các nhánh cục bộ chưa được hợp nhất vào một điều khiển từ xa.

Nếu bạn nhìn vào đầu ra của bạn sẽ thấy một cái gì đó như

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

Chi nhánh blaissue_248là chi nhánh địa phương sẽ bị xóa âm thầm.

Nhưng bạn cũng có thể thấy từ này [gone], cho biết các nhánh đã được đẩy đến một điều khiển từ xa (hiện đã biến mất) và do đó biểu thị các nhánh có thể bị xóa.

Do đó, câu trả lời ban đầu có thể được thay đổi thành (tách thành multiline cho chiều dài dòng ngắn hơn)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

để bảo vệ các chi nhánh chưa sáp nhập. Ngoài ra, grepping cho chủ để bảo vệ nó, là không cần thiết, vì điều này có một điều khiển từ xa có nguồn gốc và không hiển thị như đã biến mất.


3

Đối với tôi git branch --mergedkhông hiển thị các chi nhánh được hợp nhất thông qua GitHub PR. Tôi không chắc chắn về lý do, nhưng tôi sử dụng dòng sau để xóa tất cả các nhánh cục bộ không có nhánh theo dõi từ xa :

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

Giải trình:

  • git branch --format "%(refname:short)" đưa ra một danh sách các chi nhánh địa phương
  • git branch -r | grep -v HEAD | cut -d/ -f2- đưa ra một danh sách các chi nhánh từ xa, lọc ra HEAD
  • diff <(...) <(...) đưa ra một khác biệt đầu ra của hai lệnh bên trong dấu ngoặc đơn
  • grep '<' lọc các nhánh tồn tại trong danh sách đầu tiên, nhưng không có trong thứ hai
  • cut -c 3- đưa ra dòng bắt đầu từ ký tự thứ 3, do đó loại bỏ tiền tố <
  • xargs git branch -Dthực hiện git branch -Dđối với từng tên chi nhánh

Ngoài ra, bạn có thể tránh grep -v '<'như thế này:

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.