ลบสาขาการติดตามไม่ได้อยู่ในระยะไกล


1172

มีวิธีง่ายๆในการลบสาขาติดตามทั้งหมดที่มีระยะไกลเทียบเท่าไม่อยู่อีกต่อไป?

ตัวอย่าง:

สาขา (ท้องถิ่นและระยะไกล)

  • เจ้านาย
  • ต้นกำเนิด / Master
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-A
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-B
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-C

ในพื้นที่ฉันมีสาขาหลักเท่านั้น ตอนนี้ฉันต้องทำงานกับbug-fix-aดังนั้นฉันจึงลองดูทำงานและผลักดันการเปลี่ยนแปลงไปยังรีโมต ต่อไปฉันทำเช่นเดียวกันกับข้อผิดพลาดแก้ไข-B

สาขา (ท้องถิ่นและระยะไกล)

  • เจ้านาย
  • ข้อผิดพลาดแก้ไข-A
  • ข้อผิดพลาดแก้ไข-B
  • ต้นกำเนิด / Master
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-A
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-B
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-C

ตอนนี้ฉันมีสาขาในประเทศต้นแบบ , ข้อผิดพลาดแก้ไข-A , ข้อผิดพลาดแก้ไข-B ผู้ดูแลสาขาหลักจะรวมการเปลี่ยนแปลงของฉันเข้ากับเจ้านายและลบสาขาทั้งหมดที่เขารวมไว้แล้ว

ดังนั้นสถานะปัจจุบันคือตอนนี้:

สาขา (ท้องถิ่นและระยะไกล)

  • เจ้านาย
  • ข้อผิดพลาดแก้ไข-A
  • ข้อผิดพลาดแก้ไข-B
  • ต้นกำเนิด / Master
  • ต้นกำเนิด / ข้อผิดพลาดแก้ไข-C

ตอนนี้ฉันต้องการเรียกบางคำสั่งเพื่อลบสาขา (ในกรณีนี้bug-fix-a , bug-fix-b ) ซึ่งไม่ได้แสดงอยู่ในที่เก็บระยะไกลอีกต่อไป

มันจะเป็นสิ่งที่ชอบคำสั่งที่มีอยู่แต่เหมือนgit remote prune origingit local prune origin

คำตอบ:


1282

git remote prune origin ลูกพรุนติดตามสาขาไม่ได้อยู่ในระยะไกล

git branch --merged แสดงรายการสาขาที่ถูกรวมเข้ากับสาขาปัจจุบัน

xargs git branch -d ลบสาขาที่ระบุในอินพุตมาตรฐาน

git branch --mergedจะลบสาขาระมัดระวังที่ระบุไว้โดย รายการอาจรวมถึงmasterหรือสาขาอื่น ๆ ที่คุณไม่ต้องการลบ

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

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

17
บรรทัดแรกของสาขาที่ผสานอยู่* masterในระบบของฉัน คำสั่งต่อไปนี้ใช้งานได้สำหรับฉัน:git branch -d $(git branch --merged |tail -n +2)
Trendfischer

99
ถ้าฉันรวมdevelopแล้ว! คุณอาจ (แน่นอน!) ไม่ต้องการลบมัน นอกจากนี้ฉันคิดว่ามันควรจะเป็นในกรณีที่ตัวพิมพ์เล็กหมายถึง "ลบอย่างปลอดภัย" เช่นลบเฉพาะเมื่อรวม git branch --mergedmastergit branch -d-d
thom_nic

11
ดูเหมือนว่าวิธีการแก้ปัญหาที่ดีขึ้นมีให้มี
Sergey Brunov

34
การผสานที่ถูกลบออกมีประโยชน์ แต่ไม่เหมือนกับ "เอากิ่งที่ไม่ได้อยู่บนรีโมทออก"
dlsso

11
เพียงแค่ใช้ grep เพื่อแยกมาสเตอร์:git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
Geniass

589

หลังจากคำสั่ง

git fetch -p

ลบการอ้างอิงระยะไกลเมื่อคุณเรียกใช้

git branch -vv

มันจะแสดง 'หายไป' เป็นสถานะระยะไกล ตัวอย่างเช่น,

$ 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

ดังนั้นคุณสามารถเขียนสคริปต์อย่างง่าย ๆ เพื่อลบสาขาในพื้นที่ที่ใช้รีโมท:

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

โปรดทราบว่าข้างต้นใช้คำสั่ง "Porcelain" git branchเพื่อรับสถานะต้นน้ำ

อีกวิธีในการรับสถานะนี้คือการใช้คำสั่ง "การประปา" git for-each-refกับตัวแปรการแก้ไข%(upstream:track)ซึ่งจะ[gone]เหมือนกับข้างบน

วิธีนี้ค่อนข้างปลอดภัยกว่าเนื่องจากไม่มีความเสี่ยงในการจับคู่ข้อความที่ส่งโดยไม่ตั้งใจ

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

8
@KrzysztofWende - ไม่ใช่ใน Solaris และ BSD บางตัวและ OS X บางตัว :)
jww

4
ดูเหมือนว่าจะเป็นการลบสาขาใด ๆ ที่ "หายไป" ในข้อความยืนยันล่าสุด
dlsso

11
@dlsso หากข้อความคอมมิชชันล่าสุดมีสตริง ": หายไป]" ใช่แล้วมันจะถูกลบเช่นกัน คุณสามารถทำให้มันแข็งแกร่งขึ้นด้วยค่าใช้จ่ายของความเรียบง่ายโดยเพิ่ม awk / gawk เพิ่มเติมเพื่อตัดการส่งข้อความคอมมิท git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
jason.rickman

2
ในการตอบกลับความคิดเห็นก่อนหน้าของฉัน (คำถาม) สาขาปัจจุบันมี * เป็นฟิลด์แรก หากเป็นเช่นนั้นในรายการสาขา "ที่หายไป" จะมีการกำหนด $ 1 * และจะถูกตีความเป็นชื่อไฟล์ด้วย awk spitting out ชื่อไฟล์และโฟลเดอร์ ฉันยกเลิกการแสดงออก grep และได้ทำการกรองawk '/: gone]/{if ($1!="*") print $1}'ทั้งหมดแล้ว: . ตอนนี้ใช้งานได้ตามที่คาดไว้
rhaben

5
@ahmedbhs เนื่องจากคำสั่งใช้เครื่องหมายคำพูดเดี่ยว 'คุณต้องใช้เครื่องหมายคำพูดคู่ "เพื่อล้อมรอบคำสั่งทั้งหมดนอกจากนี้นามแฝง git ที่เป็นคำสั่งเชลล์ (เช่นนี้) ต้องใช้! ตอนเริ่มต้นสิ่งนี้ใช้ได้กับฉัน:test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
jason.rickman

306

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

  1. ตรวจสอบสาขาเริ่มต้นของคุณ มักจะgit checkout master
  2. วิ่ง git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

คำอธิบาย:

ทำงานโดยการตัดกิ่งติดตามของคุณจากนั้นลบสาขาท้องถิ่นที่แสดงว่า "หายไป" git branch -vvแล้ว

หมายเหตุ:

หากภาษาของคุณถูกตั้งค่าเป็นสิ่งอื่นที่ไม่ใช่ภาษาอังกฤษคุณจะต้องเปลี่ยนgoneเป็นคำที่เหมาะสม สาขาที่อยู่ในท้องถิ่นเท่านั้นจะไม่ถูกสัมผัส สาขาที่ถูกลบในระยะไกล แต่ไม่ได้ผสานจะแสดงการแจ้งเตือน แต่จะไม่ถูกลบในท้องถิ่น หากคุณต้องการที่จะลบเหล่านั้นเช่นการเปลี่ยนแปลงที่ดีในการ-d-D


2
สำหรับ OS ฝรั่งเศสต้องเปลี่ยนไปโดยไม่เห็นด้วย
โมฮาเหม็ด EL HABIB

4
ควรเพิ่ม LANG = en_US ก่อนสาขา git เพื่อบังคับใช้ภาษาอังกฤษ: เรียก git --prune && LANG = en_US สาขา git -vv | awk '/: หายไป] / {พิมพ์ $ 1}' | xargs git branch -d
Mohamed EL HABIB

3
ฉันจะเพิ่มgit checkout master && ...ที่จุดเริ่มต้นของคำสั่ง
iarroyo

2
สิ่งนี้เป็นอันตรายเมื่อคุณอยู่ในสาขาที่ควรจะลบ - ในกรณีนั้นคอลัมน์แรกคือ '*' ซึ่งจะถูกส่งไปยัง xargs เพื่อปรับปรุงสิ่งนี้เพิ่มแถบอักขระ '*' ก่อนส่งออกไปยัง awk: sed -e 's / ^ * //'
meeee

6
ระวัง! มีกรณีที่ทันสมัยที่จะมีผลในการลบสาขาในประเทศทั้งหมดของคุณคือ: ถ้าคุณกำลังอยู่ในสาขาที่ถูกลบในระยะไกลการส่งออกของที่จะเริ่มต้นด้วยเครื่องหมายดอกจันซึ่งจะสิ้นผลในการดำเนินการgit branch -vv git branch -d *นี่คือเวอร์ชันที่ถูกแก้ไขซึ่งจะละเว้นบรรทัดที่มีเครื่องหมายดอกจัน:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
kcm

210

ปกติฉันจะไม่ตอบคำถามที่มี 16 คำตอบอยู่แล้ว แต่คำตอบอื่น ๆ ทั้งหมดนั้นผิดและคำตอบที่ถูกต้องนั้นง่ายมาก คำถามกล่าวว่า "มีวิธีง่ายๆในการลบสาขาการติดตามทั้งหมดที่มีการเทียบระยะไกลไม่อยู่อีกต่อไปหรือไม่"

หาก "ง่าย" หมายถึงการลบพวกเขาทั้งหมดในครั้งเดียวไม่บอบบางไม่เป็นอันตรายและไม่ต้องพึ่งพาเครื่องมือที่ผู้อ่านไม่ทุกคนจะมีคำตอบที่ถูกต้องคือ: ไม่

คำตอบบางคำตอบนั้นง่าย แต่พวกเขาไม่ได้ทำในสิ่งที่ถูกถาม คนอื่นทำในสิ่งที่ถูกถาม แต่ไม่ง่าย: ทั้งหมดพึ่งพาการแยกวิเคราะห์ Git ผ่านคำสั่งการจัดการข้อความหรือภาษาสคริปต์ซึ่งอาจไม่ปรากฏในทุกระบบ ยิ่งไปกว่านั้นคำแนะนำส่วนใหญ่ใช้คำสั่ง Porcelain ซึ่งเอาต์พุตไม่ได้รับการออกแบบให้แยกวิเคราะห์โดยสคริปต์ ("Porcelain" หมายถึงคำสั่งที่มีไว้สำหรับการทำงานของมนุษย์สคริปต์ควรใช้คำสั่ง "plumbing" ระดับต่ำกว่า)

อ่านเพิ่มเติม:


หากคุณต้องการทำสิ่งนี้อย่างปลอดภัยสำหรับกรณีการใช้งานในคำถาม (สาขาการติดตามการเก็บรวบรวมขยะที่ถูกลบบนเซิร์ฟเวอร์ แต่ยังคงมีอยู่ในสาขาท้องถิ่น) และด้วยคำสั่ง Git ระดับสูงเท่านั้นคุณต้อง

  • git fetch --prune(หรือgit fetch -pซึ่งเป็นนามแฝงหรือgit prune remote originทำสิ่งเดียวกันโดยไม่ดึงข้อมูลและอาจไม่ใช่สิ่งที่คุณต้องการเป็นส่วนใหญ่)
  • โปรดทราบว่าสาขาระยะไกลใด ๆ ที่ถูกรายงานว่าถูกลบ หรือเพื่อค้นหาในภายหลังgit branch -v(สาขาติดตามเด็กกำพร้าใด ๆ จะถูกทำเครื่องหมาย "[หายไป]")
  • git branch -d [branch_name] ในแต่ละสาขาการติดตามกำพร้า

(ซึ่งเป็นคำตอบอื่น ๆ ที่เสนอ)

ถ้าคุณต้องการสคริปต์วิธีการแก้ปัญหาก็for-each-refคือจุดเริ่มต้นของคุณเช่นเดียวกับคำตอบของ Mark Longairที่นี่และคำตอบของคำถามอื่นแต่ฉันไม่เห็นวิธีที่จะใช้ประโยชน์จากมันโดยไม่ต้องเขียน shell script loop หรือใช้ xargs หรืออะไรบางอย่าง .


คำอธิบายพื้นหลัง

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

ที่กำหนดให้สาขาการติดตามfeature/X, พื้นที่เก็บข้อมูลระยะไกล (เซิร์ฟเวอร์) feature/Xจะมีสาขานี้และเรียกมันว่า ที่เก็บในเครื่องของคุณมีสาขาremotes/origin/feature/Xซึ่งหมายความว่า "นี่คือสิ่งที่รีโมทบอกฉันถึงคุณสมบัติ / สาขา X เป็นครั้งสุดท้ายที่เราพูดคุยกัน" และสุดท้ายพื้นที่เก็บข้อมูลในท้องถิ่นมีสาขาfeature/Xที่ชี้ไปที่การกระทำล่าสุดของคุณและกำหนดค่าให้ "ติดตาม"remotes/origin/feature/Xซึ่งหมายความว่าคุณสามารถดึงและดันเพื่อจัดตำแหน่งให้อยู่ในแนวเดียวกัน

ณ จุดหนึ่งมีคนลบfeature/Xบนระยะไกล จากช่วงเวลานั้นคุณเหลืออยู่กับท้องถิ่นของคุณfeature/X(ซึ่งคุณอาจไม่ต้องการอีกต่อไปเนื่องจากการทำงานในคุณสมบัติ X เสร็จสิ้นแล้ว) และสิ่งที่คุณremotes/origin/feature/Xไม่มีประโยชน์อย่างแน่นอนเพราะวัตถุประสงค์เพียงอย่างเดียวคือเพื่อจดจำสถานะของเซิร์ฟเวอร์สาขา .

และ Git จะช่วยให้คุณล้างข้อมูลซ้ำซ้อนโดยอัตโนมัติremotes/origin/feature/X- นั่นคือสิ่งที่git fetch --prune- แต่ด้วยเหตุผลบางอย่างมันไม่อนุญาตให้คุณลบข้อมูลของคุณเองโดยอัตโนมัติfeature/X... แม้ว่าคุณจะfeature/Xยังมีข้อมูลการติดตามเด็กกำพร้าอยู่ก็ตาม เพื่อระบุสาขาการติดตามเดิมที่ถูกผสานอย่างสมบูรณ์ (หลังจากที่ทุกคนก็สามารถให้คุณข้อมูลที่ช่วยให้คุณสามารถดำเนินการด้วยมือตัวเอง.)


3
นี่เป็นคำตอบที่ปลอดภัยกว่ามาก นอกจากนี้ยังใช้งานได้หากคุณใช้เวิร์กโฟลว์ "สควอชและผสาน" ซึ่งแตกต่างจากคำตอบที่เลือก
Jake Levitt

3
นี่เป็นคำตอบที่ง่ายเพียงส่วนเดียวของคำถาม "วิธีค้นหาสาขาที่หายไป" (และด้วยคำสั่งเดียวกับที่โพสต์แล้วโดย jason.rickman ในปี 2015) แต่จากนั้นบอกให้คุณลบสาขาทั้งหมดด้วยตนเองซึ่งเป็นสิ่งที่ OP ต้องการ ไม่อยากทำ
Voo

4
@Voo นั่นคือจุดประสงค์ของคำตอบ: อย่าบอกวิธีทำ (นั่นเป็นเพียงโบนัส) แต่บอกว่าคำตอบคือไม่มีวิธีง่าย ๆ ที่จะทำ ซึ่งเป็นคำตอบที่ถูกต้องสำหรับคำถามตามที่กำหนดไว้
Andrew Spencer

1
"ถ้าคุณต้องการทำสิ่งนี้อย่างปลอดภัยสำหรับกรณีการใช้งานในคำถาม .. " - ซึ่งคัดค้านการเรียกร้องส่วนใหญ่ของวรรคแรก "[Git] สามารถให้ข้อมูลที่ช่วยให้คุณสามารถดำเนินการด้วยตัวเองได้" - เราเป็นโปรแกรมเมอร์ดังนั้นเมื่อได้รับข้อมูลเป็นรายการ (ซึ่งแสดง) งานก็ยังคงง่าย (เช่นxargs) นอกจากนี้ยังมีgit aliasเพื่อลดความซับซ้อนของจำนวนกรณี
2864740

2
@ user2864740 ผู้อ่านบางคนอาจพิจารณาว่าการเขียนสคริปต์ทุบตีเล็ก ๆ นั้นอยู่ภายใต้คำจำกัดความของ "ง่าย" และนั่นเป็นตำแหน่งที่ป้องกันได้อย่างสมบูรณ์แบบ แต่ฉันให้การตีความ "ง่าย" ของตัวเองในย่อหน้าที่ 2 และคำตอบที่เหลือนั้นสอดคล้องกัน กับมัน และเพื่อป้องกันการตีความที่เข้มงวดของฉันผู้ใช้ Git ทุกคนมีxargsหรือทุบตีและพวกเขาอาจไม่ได้อยู่ที่นี่เพื่อมองหาความท้าทายในการเข้ารหัสขนาดเล็กมากพอ ๆ กับคำตอบด่วน ๆ ที่พวกเขาสามารถใช้ได้อย่างปลอดภัยโดยไม่รบกวนตนเองต่อเป้าหมายที่แท้จริง .
Andrew Spencer

52

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

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

ตรวจสอบให้แน่ใจว่าเรามีความเชี่ยวชาญ

คุณสามารถมั่นใจได้ว่าmasterหรือสาขาอื่น ๆ สำหรับเรื่องนั้นจะไม่ถูกลบออกโดยการเพิ่มสาขาอื่นgrepหลังจากสาขาแรก ในกรณีนี้คุณจะไป:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

ดังนั้นหากเราต้องการที่จะเก็บmaster, developและstagingสำหรับตัวอย่างเช่นเราจะไป:

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

ทำให้เป็นชื่อแทน

เพราะมันเป็นบิตนานคุณอาจต้องการเพิ่มนามแฝงที่คุณหรือ.zshrc .bashrcของฉันถูกเรียกgbpurge(สำหรับ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'

จากนั้นโหลดซ้ำของคุณ.bashrcหรือ.zshrc:

. ~/.bashrc

หรือ

. ~/.zshrc

8
มีประโยชน์ แต่ไม่เหมือนกันกับ "ลบสาขาที่ไม่ได้อยู่ในระยะไกล"
dlsso

คำตอบที่ดี @karlingen ฉันมีสิ่งนี้อย่างถาวรเหมือน gbpurge ในสภาพแวดล้อมการพัฒนาทั้งหมดของฉัน
Peter Dolan

50

โซลูชัน Windows

สำหรับ 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 เปลี่ยนเป็นสาขาหลัก

git remote update origin --prune พรุนสาขาระยะไกล

git branch -vvรับเอาต์พุต verbose ของทุกสาขา ( การอ้างอิง git )

Select-String -Pattern ": gone]" รับเฉพาะระเบียนที่ถูกลบออกจากระยะไกล

% { $_.toString().Trim().Split(" ")[0]} รับชื่อสาขา

% {git branch -d $_} ลบสาขา


3
ขอบคุณสำหรับสิ่งนี้แม้ว่าฉันจะต้องเพิ่ม.Trim()หลัง.toString()เพื่อที่จะลบสองช่องว่างก่อนที่ชื่อสาขา
แมทธิว

2
ขอบคุณสำหรับคำสั่งนี้ ผมต้องเปลี่ยนgit branch -dไปgit branch -Dที่อื่นที่ฉันได้รับข้อผิดพลาดสาขาที่ไม่ได้รวมอย่างเต็มที่
markieo

1
@markieo คุณน่าจะรู้เรื่องนี้อยู่แล้ว แต่สำหรับคนอื่น - git branch -Dเป็นอันตรายและจะลบงานในท้องถิ่นที่คุณยังไม่ได้ผลัก มีความปลอดภัยอยู่เสมอเพียงแค่ต้องระวังด้วย-d -D
Nate Barbettini

33

การจับคู่รูปแบบสำหรับ "หายไป" ในโซลูชันอื่น ๆ ส่วนใหญ่เป็นเรื่องเล็กน้อยที่น่ากลัวสำหรับฉัน การจะมีความปลอดภัยมากขึ้นนี้ใช้--formatธงที่จะดึงออกของแต่ละสาขาสถานะการติดตามต้นน้ำ

ฉันต้องการเวอร์ชันที่ใช้งานง่ายกับ Windows ดังนั้นนี่จะลบสาขาทั้งหมดที่ระบุว่า "หายไป" โดยใช้ Powershell:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

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


6
--formatตัวเลือกที่ดูเหมือนว่าจะค่อนข้างใหม่; ฉันต้องการอัพเกรด git จาก 2.10.something เป็น 2.16.3 เพื่อรับมัน นี่คือการดัดแปลงของฉันสำหรับระบบ Linux-ish:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
bxm

2
นี่เป็นทางออกที่ดีที่สุด refname:shortข้อเสนอแนะที่หนึ่งคือการใช้งาน จากนั้นคุณสามารถลบบรรทัด% { $_ -replace '^refs/heads/', '' }
ioudas

2
นี่เป็นทางออกที่ดีสำหรับ windows ฉันใช้มันเหมือนสาเหตุนี้มันเป็นอ่านได้มากขึ้นgit branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }นอกจากนี้ยังอาจจะเป็นความคิดที่ดีที่จะใช้แทน-d -Dการลบบังคับไม่จำเป็นสำหรับสาขาที่ไม่ได้อยู่ในระยะไกล
Rubanov

31

ลบสาขาทั้งหมดที่รวมอยู่ในต้นแบบ แต่อย่าพยายามลบต้นแบบออก:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

หรือเพิ่มชื่อแทน:

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

คำอธิบาย:

git checkout master สาขาชำระเงินหลัก

git pull origin master ตรวจสอบให้แน่ใจว่าสาขาในพื้นที่มีการเปลี่ยนแปลงระยะไกลทั้งหมดที่ผสาน

git fetch -p ลบการอ้างอิงไปยังสาขาระยะไกลที่ถูกลบ

git branch -d $(git branch master --merged | grep master -v) ลบสาขาทั้งหมดที่รวมอยู่ในต้นแบบ แต่อย่าพยายามลบต้นแบบออก


3
One note สิ่งนี้มีประโยชน์มาก แต่มันจะลบกิ่งเหล่านั้นที่ไม่เคยถูกผลักไปที่รีโมท จะปลอดภัยกว่าเฉพาะรายการความแตกต่างจากนั้นคัดลอกสิ่งที่คุณต้องการลบลงในgit branch -Dคำสั่ง
Zefiryn

เพื่อชี้แจงให้ชัดเจน Zefiryn หมายถึงการใช้ตัวเลือก -D ซึ่งไม่ได้เป็นส่วนหนึ่งของสายการบินเดียว
cs01

1
หรือใช้ตัวพิมพ์เล็กgit branch -dซึ่งควรออกคำเตือนเกี่ยวกับการไม่ผลักสาขา
acme

16
git fetch -p

การทำเช่นนี้จะตัดกิ่งไม้ที่ไม่มีอยู่บนรีโมทอีกต่อไป


64
สิ่งนี้จะลบการอ้างอิงระยะไกล แต่ไม่ใช่สาขาในตัวเอง ในขณะที่คำสั่งที่มีประโยชน์ฉันไม่คิดว่านี่จะตอบคำถามของ OP
thataustin

อะไร? นี่เป็นการลบสาขาท้องถิ่นสำหรับฉัน
Alex Hall

1
@AlexHall พื้นที่เก็บข้อมูลระยะไกลมีสาขาX; คุณgit checkout X; ขณะนี้พื้นที่เก็บข้อมูลของคุณมี (ท้องถิ่น) สาขาการติดตามXและสาขาที่ห่างไกลorigin/X; ลบพื้นที่เก็บข้อมูลระยะไกลX; คุณgit fetch-p; ในที่เก็บในเครื่องของคุณไม่เพียงorigin/Xแต่Xถูกลบไปแล้ว นั่นคือสิ่งที่คุณพูด
แอนดรูสเปนเซอร์

16

ยัง - อีกคำตอบสำหรับกอง, วาดอย่างหนักจากคำตอบของ Patrick (ซึ่งฉันชอบเพราะดูเหมือนว่าจะทำไปด้วยความคลุมเครือใด ๆ เกี่ยวกับที่gone]จะจับคู่ในgit branchผลลัพธ์) แต่เพิ่ม * nix งอ

ในรูปแบบที่ง่ายที่สุด:

git branch --list --format \
  "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
  | xargs git branch -D

ฉันเขียนสิ่งนี้ไว้ในgit-goneสคริปต์บนเส้นทางของฉัน:

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format \
    "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

NB - --formatตัวเลือกดูเหมือนจะค่อนข้างใหม่ ฉันต้องการอัพเกรด git จาก 2.10.something เป็น 2.16.3 เพื่อรับมัน

แก้ไข: tweaked เพื่อรวมข้อเสนอแนะเกี่ยวกับrefname:shortจาก Benjamin W.

NB2 - ฉันเพิ่งทดสอบเท่านั้นbashดังนั้น hashbang แต่อาจพกพาไปshได้


คุณไม่สามารถข้ามsedส่วนโดยใช้%(refname:short)ในบรรทัดแรกได้หรือไม่?
Benjamin W.

ดูเหมือนว่าจะทำงานให้ฉันและฉันมีมันเป็นนามแฝง Git เรียบร้อยในขณะนี้ - ทางออกที่สะอาดที่สุดของพวกเขาทั้งหมดที่นี่!
Benjamin W.

2.13 --formatการแนะนำให้รู้จัก วิธีที่จะข้ามไปอีกส่วนหนึ่งคือการใช้งานsed git update-ref -dโปรดทราบว่านี่อาจจะค่อนข้างไม่ปลอดภัยการใช้git for-each-refปลอดภัยกว่าที่นี่ (ระบุไว้--shell)
gsnedders

คำตอบที่ยอดเยี่ยมและมันช่วยให้ฉันตอบคำถามของตัวเองเมื่อ--formatทำสิ่งนี้ด้วยตัวเอง เพียงแค่หนึ่งคำถาม: ทำไม#!bash? ทุกอย่างที่นี่ดูเหมือนพกพาshไปหาฉัน
Toby Speight

นั่นเป็นเพียงปกติของฉันและไม่ได้ทดสอบที่อื่น
bxm

15

อาจมีประโยชน์กับบางบรรทัดง่ายๆในการล้างสาขาท้องถิ่นทั้งหมดยกเว้นต้นแบบและพัฒนา

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

คำตอบที่ยอดเยี่ยม! ฉันชอบวิธีที่ผู้เล่นสามารถเล่นกับ'git branch | grep -v "master" | grep -v "develop"สิ่งต่างๆได้อย่างง่ายดายก่อนที่จะเพิ่มลงในส่วนการลบของคำสั่ง 👏😊
finneycanhelp

แต่นี่ไม่ได้ตอบคำถามข้างต้น สิ่งนี้จะลบสาขาแม้ว่าจะยังมีรีโมตอยู่
Jim.B

13

สิ่งนี้จะลบการรวมสาขาโลคัลทั้งหมดยกเว้นการอ้างอิงต้นแบบโลคัลและการใช้ในปัจจุบัน:

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d

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

git remote prune origin

git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d คำอธิบาย:ฉันต้องการแทนที่git branch --mergedด้วยgit branch -vvเพื่อแสดงสถานะ (หายไป) เพราะก่อนหน้านี้git branch --mergedสามารถแสดงต้นแบบได้เช่นกัน
jpmottin

13

ฉันไม่คิดว่ามีคำสั่งในตัวให้ทำเช่นนี้ แต่สามารถทำสิ่งต่อไปนี้ได้อย่างปลอดภัย:

git checkout master
git branch -d bug-fix-a

เมื่อคุณใช้-dคอมไพล์จะปฏิเสธที่จะลบสาขายกเว้นว่าจะถูกรวมเข้าในHEADหรือสาขาการติดตามระยะไกลอัปสตรีม ดังนั้นคุณสามารถวนซ้ำผลลัพธ์ของgit for-each-refและลองลบแต่ละสาขา ปัญหาของวิธีการนั้นคือฉันสงสัยว่าคุณอาจไม่ต้องการbug-fix-dลบเพียงเพราะorigin/bug-fix-dมีประวัติของมัน คุณสามารถสร้างสคริปต์ได้ดังนี้:

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

คำเตือน: ฉันยังไม่ได้ทดสอบสคริปต์นี้ - ใช้ด้วยความระมัดระวัง ...


ฉันเอาเสรีภาพในการแก้ไขสคริปต์ ยังไม่รับประกันใด ๆ แต่จะทำงานและดูเหมือนว่าจะทำงานได้ในขณะนี้
fwielstra

13

TL; DR:

ลบสาขาท้องถิ่นทั้งหมดที่ไม่ได้อยู่ในระยะไกล

git fetch -p && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D

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

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d

คำอธิบาย

  • git fetch -p จะตัดสาขาทั้งหมดที่ไม่มีอยู่บนรีโมทอีกต่อไป
  • git branch -vv จะพิมพ์สาขาท้องถิ่นและสาขาที่ตัดแล้วจะถูกแท็กด้วย gone
  • grep ': gone]' เลือกเฉพาะสาขาที่หายไป
  • awk '{print $1}' กรองผลลัพธ์เพื่อแสดงเฉพาะชื่อของสาขา
  • xargs git branch -D จะวนซ้ำทุกบรรทัด (สาขา) และบังคับให้ลบสาขานี้

ทำไมgit branch -Dไม่git branch -dงั้นคุณจะมีสาขาที่ไม่ได้รวมอย่างเต็มที่

error: The branch 'xxx' is not fully merged.

1
คุณต้องการจะพูดรีโมทแทนที่จะเป็นเจ้านายหรือไม่?
tinos


7

จากข้อมูลข้างต้นสิ่งนี้ได้ผลกับฉัน:

git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs`

มันจะลบสาขาท้องถิ่นทั้งหมดที่อยู่': gone] 'ในระยะไกล


1
ดูเหมือนว่าจะเป็นการลบสาขาใด ๆ ที่ "หายไป" ในข้อความยืนยันล่าสุด
dlsso

นอกจากนี้ยังจะลบสาขาใด ๆ ที่มีgoneที่ใดก็ได้ในชื่อ
bfontaine

3
"git branch -D git branch -vv | grep ': หายไป]' | awk '{พิมพ์ $ 1}' | xargs`" นี่ใช้งานได้สำหรับฉัน
Muthu Ganapathy Nathan

7
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d

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


ทางออกที่ดีที่สุดจนถึงแม้ว่าฉันเปลี่ยนเป็นgrep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -Dบังคับให้ลบทั้งหมด
Shoaib

เป็นอันตรายหากชื่อสาขาของคุณมีซับสตริงgoneที่ใดก็ได้ในนั้น (เช่นusingonefunction)
Toby Speight

7

สิ่งนี้ไม่เหมาะกับฉันเลย ฉันต้องการสิ่งที่จะล้างสาขาในท้องถิ่นทั้งหมดที่กำลังติดตามสาขาระยะไกลเปิดoriginซึ่งสาขาระยะไกลถูกลบ ( gone) ฉันไม่ต้องการลบสาขาท้องถิ่นที่ไม่เคยตั้งค่าเพื่อติดตามสาขาระยะไกล (เช่น: สาขา dev ท้องถิ่นของฉัน) นอกจากนี้ฉันต้องการซับในแบบง่าย ๆ ที่เพิ่งใช้gitหรือเครื่องมือ CLI ธรรมดาอื่น ๆ แทนที่จะเขียนสคริปต์ที่กำหนดเอง ฉันลงเอยด้วยการใช้เล็กน้อยgrepและawkเพื่อให้คำสั่งง่าย ๆ นี้

นี่คือสิ่งที่ท้ายที่สุดในของฉัน~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

นี่คือgit config --global ...คำสั่งสำหรับเพิ่มได้อย่างง่ายดายเช่น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'

หมายเหตุ: ในคำสั่งการตั้งค่าฉันใช้-dตัวเลือกเพื่อgit branchแทน-Dอย่างที่ฉันทำในการกำหนดค่าจริงของฉัน ฉันใช้-Dเพราะฉันไม่ต้องการได้ยิน Git บ่นเกี่ยวกับกิ่งที่ยังไม่ได้จม คุณอาจต้องการฟังก์ชั่นนี้เช่นกัน ถ้าเป็นเช่นนั้นเพียงใช้-Dแทน-dคำสั่งท้ายคำสั่ง config


ฉันชอบแนวทางนามแฝงคอมไพล์ คำถามด่วน: ทำไมการทำgit branch -vvและ greping สำหรับ: gone]และไม่ทำgit branch -vและ grep สำหรับ[gone]?
lalibi

@lalibi เป็นคำถามที่ดี ฉันจำไม่ได้ vฉันสงสัยว่าบางสิ่งบางอย่างที่ไม่ได้แสดงที่มีเพียงหนึ่ง หากได้git branch -v | grep '[gone]'ผลกับคุณไปเลย มันดูสะอาดขึ้นเล็กน้อย
Karl Wilbur

4

จากคำแนะนำ Git: การลบสาขาท้องถิ่นเก่าซึ่งมีลักษณะคล้ายกับโซลูชันของ jason.rickmanฉันได้ใช้คำสั่งที่กำหนดเองเพื่อจุดประสงค์นี้ที่เรียกว่าgit หายไปโดยใช้ 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 รวมการตัดแต่งกิ่งและแสดงรายการกิ่ง "หายไป":

$ 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

จากนั้นคุณสามารถเหนี่ยวไกใช้หรือgit gone -dgit gone -D

หมายเหตุ

  • ที่ผมแสดงออกปกติใช้เป็น"$BRANCH/.*: gone]"ที่ปกติจะเป็น$BRANCH originสิ่งนี้อาจจะไม่ทำงานหากเอาต์พุต Git ของคุณแปลเป็นภาษาฝรั่งเศสและอื่น ๆ
  • เซบาสเตียนไวส์เนอร์ยังส่งต่อไปยังผู้ใช้ Windows ที่หนึ่งจะเรียกว่าคอมไพล์หายไป

นี่น่าจะเป็นคำตอบที่ยอมรับได้ - git goneดูเหมือนเป็นนามแฝงgit branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -dซึ่งแก้ปัญหาของ OP ได้
alex

4

วาดอย่างหนักจากจำนวน ของ อื่น ๆ คำตอบที่นี่ผมได้จบลงด้วยดังต่อไปนี้ (คอมไพล์ 2.13 ขึ้นไปเท่านั้นผมเชื่อว่า) ซึ่งควรจะทำงานที่ใด ๆ 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

สิ่งนี้ใช้for-each-refแทนการสะดุดตาbranch(เช่นเดียวกับbranchคำสั่ง "เครื่องลายคราม" ที่ออกแบบมาสำหรับเอาต์พุตที่มนุษย์อ่านได้ไม่ใช่การประมวลผลของเครื่องจักร) และใช้--shellอาร์กิวเมนต์เพื่อให้ได้เอาต์พุตที่ถูกต้อง (ซึ่งทำให้เราไม่ต้องกังวลเกี่ยวกับตัวละครในชื่ออ้างอิง)


มันใช้งานได้สำหรับฉัน แต่มันก็ยังดีถ้าคุณสามารถอธิบายว่าขั้นตอนอื่น ๆ ในคำสั่งกำลังทำ เช่นฉันไม่รู้ว่า[ ! -z "$ref" ]หมายถึงอะไร ฉันคิดว่าสายการบินที่หลากหลายจะช่วยได้แล้ว แต่ก็ยังขอบคุณสำหรับข้อมูลของคุณ!
KevinH

4

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

คำสั่งเพื่อลบสาขาท้องถิ่นไม่ได้อยู่ในระยะไกล:

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done

เพื่อรวมเข้ากับ gitconfig เพื่อให้สามารถทำงานกับ git branch-prune :

ทุบตี

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'

PowerShell

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'

(ต้องการความช่วยเหลือในการค้นหาคำสั่งสากลสำหรับ PowerShell และ bash)

ทำไมคำตอบนี้ดีที่สุด

  • นำเสนอโซลูชั่นที่สมบูรณ์: เพิ่ม git branch-pruneคำสั่งให้คอมไพล์ของคุณ
  • ทำงานได้ดีจาก Windows PowerShell
  • แนวคิดหลักคือวิธีการกันกระสุนของ@ jason.rickmanที่ใช้git for-each-ref
  • การแยกและการกรองเสร็จสิ้น--filterจึงไม่จำเป็นต้องพึ่งพาภายนอก

คำอธิบาย:

  • เพิ่มนามแฝงใหม่ให้กับคุณ ~\.gitconfigเพิ่มนามแฝงใหม่เพื่อคุณหลังจากดำเนินการนี้คุณสามารถทำได้git branch-prune
  • ภายในนามแฝงนี้:
    • ดึงสาขาด้วย --pruneธงซึ่ง "ตัดกิ่งก้านสาขาติดตามระยะไกลไม่ได้อยู่ในระยะไกล"
    • ใช้git for-each-refและ--filterเพื่อรับรายการของสาขา[gone](ไม่มีรีโมต)
    • วนรอบรายการนี้และลบสาขาอย่างปลอดภัย

1
ขอบคุณ@ jerry-wuสำหรับการปรับปรุงความสุดยอดของการแก้ปัญหานี้ให้เป็นอนันต์
Himura

@ jerry-wuและการแก้ไขคำสั่ง git config ครั้งสุดท้ายของคุณไม่ทำงานใน PowerShell ((
Himura

1

ฉันมากับสคริปต์ทุบตีนี้ มันมักจะเก็บกิ่งไม้develop, ,qamaster

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

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

เพียงเพิ่มตัวอย่างต่อไปนี้ใน. bashrc (.bashprofile บน macos)

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
  1. ดึงรีโมททั้งหมด
  2. รับเฉพาะสาขาที่ผสานจาก git
  3. ลบออกจากรายการนี้สาขา "ป้องกัน / สำคัญ"
  4. ลบส่วนที่เหลือ (เช่นล้างและรวมสาขา)

คุณจะต้องแก้ไข grep regex เพื่อให้เหมาะกับความต้องการของคุณ (ที่นี่จะเป็นการป้องกันมาสเตอร์, preprod และ dmz จากการลบ)


git fetch --all --pruneทำเคล็ดลับ ขอบคุณ!
LeOn - Han Li

1

สิ่งนี้ใช้ได้กับฉัน:

git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

โอ้ฉันโพสต์สิ่งนี้บนสองครั้ง ... เพิ่งเห็นสิ่งนี้เมื่อตรวจสอบโพสต์ แต่คุณสามารถชี้ไปที่คนที่ให้คำสั่งนี้แทนการเป็นของคุณ!
Dwza

ฉันได้รับจากฟอรั่มอย่าพยายามฉลาดแค่ตอบหรือเพิกเฉย
Fareed Alnamrouti

ยิ่งกว่าที่คุณจะทำได้ ... อย่างไรก็ตาม ... ไม่ได้มาที่นี่เพื่อพูดคุยเรื่องนี้กับคุณ ตามที่คุณพูด .. . ใช้ความคิดเห็นของฉันหรือเพิกเฉยมัน;)
Dwza

0

ฉันไม่แน่ใจว่าต้องใช้เวลานานเท่าไหร่ แต่ฉันจะใช้ git-up ตอนนี้ซึ่งดูแลเรื่องนี้

ฉันทำgit upแล้วมันจะเริ่มติดตามสาขาใหม่และลบสาขาเก่า

เพียงเพื่อให้ชัดเจนมันไม่ได้ออกคำสั่ง git นอกกรอบ - https://github.com/aanand/git-up

BTW มันยังทำให้ต้นไม้สกปรกและทำให้ rebases ยังคงอยู่ด้วย git upยังคงมีเพียง

หวังว่ามันจะมีประโยชน์สำหรับใครบางคน


2
นี่ไม่ได้เป็นการลบสาขาท้องถิ่นที่ไม่มีอยู่บนเซิร์ฟเวอร์
แอชลีย์

0

นี่เป็นวิธีแก้ปัญหาที่ฉันใช้สำหรับตู้ปลา การทดสอบบนMac OS X 10.11.5, และfish 2.3.0git 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

หมายเหตุเล็กน้อย:

base_branchให้แน่ใจว่าจะตั้งค่าที่ถูกต้อง ในกรณีนี้ฉันใช้developเป็นสาขาพื้นฐาน แต่อาจเป็นอะไรก็ได้

grep -v "\(master\|$base_branch\|\*\)"ส่วนนี้เป็นสิ่งสำคัญมาก: เป็นการรับรองว่าคุณจะไม่ลบข้อมูลหลักหรือสาขาหลักของคุณ

ฉันใช้git branch -d <branch>ความระมัดระวังเป็นพิเศษเพื่อที่จะไม่ลบสาขาใด ๆ ที่ไม่ได้รับการผสานอย่างสมบูรณ์กับส่วนหัวหรือปัจจุบัน

วิธีง่ายๆในการทดสอบคือการแทนที่ด้วยgit branch -d $fecho "will delete $f"

ฉันคิดว่าฉันควรเพิ่ม: ใช้ความเสี่ยงของคุณเอง!


0

ฉันได้เขียนสคริปต์ Python โดยใช้GitPythonเพื่อลบสาขาท้องถิ่นที่ไม่มีอยู่ในระยะไกล

    import git
    import subprocess
    from git.exc import GitCommandError
    import os

    def delete_merged_branches():
        current_dir = input("Enter repository directory:")
        repo = git.Repo(current_dir)
        git_command = git.Git(current_dir)

        # fetch the remote with prune, this will delete the remote references in local.
        for remote in repo.remotes:
            remote.fetch(prune=True)

        local_branches = [branch.name for branch in repo.branches]
        deleted_branches = []

        # deleted_branches are the branches which are deleted on remote but exists on local.
        for branch in local_branches:
            try:
                remote_name = 'origin/'+ branch
                repo.git.checkout(remote_name)
            except GitCommandError:
            # if the remote reference is not present, it means the branch is deleted on remote.
                deleted_branches.append(branch)

        for branch in deleted_branches:
            print("Deleting branch:"+branch)
            git_command.execute(["git", "branch", "-D",branch])


        # clean up the work flow.
        repo.git.checkout('master')
        repo.git.pull()

    if __name__ == '__main__':
        delete_merged_branches()

หวังว่าบางคนจะพบว่ามีประโยชน์โปรดเพิ่มความคิดเห็นหากฉันพลาดอะไรไป


0

หากคุณใช้zshเชลล์พร้อมการOh My Zshติดตั้งวิธีที่ง่ายที่สุดในการทำเช่นนี้คือการใช้การเติมข้อความอัตโนมัติในตัว

ก่อนอื่นให้กำหนดว่าคุณต้องการลบสาขาใดด้วย:

~ git branch --merged

  branch1
  branch2
  branch3
* master

นี่จะแสดงรายการของสาขาที่ผสานแล้ว

หลังจากคุณทราบจำนวนน้อยที่คุณต้องการลบแล้วพิมพ์:

~ git branch -d 

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

Tab เลือกสาขาซ้ำแล้วซ้ำอีกจนกว่าคุณจะมีรายการสาขาที่คุณไม่ต้องการลบ:

~ git branch -d branch1 branch2 branch3

ตอนนี้เพียงกด Enter เพื่อลบคอลเลกชันสาขาของคุณ

หากคุณไม่ได้ใช้ zsh บนเทอร์มินัลของคุณ ... ไปที่นี่


0

ฉันชอบใช้ไพพ์เพราะมันทำให้คำสั่งอ่านง่ายขึ้น

นี่คือทางออกของฉันหากคุณต้องการลบสาขาทั้งหมดยกเว้นมาสเตอร์

git branch | grep -v master | xargs -n 1 git branch -D

หากต้องการลบสาขาอื่นที่ตรงกับเกณฑ์ของคุณให้แก้ไขบล็อกแรกและบล็อกที่สอง

git branch --merged | grep feature_name | xargs -n 1 git branch -D

-3

นี่คือคำตอบง่ายๆที่ใช้งานได้สำหรับฉันโดยใช้ลูกค้า git:

ลบที่เก็บทั้งหมดออกจากเครื่องของคุณจากนั้นตรวจสอบอีกครั้ง

ไม่มีการล้อเล่นกับสคริปต์ที่มีความเสี่ยง


2
สาขาที่ฉันกำลังทำงานอยู่ในขณะนี้: /
Mailo Světel

@ MailoSvětelหากพวกเขาอยู่ในระยะไกลของคุณแล้วคุณสามารถดึงพวกเขาอีกครั้ง (อย่าลืมผูกมัดและผลักดันงานล่าสุดของคุณสู่ที่ห่างไกล!)
Juan Carlos Ospina Gonzalez

ในคำถามของฉันและในคำตอบส่วนใหญ่เราพยายามหลีกเลี่ยงงานที่ไม่จำเป็น ในคำอื่น ๆ : สิ่งที่ฉันต้องทำคือเพียงลบสาขาฉันจะไม่ทำงานอีกต่อไป การลบ repo การโคลนและเริ่มติดตามกิ่งไม้อีกครั้งเป็นงานที่ไม่จำเป็นสำหรับฉัน นอกจากนั้นงานบางอย่างอาจสูญหาย :(
Mailo Světel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.