ฉันจะลบสาขา Git ทั้งหมดที่ถูกผสานได้อย่างไร


1935

ฉันมีสาขา Git มากมาย ฉันจะลบสาขาที่รวมอยู่แล้วได้อย่างไร มีวิธีง่าย ๆ ในการลบทั้งหมดแทนที่จะลบทีละรายการหรือไม่


46
หากต้องการเฉพาะเจาะจงมากขึ้นgit branch -Dจะลบสาขาใด ๆ ไม่ว่าจะเป็นการผสานหรือไม่ก็ตาม
PhilT

12
คุณสามารถทำได้โดยตรงจาก GitHub หากคุณไปที่ส่วน 'สาขา' ของ repo ของคุณ (เช่นgithub.com/<username>/<repo_name>/branches ) ควรมีรายชื่อสาขาทั้งหมดของคุณพร้อมกับไอคอนถังขยะสีแดงที่ด้านข้างซึ่งจะลบสาขาที่เลือก เร็วกว่าการทำใน terminal! จะแสดงให้เห็นว่าmasterแต่ละสาขาอยู่ข้างหน้า / หลัง แต่ลูกค้าในท้องถิ่นของคุณจะยังคงรายชื่อสาขาเก่าถ้าคุณทำงานgit branch -a; ใช้git fetch --pruneเพื่อลบพวกเขา (ตามคำตอบนี้ )
user5359531

3
Script การทำเช่นนี้ท้องถิ่นหรือระยะไกล - มีการตรวจสอบความปลอดภัยและการกำหนดค่าล่วงหน้า "สาขาปลอดภัย": github.com/fatso83/dotfiles/tree/master/utils/... git delete-merged --doit originหรือgit delete-merged --doit --local
oligofren

นอกจากนี้คุณยังสามารถใช้แอพนี้เพื่อลบสาขาที่ผสานโดยอัตโนมัติ
Sebass van Boxel

rm -fr work && git clone http://example.com/work.gitในช่วงหลายปีที่ผ่านมาได้กลายเป็นวิธีที่ง่ายที่สุดในการออกจากดองกับคอมไพล์
Reactgular

คำตอบ:


3115

UPDATE:

คุณสามารถเพิ่มสาขาอื่น ๆ เพื่อแยกเช่น master และ dev หากเวิร์กโฟลว์ของคุณมีบรรพบุรุษเป็นไปได้ โดยปกติฉันแยกออกจากแท็กและต้นแบบ "sprint-start" และ dev และ qa ไม่ใช่บรรพบุรุษ

ขั้นแรกให้แสดงรายการสาขาทั้งหมดที่รวมอยู่ในรีโมท

git branch --merged

คุณอาจเห็นบางสาขาที่คุณไม่ต้องการลบ เราสามารถเพิ่มอาร์กิวเมนต์บางอย่างเพื่อข้ามสาขาที่สำคัญที่เราไม่ต้องการลบเช่นเจ้านายหรือนักพัฒนา คำสั่งต่อไปนี้จะข้ามสาขาหลักและสิ่งใดก็ตามที่มีอยู่ในนั้น

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

หากคุณต้องการข้ามคุณสามารถเพิ่มลงในคำสั่ง egrep ได้ดังต่อไปนี้ สาขาskip_branch_nameจะไม่ถูกลบ

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

หากต้องการลบสาขาท้องถิ่นทั้งหมดที่รวมอยู่ในสาขาที่เช็คเอาท์แล้ว:

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

คุณจะเห็นว่าเจ้านายและ dev นั้นถูกแยกออกในกรณีที่พวกเขาเป็นบรรพบุรุษ


คุณสามารถลบสาขาท้องถิ่นที่ผสานด้วย:

git branch -d branchname

หากยังไม่ได้รวมใช้:

git branch -D branchname

หากต้องการลบออกจากการใช้ระยะไกล:

git push --delete origin branchname

git push origin :branchname    # for really old git

เมื่อคุณลบสาขาจากระยะไกลคุณสามารถตัดเพื่อกำจัดสาขาติดตามระยะไกลด้วย:

git remote prune origin

หรือตัดสาขาการติดตามระยะไกลแต่ละอันตามคำตอบอื่น ๆ ที่แสดงด้วย:

git branch -dr branchname

หวังว่านี่จะช่วยได้


46
คำเตือน: หากคุณเพิ่งสร้างสาขามันจะลบสาขานั้นด้วย ตรวจสอบให้แน่ใจว่าไม่มีสาขาที่สร้างขึ้นใหม่ในรายการก่อนที่คุณจะรันคำสั่งส่วนใหญ่
Gary Haran

153
OPPOSITE OF WARNING: reflog จะบันทึกเบคอนของคุณ ดังนั้นไม่ต้องกังวล
Adam Dymitruk

33
โปรดทราบว่าคำสั่งแรกจะลบเฉพาะสาขาในพื้นที่เท่านั้นดังนั้นจึงไม่อันตรายเท่าที่บางคนชี้
ifightcrime

79
PowerShell รุ่นที่แตกต่างกันเพื่อให้ฉันสามารถค้นหาได้ที่นี่ในครั้งต่อไปฉัน googled คำตอบ:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou

23
สิ่งนี้จะทำให้เกิดข้อผิดพลาดfatal: branch name requiredหากคุณไม่มีสาขาที่ควรลบ เพื่อหลีกเลี่ยงการที่คุณสามารถผ่าน-rไปxargsได้มันจะไม่ทำงานgit branch -dหาก stdin ว่างเปล่า (นี่คือส่วนขยาย GNU xargs ตามหน้า man)
Marius Gedminas

457

หากต้องการลบสาขาทั้งหมดบนรีโมตที่ถูกผสานแล้ว:

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

ใน Git รุ่นล่าสุด

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

อัปเดต (โดย @oliver เนื่องจากไม่พอดีในความคิดเห็น แต่มีคำตอบเพียงพอแล้ว) : หากคุณอยู่ในสาขา ABC แล้ว ABC จะปรากฏในผลลัพธ์ของgit branch -r --mergedเนื่องจากไม่ได้ระบุสาขาดังนั้นค่าเริ่มต้นของสาขาจะเป็นสาขาปัจจุบันและสาขา มีคุณสมบัติเสมอเมื่อรวมเข้ากับตัวเอง (เพราะไม่มีความแตกต่างระหว่างสาขาและตัวเอง!)

ดังนั้นโปรดระบุสาขา:

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

หรือครูชำระเงินครั้งแรก:

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

18
คำตอบที่ดีที่สุดโดยไกล เพียงแค่ทราบสาขาหลักของฉันชื่อdevดังนั้นฉันจึงต้องเปลี่ยนที่
โดเรียน

41
ฉันต้องเพิ่ม| grep originหลังจากgrep -v masterเพื่อป้องกันการผลักสาขาของรีโมทอื่น ๆ ให้กำเนิด ขอแนะนำให้ทดสอบเอาท์พุทไว้ล่วงหน้าโดยใช้git branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4

9
ฉันปรับเปลี่ยนเล็กน้อยเพื่อแยกdevelopสาขาเช่นกัน git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. ตอนนี้กลายเป็นนามแฝงของฉัน
sarat

8
สิ่งที่ทำให้นี่เป็นคำตอบที่ดีที่สุดที่ฉันได้อ่านคือ-rข้อโต้แย้งที่ฉันไม่เคยเห็นมาก่อน มันรับมาว่าสาขาในประเทศเท่านั้นที่คุ้มค่าที่จะทำความสะอาด แต่รีโมทก็เต็มไปด้วยขยะด้วยเช่นกัน
Asbjørn Ulsberg

19
ข้อควรระวัง - เพิ่งตระหนัก: นี้เห็นได้ชัดว่าจะได้พบกับสาขารวมสาขาในปัจจุบันไม่ต้นแบบดังนั้นถ้าคุณอยู่ในมันจะเช็ดmyFeatureBranch origin/myFeatureBranchอาจเป็นการดีที่สุดgit checkout masterก่อน
jakub.g

190

เพียงแค่ขยายคำตอบของอดัมนิดหน่อย:

เพิ่มสิ่งนี้ในการกำหนดค่า Git ของคุณโดยการเรียกใช้ git config -e --global

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

git cleanupและจากนั้นคุณสามารถลบทุกสาขาที่ผสานท้องถิ่นทำง่ายๆ


11
คำสั่งแรกไม่ควรเป็น: git branch --merged masterเนื่องจากคุณต้องการดูสิ่งที่ถูกรวมเข้ากับต้นแบบไม่ได้เช็คเอาท์จากสาขาในปัจจุบัน?
Joe Phillips

@JoePhilllips บางคนมีสาขาหลักไม่ได้ต้นแบบ แต่แทนที่จะdevelopหรือdevและในกรณีที่คำสั่งจะล้มเหลวด้วยfatal: malformed object nameมันจะดีกว่าที่จะมีคำสั่งทั่วไปและคุณมีความรับผิดชอบในการทำงานได้
smohamed

1
@JoePhilllips จุดของคำตอบนี้คือการรวบรวมคำตอบของอดัม (คำตอบที่ดีที่สุดสำหรับคำถามนี้) ในนามแฝง git ที่เป็นประโยชน์ คำตอบของอดัมไม่ได้มีสิ่งที่คุณแนะนำและหลายคนพบว่ามีประโยชน์ดังนั้นฉันจะไม่เปลี่ยนใจ ฉันอยากจะแนะนำให้เปิดการอภิปรายเกี่ยวกับคำตอบของอดัมถ้าคุณรู้สึกอย่างจริงจังเกี่ยวกับเรื่องนี้
real_ate

13
การเพิ่ม-rลงในxargsจะป้องกันข้อผิดพลาดที่ไม่จำเป็น ( branch name required) เมื่อใช้ชื่อแทนนี้หลายครั้งหรือเมื่อไม่มีสาขาเหลือที่จะถูกลบ นามแฝงของฉันมีลักษณะเช่นนี้:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta

1
คำสั่งปัจจุบันไม่กรองต้นแบบและพัฒนาสาขา
Andriy F.

83

นอกจากนี้ยังใช้เพื่อลบสาขาที่ผสานทั้งหมดยกเว้นมาสเตอร์

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

3
ตอนนี้มันจะไม่ลบสาขาใด ๆ ที่มีmasterอยู่ในนั้น ลองgrep -v ^master$ตรงกลาง
wchargin

ฉันจะให้| grep -v '^\*'หลีกเลี่ยงการลบสาขาปัจจุบันหากคุณไม่ได้อยู่ในปริญญาโท
svassr

5
ขอบคุณมาก! grep -v '^ master$'หนึ่งข้อแม้สำหรับทุกคนที่ใช้นี้ทราบว่ามีสองช่องว่างใน หากคุณพิมพ์ด้วยตัวเองและพลาดคุณจะลบmasterถ้าคุณไม่ได้อยู่ในมัน
styger

3
@ Mr.Polywhirl การแก้ไขของคุณแบ่งคำสั่งและคุณควรจะเปลี่ยนมัน จำเป็นต้องเว้นวรรคสองช่องเนื่องจากgit branchจะแสดงชื่อแต่ละสาขาในบรรทัดใหม่โดยมีช่องว่างสองช่องทางด้านซ้ายหากไม่ใช่สาขาที่เช็คเอาท์ในปัจจุบัน คุณรับประกันได้ว่าใครก็ตามที่รันคำสั่งนี้จะลบสาขาหลักของพวกเขาเว้นแต่ว่ามันจะเป็นสาขาที่เช็คเอาท์ในปัจจุบัน
styger

79

คุณจะต้องการยกเว้นmaster& developสาขาจากคำสั่งเหล่านั้น

ล้างคอมไพล์ท้องถิ่น:

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

ล้าง git จากระยะไกล:

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

ซิงค์การลงทะเบียนโลคัลของรีโมตสาขา:

git fetch -p

3
+1 สำหรับเวอร์ชันรีโมตเช่นกัน (แต่จำเป็นน้อยกว่าเนื่องจากเรามีรีโมต --prune) นอกจากนี้ยังควรระวังว่าสิ่งเหล่านี้จะไม่ทำงานกับเวอร์ชัน git รุ่นเก่า
malko

4
git config --global --add fetch.prune trueเพื่อตัดโดยอัตโนมัติเมื่อดึงหรือดึง
T3rm1

1
ใจคุณพรุนไม่เหมือนกับระยะไกลที่ชัดเจน ล้างระยะไกลจริงลบสาขาระยะไกลที่ผสานอย่างเต็มที่กับสาขาปัจจุบันของคุณ ลูกพรุนทำความสะอาดเฉพาะรีจิสตรีในระยะไกลของสาขาที่ถูกลบไปแล้ว
Guido Bouman

คำนี้เป็นคำที่ทำให้เข้าใจผิดเล็กน้อยเนื่องจากจะมีการพิจารณาการรวมสาขาเมื่อถูกรวมก่อน แต่มีคอมมิตใหม่หลังจากการผสานซึ่งไม่ถูกผสาน
สโคน

ในการลบรีโมทต้นทางทั้งหมดในการโทรครั้งเดียวฉันใช้สิ่งนี้:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley

48

สำหรับผู้ที่อยู่ใน Windows และชอบสคริปต์ PowerShell ต่อไปนี้เป็นสิ่งที่จะลบสาขาที่ผสานในพื้นที่:

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

13
เพื่อประโยชน์ในการอยากรู้อยากเห็นสิ่งนี้สามารถย่อให้สั้นลงได้ git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard

5
@IainBallard แน่นอนว่าฉันสามารถใช้นามแฝงได้ ไม่แนะนำเมื่อคุณต้องการเพิ่มความสามารถในการอ่านสูงสุด github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn

1
แน่ใจ ฉันพบว่าคำตอบของคุณมีประโยชน์มาก :-) อย่างไรก็ตามบางครั้งไวยากรณ์ PowerShell แบบยาวได้รับสิ่งที่เกิดขึ้นในบล็อก แต่โดยพื้นฐานแล้วฉันกำลังหยิบยกสิ่งที่คุณอาจคัดลอก / วางหรือพิมพ์เป็นครั้งเดียว ขอบคุณอีกครั้ง.
เลน Ballard

4
นี่คือหนึ่งซับสำหรับเชลล์ cmd ของ Windows ที่รักษาต้นแบบและสาขาปัจจุบันของคุณ: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(ถอนหายใจแทนที่ backquotes สองครั้งด้วยซิงเกิ้ลฉันไม่แน่ใจว่าจะจัดรูปแบบตัวอักษรที่มี backquotes ได้อย่างไร
yoyo

42

ฉันใช้คำตอบของอดัมมาหลายปีแล้ว ที่กล่าวว่ามีบางกรณีที่มันไม่ทำงานตามที่ฉันคาดไว้:

  1. สาขาที่มีคำว่า "master" ถูกละเว้นเช่น "notmaster" หรือ "masterful" แทนที่จะเป็นเพียงสาขาหลัก
  2. สาขาที่มีคำว่า "dev" ถูกเพิกเฉยเช่น "dev-test" มากกว่าเฉพาะสาขา dev
  3. การลบสาขาที่สามารถเข้าถึงได้จาก HEAD ของปัจจุบันสาขา (นั่นคือไม่จำเป็นต้องเป็นหลัก)
  4. ในสถานะ HEAD เดี่ยวการลบทุกสาขาที่สามารถเข้าถึงได้จากการกระทำปัจจุบัน

1 & 2 ตรงไปยังที่อยู่เพียงแค่เปลี่ยน regex 3 ขึ้นอยู่กับบริบทของสิ่งที่คุณต้องการ (เช่นลบสาขาที่ไม่ได้รวมเข้ากับมาสเตอร์หรือกับสาขาปัจจุบันของคุณ) 4 มีความเป็นไปได้ที่จะเกิดภัยพิบัติ (แม้ว่าจะสามารถกู้คืนได้git reflog) หากคุณดำเนินการนี้โดยไม่ตั้งใจในสถานะ HEAD เดี่ยว

ในที่สุดฉันต้องการให้สิ่งนี้อยู่ในสายการบินเดียวที่ไม่ต้องการสคริปต์แยก (Bash | Ruby | Python)

TL; DR

สร้างนามแฝง "sweep" คอมไพล์ที่ยอมรับการ-fตั้งค่าสถานะทางเลือก:

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

และเรียกใช้กับ:

git sweep

หรือ:

git sweep -f

คำตอบที่ยาวและละเอียด

มันง่ายที่สุดสำหรับฉันที่จะสร้าง repo git ตัวอย่างกับกิ่งไม้บางอย่างและมุ่งมั่นที่จะทดสอบพฤติกรรมที่ถูกต้อง:

สร้าง repo คอมไพล์ใหม่ด้วยการกระทำเพียงครั้งเดียว

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

สร้างสาขาใหม่

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

พฤติกรรมที่ต้องการ: เลือกสาขาที่ผสานทั้งหมดยกเว้น: master, development หรือcurrent

regex ดั้งเดิมพลาดสาขา "เก่ง" และ "notmaster":

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

ด้วย regex ที่อัปเดต (ซึ่งตอนนี้แยก "พัฒนา" มากกว่า "dev"):

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

สลับไปที่สาขา foo ทำการคอมมิชชันใหม่แล้วชำระเงินที่สาขาใหม่ foobar ตาม foo:

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

สาขาปัจจุบันของฉันคือ foobar และถ้าฉันเรียกใช้คำสั่งด้านบนอีกครั้งเพื่อแสดงรายการสาขาที่ฉันต้องการลบสาขา "foo" จะถูกรวมไว้แม้ว่ามันจะไม่ได้ถูกรวมเข้ากับมาสเตอร์:

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

อย่างไรก็ตามถ้าฉันเรียกใช้คำสั่งเดียวกันบนต้นแบบจะไม่รวมสาขา "foo":

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

และนี่เป็นเพราะgit branch --mergedค่าเริ่มต้นของ HEAD ของสาขาปัจจุบันหากไม่ได้ระบุไว้เป็นอย่างอื่น อย่างน้อยสำหรับขั้นตอนการทำงานของฉันฉันไม่ต้องการลบสาขาท้องถิ่นเว้นแต่ว่าพวกเขาจะถูกรวมเข้ากับข้อมูลหลักดังนั้นฉันจึงชอบตัวแปรต่อไปนี้:

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

สถานะ HEAD ที่แยกออก

การใช้พฤติกรรมเริ่มต้นของgit branch --mergedมีผลกระทบที่สำคัญยิ่งขึ้นในสถานะ HEAD ที่แยกออก:

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

สิ่งนี้จะลบสาขาที่ฉันเพิ่งเปิดใช้งาน "foobar" พร้อมกับ "foo" ซึ่งแทบจะไม่ได้ผลลัพธ์ที่ต้องการ อย่างไรก็ตามด้วยคำสั่งที่แก้ไขแล้วของเรา:

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

หนึ่งบรรทัดรวมถึงการลบจริง

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

ทั้งหมดถูกรวมเข้าเป็นนามแฝง "sweep" คอมไพล์

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

นามแฝงยอมรับการ-fตั้งค่าสถานะเพิ่มเติม พฤติกรรมเริ่มต้นคือการลบเฉพาะสาขาที่ถูกรวมเข้ากับมาสเตอร์ แต่-fแฟล็กจะลบสาขาที่ถูกรวมเข้ากับสาขาปัจจุบัน

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 configอะตอมใช่ไหม
VasiliNovikov

ที่จะจัดการกับตัวเลือก '-f' อาร์กิวเมนต์ (ถ้าผมเข้าใจคำถามของคุณได้อย่างถูกต้อง)
วน

1
แต่มันช่วยได้อย่างไร ฉันหมายถึงจุดเริ่มต้นของการแสดงออก, !f(){ git branch .... มันเป็นการประกาศฟังก์ชั่นใช่มั้ย ทำไมไม่เริ่มต้นโดยตรงกับgit branch ...?
VasiliNovikov

1
คุณพูดถูก แก้ไขคำตอบของฉันตาม ขอบคุณสำหรับตัวชี้!
วน

สิ่งต่อไปนี้จะไม่เหมือนกับโหมดไม่บังคับหรือไม่ git checkout master && git branch -d `git branch --merged` && git checkout - ยกเว้นว่ามันจะลบdevelopแต่อาจเป็นวิธีที่ง่ายกว่า
Guido Bouman


18

ใช้ Git เวอร์ชั่น 2.5.0:

git branch -d `git branch --merged`

16
สิ่งนี้สามารถลบmasterสาขา btw!
Wazery

4
จริง masterฉันจะใช้มันเมื่อฉันแน่ใจว่าฉัน
drautb

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

1
สิ่งนี้เป็นอันตรายหากคุณมีกระแสลองนึกภาพว่าคุณมีปรมาจารย์ <- stage <- dev ยังคงเป็นวิธีแก้ปัญหาที่ง่ายที่สุด
โจเซฟบริกส์

14

คุณสามารถเพิ่มความมุ่งมั่นในตัวเลือก --merged วิธีนี้คุณสามารถทำให้แน่ใจได้ว่าจะลบสาขาที่ถูกผสานเข้าด้วยกันเช่นที่มา / มาสเตอร์

คำสั่งดังต่อไปนี้จะลบสาขาที่ผสานออกจากต้นกำเนิดของคุณ

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

คุณสามารถทดสอบว่าสาขาใดจะถูกลบออกแทนที่ต้นกำเนิดการผลัก git - ลบด้วยเสียงสะท้อน

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

2
ฉันชอบตัวเลือกการทดสอบ
iwein

12

ฉันใช้สคริปต์ Ruby ต่อไปนี้เพื่อลบสาขาในพื้นที่และระยะไกลที่ผสานแล้วของฉัน หากฉันกำลังทำเพื่อที่เก็บที่มีรีโมตหลายตัวและต้องการเพียงลบออกจากอันเดียวฉันแค่เพิ่มคำสั่งที่เลือกลงในรายการรีโมตเพื่อรับรีโมตที่ฉันต้องการเท่านั้น

#!/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

รังเกียจไหมถ้าฉันขโมยชิ้นอาหารอันโอชะนี้สำหรับห้องสมุดผู้ช่วยเล็ก ๆ น้อย ๆ ? github.com/yupiq/git-branch-util
logan

1
ไปหาฉันจะไม่ใส่ที่นี่ถ้าฉันใส่ใจเกี่ยวกับผู้ใช้รหัสในทางใดทางหนึ่ง
mmrobins

@mmrobins คุณมีส่วนเสริม\/ที่จุดเริ่มต้นของคำสั่งปฏิเสธสำหรับremote_branchesบรรทัด นั่นเป็นคำที่พิมพ์ผิดหรือมีจุดประสงค์หรือไม่?
เยาวราช

@ mmrobins ไม่เป็นไรฉันเห็นb.split(/\//)บรรทัดแล้ว
Jawwad

หากคุณต้องการทำสิ่งนี้โดยทางวานิลลาทุบตีมากกว่าทับทิม: stackoverflow.com/a/37999948/430128
Raman

11

วิธีการลบสาขาที่ผสานในคอนโซล PowerShell

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

หากคุณต้องการยกเว้น หลักหรือชื่อสาขาอื่น ๆ คุณสามารถไพพ์ด้วย PowerShell Select-String เช่นนี้และส่งผลลัพธ์ไปที่git branch -d:

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

1
คำตอบที่สูงกว่าคือการแนะนำตัวกรองหลักหรือสาขาอื่น ๆ สำหรับผู้ที่ต้องการทำสิ่งนั้นใน powershell: git branch --merged | findstr / v "master" | % {git branch -d $ _. trim ()}
tredzko

@tredzko จุดที่ดี FTR คำตอบที่สูงกว่าคือstackoverflow.com/questions/6127328/ … - คุณสามารถโพสต์ความคิดเห็นของคุณใหม่ด้วยลิงค์ที่เชื่อมโยงจากนั้นฉันจะลบสิ่งนี้
Ruben Bartelink

นอกจากนี้ยังพยายามลบ* master:)
iesen

9

คำตอบของคูโบนพลาดการลบสาขาที่มีคำหลักในชื่อสาขา การปรับปรุงต่อไปนี้เกี่ยวกับคำตอบของเขา:

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

แน่นอนว่ามันไม่ได้ลบสาขา "มาสเตอร์" เอง :)


8

ไม่มีคำสั่งใน Git ที่จะทำสิ่งนี้ให้คุณโดยอัตโนมัติ แต่คุณสามารถเขียนสคริปต์ที่ใช้คำสั่ง Git เพื่อให้สิ่งที่คุณต้องการ สิ่งนี้สามารถทำได้หลายวิธีขึ้นอยู่กับรูปแบบการแตกแขนงที่คุณใช้

หากคุณจำเป็นต้องรู้ว่าสาขาได้ถูกรวมเข้ากับต้นแบบแล้วคำสั่งต่อไปนี้จะไม่ให้ผลลัพธ์ถ้า myTopicBranch ถูกผสาน (เช่นคุณสามารถลบได้)

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

คุณสามารถใช้คำสั่งกิ่ง Git และแยกสาขาทั้งหมดใน Bash และforวนรอบทุกสาขา ในลูปนี้คุณตรวจสอบด้วยคำสั่งด้านบนหากคุณสามารถลบสาขาหรือไม่


7

git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d จะลบสาขาท้องถิ่นทั้งหมดยกเว้นสาขาที่เช็คเอาท์ในปัจจุบันและ / หรือ masterจะลบทุกสาขายกเว้นท้องถิ่นในปัจจุบันการตรวจสอบออกสาขาและ

นี่คือบทความที่เป็นประโยชน์สำหรับผู้ที่ต้องการที่จะเข้าใจคำสั่งเหล่านี้: Git สะอาด: ลบสาขาผสานแล้วโดยสตีเวน Harman


7

หมายเหตุ : ฉันไม่พอใจกับคำตอบก่อนหน้า (ไม่ทำงานในทุกระบบไม่ทำงานในระยะไกลไม่ระบุสาขา - ที่ถูกฝังไม่ได้กรองอย่างแน่นอน) ดังนั้นฉันจึงเพิ่มคำตอบของตัวเอง

มีสองกรณีหลัก:

ในประเทศ

คุณต้องการลบสาขาในประเทศที่ถูกรวมไปยังสาขาท้องถิ่นอื่นแล้ว ในระหว่างการลบคุณต้องการเก็บสาขาที่สำคัญบางอย่างเช่นหลักพัฒนาและอื่น ๆ

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

หมายเหตุ :

  • git branch output --format ".. " คือการตัดช่องว่างและอนุญาตการจับคู่ grep ที่แน่นอน
  • grep -Eถูกใช้แทน egrepดังนั้นจึงสามารถทำงานได้ในระบบที่ไม่มี egrep (เช่น: git สำหรับ windows)
  • grep -E -v '^master$|^feature/develop$' คือการระบุสาขาท้องถิ่นที่ฉันไม่ต้องการลบ
  • xargs -n 1 git branch -d: ดำเนินการลบสาขาท้องถิ่น (จะไม่สามารถใช้งานได้สำหรับสาขาระยะไกล)
  • แน่นอนคุณได้รับข้อผิดพลาดหากคุณลองลบสาขาที่เช็คเอาท์ในปัจจุบัน ดังนั้นฉันขอแนะนำให้เปลี่ยนไปใช้ปริญญาโทก่อน

ห่างไกล

คุณต้องการลบสาขารีโมตที่ถูกรวมกับรีโมตสาขาอื่นแล้ว ในระหว่างการลบคุณต้องการเก็บสาขาที่สำคัญบางอย่างไว้เช่น HEAD, master, release ฯลฯ

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

หมายเหตุ :

  • สำหรับระยะไกลเราใช้-rตัวเลือกและระบุชื่อสาขาเต็ม :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' เป็นการจับคู่สาขาระยะไกลที่เราไม่ต้องการลบ
  • cut -d/ -f2-: ลบส่วนนำหน้า 'Origin /' ที่ไม่จำเป็นซึ่งพิมพ์ออกมาโดยgit branchคำสั่ง
  • xargs -n 1 git push --delete origin : ทำการลบสาขาระยะไกล

7

หากคุณใช้ Windows คุณสามารถใช้ Windows Powershell หรือ Powershell 7 กับOut-GridViewเพื่อให้มีรายการสาขาที่ดีและเลือกด้วยเมาส์ที่คุณต้องการลบ:

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

ป้อนคำอธิบายรูปภาพที่นี่ หลังจากคลิกตกลง Powershell จะส่งชื่อสาขาไปยังgit branch -dคำสั่งและลบออก ป้อนคำอธิบายรูปภาพที่นี่


6

คุณสามารถใช้เครื่องมือgit-del-br

git-del-br -a

คุณสามารถติดตั้งผ่านทางpipใช้

pip install git-del-br

PS: ฉันเป็นผู้สร้างเครื่องมือ ข้อเสนอแนะ / ข้อเสนอแนะยินดีต้อนรับ


1
@ stackoverflow.com/users/100297/martijn-pieters : ทำไมคำตอบนี้จึงถูกลบและลดระดับลง
tusharmakkar08

1
คำตอบและเครื่องมือของคุณไม่ทำงาน ฉันใช้เวลาสองสามชั่วโมงกับมัน ไม่มีอะไร
SpoiledTechie.com

@ SpoiledTechie.com: คุณช่วยบอกฉันว่าคุณประสบปัญหาอะไรบ้าง? ฉันใช้มันเป็นประจำ
tusharmakkar08

ฉันสามารถแชร์ภาพหน้าจอได้ไหมถ้าคุณต้องการออฟไลน์? นิสัยเสียที่สิ่งที่ google mail :)
SpoiledTechie.com

5

หากคุณต้องการที่จะลบสาขาท้องถิ่นทั้งหมดที่รวมอยู่ในสาขาที่คุณอยู่ในปัจจุบันแล้วฉันจะได้คำสั่งที่ปลอดภัยที่จะทำตามคำตอบก่อนหน้านี้:

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

คำสั่งนี้จะไม่ส่งผลกระทบต่อสาขาปัจจุบันหรือสาขาหลักของคุณ มันจะบอกคุณว่ามันทำอะไรก่อนที่มันจะทำได้โดยใช้แฟล็ก -t ของ xargs



5

ฉันใช้รูปแบบการตั้งชื่อแบบ git-flow ดังนั้นนี่จึงทำงานได้อย่างปลอดภัยสำหรับฉัน:

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

มันเป็นพื้นมองหาที่ผสานกระทำที่เริ่มต้นด้วยสตริงอย่างใดอย่างหนึ่งหรือfix/feature/


4

ลองคำสั่งต่อไปนี้:

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

โดยใช้git rev-parseจะได้รับชื่อสาขาปัจจุบันเพื่อที่จะไม่รวมมัน หากคุณได้รับข้อผิดพลาดนั่นหมายความว่าไม่มีสาขาท้องถิ่นที่จะลบ

หากต้องการทำเช่นเดียวกันกับสาขารีโมต (เปลี่ยนoriginชื่อรีโมตของคุณ) ให้ลอง:

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

ในกรณีที่คุณได้รีโมทหลายเพิ่มgrep origin |ก่อนที่จะกรองเท่านั้นcutorigin

หากคำสั่งด้านบนล้มเหลวให้ลองลบสาขาการติดตามระยะไกลที่ถูกผสานก่อน:

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

จากนั้นgit fetchรีโมตอีกครั้งและใช้ก่อนหน้านี้git push -vdคำสั่งอีกครั้ง

หากคุณใช้บ่อยให้เพิ่มชื่อแทนลงใน ~/.gitconfigไฟล์

ในกรณีที่คุณลบบางสาขาโดยไม่ได้ตั้งใจให้ใช้git reflogเพื่อค้นหาการกระทำที่สูญหาย


4

จากคำตอบบางส่วนฉันได้สร้างBash script ของตัวเองขึ้นมาด้วย !

มันใช้git branch --mergedและgit branch -dเพื่อลบสาขาที่ได้รับการผสานและแจ้งให้คุณสำหรับแต่ละสาขาก่อนที่จะลบ

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

แบบสอบถามด้านล่างใช้งานได้สำหรับฉัน

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

และสิ่งนี้จะกรองสาขาใดก็ตามในท่อ grep

ทำงานได้ดีบน http โคลน แต่ไม่ดีสำหรับการเชื่อมต่อ ssh


4

ตั้งแต่ 2018.07

เพิ่มไปยัง[alias]ส่วนของของคุณ~/.gitconfig:

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

ตอนนี้คุณสามารถโทรติดต่อgit sweepเพื่อทำการล้างข้อมูลที่จำเป็น


สำหรับฉันการเรียก git sweep แสดงเฉพาะสาขาที่ควรล้าง แต่ไม่ได้ลบออก
Victor Moraes

4

บน Windows ที่ติดตั้งgit bashแล้ว egrep -v จะไม่ทำงาน

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

ที่ไหน grep -E -vเทียบเท่าegrep -v

ใช้-dในการลบแล้วรวมสาขาหรือ -Dที่จะลบได้ผสานรวมสาขา


egrep -v ใช้งานได้สำหรับฉัน ฉันใช้ gitbash จากตัวติดตั้ง gitextensions
Joe Phillips

4

ฉันใช้วิธีต่อไปนี้เพื่อลบสาขาในพื้นที่และระยะไกลแบบผสานในหนึ่ง cmd

ฉันมีสิ่งต่อไปนี้ในbashrcไฟล์ของฉัน:

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
}

เดิมแหล่งที่มา

นี้ไม่ได้ลบสาขาต้นแบบ แต่เอารวมสาขาท้องถิ่นและระยะไกล เมื่อคุณมีสิ่งนี้ในไฟล์ rc ของคุณแล้วให้เรียกใช้rmbคุณจะเห็นรายการของสาขาที่ผสานซึ่งจะได้รับการล้างและถามเพื่อยืนยันการดำเนินการ คุณสามารถปรับเปลี่ยนรหัสเพื่อไม่ขอการยืนยันได้เช่นกัน แต่อาจเป็นการดีที่จะเก็บไว้


3

เขียนสคริปต์ที่ Git ตรวจสอบทุกสาขาที่รวมเข้ากับมาสเตอร์

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

โซลูชันที่ได้รับการยอมรับนั้นค่อนข้างดี แต่มีประเด็นหนึ่งที่จะลบสาขาท้องถิ่นที่ยังไม่ได้รวมเข้ากับรีโมท

ถ้าคุณดูผลลัพธ์ของคุณจะเห็นว่า

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

สาขาblaและissue_248เป็นสาขาท้องถิ่นที่จะถูกลบอย่างเงียบ ๆ

แต่คุณยังสามารถเห็นคำ[gone]ที่ระบุสาขาที่ถูกผลักไปที่รีโมต (ซึ่งตอนนี้หายไปแล้ว) ดังนั้นจึงสามารถลบสาขาได้

คำตอบเดิมสามารถเปลี่ยนเป็น (แบ่งเป็นหลายบรรทัดสำหรับความยาวบรรทัดที่สั้นกว่า)

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

เพื่อป้องกันสาขาที่ยังไม่ถูกผสาน นอกจากนี้ยังมี grepping สำหรับต้นแบบเพื่อป้องกันไม่จำเป็นเช่นนี้มีรีโมทที่จุดเริ่มต้นและไม่ปรากฏขึ้นเป็นไป


3

สำหรับฉันgit branch --mergedไม่แสดงสาขาที่รวมเข้าด้วยกันผ่าน GitHub PR ฉันไม่แน่ใจด้วยเหตุผล แต่ฉันใช้บรรทัดต่อไปนี้เพื่อลบสาขาท้องถิ่นทั้งหมดที่ไม่มีสาขาการติดตามระยะไกล :

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

คำอธิบาย:

  • git branch --format "%(refname:short)" ให้รายการสาขาท้องถิ่น
  • git branch -r | grep -v HEAD | cut -d/ -f2- ให้รายชื่อของสาขาระยะไกลกรองออก HEAD
  • diff <(...) <(...) ให้ผลต่างของเอาต์พุตของสองคำสั่งในวงเล็บ
  • grep '<' กรองสาขาที่มีอยู่ในรายการแรก แต่ไม่ได้อยู่ในรายการที่สอง
  • cut -c 3- ให้บรรทัดเริ่มต้นจากตัวอักษรที่ 3 จึงลบคำนำหน้า <
  • xargs git branch -Dดำเนินการgit branch -Dกับแต่ละชื่อสาขา

หรือคุณสามารถหลีกเลี่ยงgrep -v '<'เช่นนี้

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.