26 คะแนน โดย GN⁺ 2026-02-21 | 4 ความคิดเห็น | แชร์ทาง WhatsApp
  • พบคำสั่งง่าย ๆ สำหรับแก้ปัญหา การจัดการ Git branch เก่า ในเอกสารพัฒนาภายในของ CIA
    git branch --merged | grep -v "\*\|master" | xargs -n 1 git branch -d
  • คำสั่งนี้จะลบ branch ที่ merge แล้วทั้งหมดแบบรวดเดียว โดย ยกเว้น branch ปัจจุบันและ master จากผลลัพธ์ของ git branch --merged
  • ยังมีเวอร์ชันที่ปรับให้เข้ากับโปรเจ็กต์สมัยใหม่ โดยยกเว้น branch main และ develop ด้วย
  • สามารถ ลงทะเบียนเป็น Git alias เพื่อทำงานซ้ำ ๆ ให้เป็นอัตโนมัติได้ เป็นเครื่องมือที่เรียบง่ายแต่มีประโยชน์ต่อ การเพิ่มประสิทธิภาพการทำงานอย่างต่อเนื่อง และการจัดระเบียบ repository

เคล็ดลับ Git ที่พบใน Vault7

  • เอกสาร Vault7 ที่ WikiLeaks เปิดเผยในปี 2017 มีทั้งเครื่องมือแฮ็กของ CIA และเอกสารพัฒนาภายใน
    • ในบรรดาเอกสารเหล่านั้น มีหน้าหนึ่งที่รวบรวม เคล็ดลับและทริกเกี่ยวกับ Git ซึ่งส่วนใหญ่เป็นเรื่องทั่วไป เช่น การแก้ไข commit, การใช้ stash และ bisect
  • คำสั่งบรรทัดเดียวที่พบในเอกสารนั้นยังคงอยู่ใน ~/.zshrc ของผู้เขียนมาจนถึงทุกวันนี้

ปัญหาการจัดการ branch เก่า

  • ใน local Git repository เมื่อเวลาผ่านไป branch ที่ merge แล้วจะสะสมเพิ่มขึ้น ทำให้จัดการได้ยาก
    • ไม่ว่าจะเป็น feature branch, hotfix หรือ branch สำหรับการทดลอง มักยังคงค้างอยู่หลัง merge ทำให้รายการจาก git branch ดูรกและซับซ้อน
  • แม้จะใช้คำสั่ง git branch --merged เพื่อตรวจสอบ branch ที่ merge แล้วได้ แต่ การลบทีละอันด้วยมือเป็นเรื่องยุ่งยาก

คำสั่งต้นฉบับจากเอกสาร CIA

  • คำสั่งต้นฉบับที่นำเสนอมีดังนี้
    git branch --merged | grep -v "\*\|master" | xargs -n 1 git branch -d  
    
  • คำอธิบายของแต่ละส่วน
    • git branch --merged: แสดงรายการ local branch ทั้งหมดที่ถูกรวมเข้า branch ปัจจุบันแล้ว
    • grep -v "\*\|master": ยกเว้น branch ปัจจุบัน (*) และ master
    • xargs -n 1 git branch -d: ลบ branch ที่เหลือทีละรายการอย่างปลอดภัย (-d จะไม่ลบ branch ที่ยังไม่ได้ merge)

เวอร์ชันคำสั่งที่ปรับให้ทันสมัย

  • เนื่องจากโปรเจ็กต์ส่วนใหญ่ใช้ branch main จึงสามารถปรับคำสั่งได้ดังนี้
    git branch --merged origin/main | grep -vE "^\s*(\*|main|develop)" | xargs -n 1 git branch -d  
    
  • เมื่อรันจาก branch main หลัง deploy แล้ว จำนวน branch สามารถลดจากหลายสิบเหลือเพียงไม่กี่อัน
  • ยังสามารถลงทะเบียนคำสั่งนี้เป็น Git alias เพื่อเรียกใช้งานได้สะดวก
    alias ciaclean='git branch --merged origin/main | grep -vE "^\s*(\*|main|develop)" | xargs -n 1 git branch -d'  
    
    • หลังจากนั้น เพียงพิมพ์คำสั่ง ciaclean ใน repository ก็จะจัดการให้อัตโนมัติ

ประสิทธิภาพและการใช้งานจริง

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

4 ความคิดเห็น

 
foriequal0 2026-02-21

มีคนในคอมเมนต์ HN บอกว่าเขาใช้โปรแกรมที่ผมเคยทำด้วย

ผมใช้ git-trim สำหรับเรื่องนั้น: https://github.com/foriequal0/git-trim ใน Readme ก็อธิบายด้วยว่าทำไมในบางกรณีมันถึงดีกว่า bash-oneliner https://news.ycombinator.com/item?id=47089533

 
youngminz 2026-02-21

ผมเองก็ตั้ง alias ชื่อ git gone ไว้ใช้เหมือนกันครับ สะดวกมาก
- alias.gone = ! git fetch -p && git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D

 
a1eng0 2026-02-21

ผมไม่ได้ใช้ git แบบล้วน ๆ แต่ใช้เครื่องมือชื่อ gh-poi สำหรับจัดการอยู่ครับ

https://github.com/seachicken/gh-poi

 
GN⁺ 2026-02-21
ความคิดเห็นจาก Hacker News
  • ฉันใช้ alias ชื่อ git tidy เพื่อจัดการกิ่ง
    โดยจะไม่ลบกิ่งหลัก (main, master) และจะไม่แตะกิ่งปัจจุบันหรือกิ่งของ worktree อื่นด้วย
    กิ่งที่หายไปจากรีโมตก็จะถูกลบอัตโนมัติ และมีโค้ดอยู่ใน การตั้งค่า dotfiles ของฉัน

    • การใช้ init.defaultBranch มีความเสี่ยง เพราะชื่อกิ่งหลักอาจต่างกันไปในแต่ละรีโพซิทอรี และค่านี้เป็นการตั้งค่าระดับโกลบอลจึงต้องกำหนดล่วงหน้า
      ฉันเลยสร้าง alias ชื่อ git default ให้ค้นหากิ่งหลักจริงจากรีโมต (origin) แบบอัตโนมัติ
    • สคริปต์นี้มีประโยชน์มาก น่าจะลองนำไป contribute ให้ git extras
  • ฉันใช้ คำสั่ง cleanup ที่ผสานกับ fzf
    สามารถเลือกกิ่งที่ merge แล้วล่วงหน้าแล้วลบทีเดียวได้ และถ้าต้องการก็ยกเว้นบางกิ่งออกได้
    มันจัดการกิ่งรีโมตไปพร้อมกันด้วย และมีโค้ดอยู่ใน การตั้งค่า .gitconfig ของฉัน
    อีกทั้งยังใช้ตัวแปร user.primaryBranch เพื่อกำหนดกิ่งหลักที่ต่างกันในแต่ละรีโพซิทอรี

    • คิดว่าใช้ init.defaultBranch แทนก็น่าจะได้เหมือนกัน ถึงจะเป็นรีโพซิทอรีที่ init ไปแล้วก็ยังใช้ git config --local init.defaultBranch main เพื่อตั้งค่าได้
    • สามารถ pull จากกิ่งอื่นได้โดยไม่ต้องสลับกิ่ง เช่นใช้ git pull origin main:main แล้วค่อย git rebase main
  • git branch --merged ใช้งานได้ไม่ดีในรีโพซิทอรีที่ใช้ squash merge
    เพราะ SHA ของ commit ที่ถูก squash จะต่างจาก HEAD ของกิ่งเดิม
    เลยสงสัยว่ามีเครื่องมือที่ตรวจจับกิ่งที่ถูก squash อย่างปลอดภัยได้หรือไม่

    • ฉันเพิ่งแก้สคริปต์ล่าสุดให้ลบเมื่อเข้าเงื่อนไขว่า “ไม่มี commit ในช่วง 30 วันที่ผ่านมา” + “ไม่มีกิ่งบนรีโมต”
      มันไม่สมบูรณ์แบบ แต่ใช้งานได้จริงพอสมควร และจะแสดง prompt ยืนยันก่อนลบเสมอ
      อ้างอิง การตั้งค่าลบกิ่งอัตโนมัติของ GitHub
    • ไม่ใช่แค่ squash merge เท่านั้น rebase merge ก็ตรวจจับไม่ได้เช่นกัน
      ส่วนใหญ่จึงจัดการโดยผูก hook กับอีเวนต์ลบกิ่งบนรีโมต
    • ฉันแค่ลบกิ่งโลคัลเมื่อกิ่งรีโมตหายไป
      ใช้ alias ชื่อ git gone เพื่อรัน git fetch -p แล้วจัดการกิ่งที่มีสถานะ [gone]
    • ฉันทำงานในสภาพแวดล้อมที่ใช้ Gerrit จึงมีการ rebase บนเซิร์ฟเวอร์
      เลยใช้ สคริปต์ ที่ผสมสามวิธีคือ git branch --merged, git cherry, git log grep
      แต่ถ้า commit ถูก amend หรือมีหลาย commit ก็อาจเกิดการตรวจจับผิดได้
    • ถ้าลอง rebase กิ่งนั้นก่อน ก็น่าจะพอตรวจจับ กิ่งว่าง ได้
  • ฉันใช้ alias ชื่อ git lint เพื่อจัดการกิ่งที่ merge แล้ว
    มันจะยกเว้นกิ่ง main, master, stable ไม่ลบ และฉันใช้คู่กับ git pull --prune && git lint บ่อย ๆ

  • ตัวคำสั่ง Git เองก็ธรรมดา แต่สิ่งที่น่าสนใจคือดันคลิกไปเจอเอกสารจาก Wikileaks
    โครงการ “Fine Dining” ของ CIA เป็นเครื่องมือปลอมมัลแวร์ที่ซ่อนใน USB ให้ดูเหมือนแอป

    • อันนั้นกลับดูเป็น เทคนิคสายลับ ทั่วไปมากกว่า ของที่ ‘บ้าจริง’ คือการทดลองแบบ MKULTRA ที่แอบให้คนกิน LSD โดยไม่รู้ตัว
  • จริง ๆ ปัญหาตั้งต้นอาจแก้ได้ง่าย ๆ แค่แสดง รายการกิ่งที่ยังไม่ถูก merge ออกมาก็พอ

  • มันแปลกที่งานซึ่งดูเป็นธรรมชาติแบบนี้กลับต้องใช้ bash หลายบรรทัด
    ทั้งที่โค้ดเบสของ Git ใหญ่มาก แต่กลับไม่มีเป็นฟีเจอร์พื้นฐานให้ใช้ น่าเสียดาย
    ดู บทความบล็อกที่เกี่ยวข้อง ได้ด้วย

    • แต่ถ้าคุ้นกับ xargs หรือ for loop สักหน่อย เรื่องพวกนี้ก็เล็กน้อยมาก
      ถ้าจะทำเป็นคำสั่ง built-in จริง ๆ ต้องรองรับกรณียกเว้นหลากหลายแบบ ซึ่งอาจยิ่งทำให้ซับซ้อน
    • การตัดสินเรื่องพวกนี้ด้วย “จำนวนบรรทัดโค้ด” ก็ดูเป็นเกณฑ์ที่แปลกอยู่
  • สุดท้ายก็มีคนตอบทำนองว่า “ดูเหมือนเพิ่งหัดใช้ xargs”

    • ท่าทีแบบนั้นให้ความรู้สึกเหมือน gatekeeping การแชร์สิ่งที่เพิ่งเรียนรู้เป็นเรื่องดี
      เมื่อก่อนฉันเองก็เรียนรู้เรื่องพวกนี้จากบล็อกหรือบทความเหมือนกัน
    • แต่การที่ไปเรียนรู้สิ่งนี้จากเอกสาร CIA ก็ดูสะท้อนภาพของคนต่างรุ่นดี ทุกวันนี้เป็นยุคที่คนเรียนจากอินเทอร์เน็ตมากกว่าโรงเรียน
    • ถึงจะมีปฏิกิริยาเชิงลบบ้าง แต่การ ผสมเครื่องมือ utility แบบนี้แหละคือเสน่ห์ของ CLI
    • ไม่ว่าจะมาจากเอกสาร CIA หรือที่ไหน ถ้ามีใครเพิ่งได้เรียนรู้ xargs ก็นับว่าเจ๋งในตัวเองแล้ว
    • ถ้ามองจากมุมคนยุค Bell Labs เนื้อหานี้อาจรู้สึกพื้นฐานเกินไปก็ได้
  • ช่วงนี้ฉัน ติด TUI มาก ถ้าอะไรใช้งานไม่สะดวกก็จะขอให้ Claude-code สร้าง TUI ให้
    ฉันทำ TUI สำหรับจัดการ Git worktree ด้วยไลบรารี Textual และ Claude ก็จัดการโค้ด Python ได้ค่อนข้างดี

    • มีคนแนะนำ tig ซึ่งเป็น Git TUI รุ่นเก่า และเหมาะสำหรับหาแรงบันดาลใจด้วย
    • บางคนก็เห็นความกังวลว่าโค้ดที่ Claude เขียนอาจทำให้รีโพซิทอรี Git พังได้
    • บางคนก็ไม่รู้ว่า TUI คืออะไร
    • ถ้าพูดถึง TUI สำหรับ Git ขอแนะนำ Magit อย่างมาก มันช่วยเรื่องการเรียนรู้ได้ด้วย
      บทความเกี่ยวกับฟีเจอร์ rebase ของ Magit ก็น่าอ่าน
    • ฉันเองก็มีเครื่องมือเล็ก ๆ หลายตัวที่ทำด้วย Claude เลยสงสัยว่าได้เปิดซอร์สไว้หรือเปล่า
  • ฉันก็ทำอะไรคล้าย ๆ กันไว้ใน Fish shell
    เป็นฟังก์ชันที่ใช้ fzf เลือกกิ่งที่หายไปจากรีโมตแล้วลบ
    มีอยู่ใน โค้ด dotfiles ของฉัน