CIA 유출 문서에서 찾은 Git 브랜치 정리 한 줄 명령어
(spencer.wtf)- 오래된 Git 브랜치 정리 문제를 해결하기 위한 간단한 명령어가 CIA 내부 개발 문서에서 발견됨
git branch --merged | grep -v "\*\|master" | xargs -n 1 git branch -d - 명령어는
git branch --merged결과에서 현재 브랜치와 master를 제외하고 병합된 브랜치를 일괄 삭제함 - 현대 프로젝트에 맞게
main과develop브랜치를 제외하도록 수정된 버전도 있음 - Git alias로 등록해 반복 작업을 자동화할 수 있으며, 단순하지만 지속적인 작업 효율 향상과 저장소 정리에 유용한 도구
Vault7에서 발견된 Git 팁
- 2017년 WikiLeaks가 공개한 Vault7 문서에는 CIA의 해킹 도구와 내부 개발 문서가 포함되어 있었음
- 그중 한 페이지에 Git 팁과 트릭 모음이 있었으며, 대부분은 일반적인 커밋 수정, 스태시, bisect 사용법 등이었음
- 해당 문서에서 발견된 한 줄짜리 명령어가 내
~/.zshrc에 지금까지 유지되고 있음
오래된 브랜치 정리 문제
- 로컬 Git 저장소에는 시간이 지나며 병합된 브랜치가 누적되어 정리가 어려워짐
- 기능 브랜치, 핫픽스, 실험용 브랜치 등이 병합 후에도 남아
git branch목록이 복잡해짐
- 기능 브랜치, 핫픽스, 실험용 브랜치 등이 병합 후에도 남아
-
git branch --merged명령으로 병합된 브랜치를 확인할 수 있지만, 수동 삭제는 번거로움
CIA 문서의 원래 명령어
- 제시된 원래 명령어는 다음과 같음
git branch --merged | grep -v "\*\|master" | xargs -n 1 git branch -d - 구성 요소 설명
-
git branch --merged: 현재 브랜치에 병합된 모든 로컬 브랜치 목록 출력 -
grep -v "\*\|master": 현재 브랜치(*)와master를 제외 -
xargs -n 1 git branch -d: 나머지 브랜치를 하나씩 안전하게 삭제 (-d는 병합되지 않은 브랜치는 삭제하지 않음)
-
현대화된 명령어 버전
- 대부분의 프로젝트가
main브랜치를 사용하므로 명령어를 다음과 같이 수정 가능git branch --merged origin/main | grep -vE "^\s*(\*|main|develop)" | xargs -n 1 git branch -d - 배포 후
main브랜치에서 실행하면 수십 개의 브랜치가 몇 개로 줄어듦 - 이 명령어를 Git alias로 등록해 간편하게 실행 가능
alias ciaclean='git branch --merged origin/main | grep -vE "^\s*(\*|main|develop)" | xargs -n 1 git branch -d'- 이후 저장소에서
ciaclean명령만 입력하면 자동 정리 수행
- 이후 저장소에서
효율성과 실용성
- 이 명령어는 매주 몇 분의 시간을 절약하고 브랜치 목록을 깔끔하게 유지하는 데 도움을 줌
- 단순하지만 지속적인 생산성 향상을 제공하는 실용적 도구로 평가됨
저도 git gone 이라는 alias 걸어 쓰고 있어요. 아주 편합니다
- alias.gone = ! git fetch -p && git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D
HN 댓글중에 제가 만들었던 프로그램 쓴다는 사람이 있네요.
I use git-trim for that:
https://github.com/foriequal0/git-trim
Readme also explains why it's better than a bash-oneliner in some cases.
https://news.ycombinator.com/item?id=47089533
저는 순수 git은 아니지만 gh-poi라는 도구를 사용하여 정리하고 있습니다.
Hacker News 의견들
-
나는
git tidy라는 alias를 써서 브랜치를 정리함
기본 브랜치(main, master)는 삭제하지 않고, 현재 브랜치나 다른 worktree의 브랜치도 건드리지 않음
원격에서 사라진 브랜치도 자동으로 삭제되며, 내 dotfiles 설정에 코드가 있음-
init.defaultBranch를 사용하는 건 위험함. 각 저장소마다 기본 브랜치 이름이 다를 수 있고, 이 설정은 전역(global)이라 미리 지정해야 함
나는git default라는 alias를 만들어서 원격(origin)에서 실제 기본 브랜치를 자동으로 찾게 함 - 이 스크립트는 정말 유용하니 git extras에 기여하면 좋겠음
-
-
나는
fzf와 통합된 cleanup 명령어를 사용함
병합된 브랜치를 미리 선택해 한 번에 삭제할 수 있고, 원하면 일부를 제외할 수도 있음
원격 브랜치도 함께 정리하며, 내 .gitconfig 설정에 코드가 있음
또한user.primaryBranch변수를 이용해 저장소마다 다른 기본 브랜치를 지정함-
init.defaultBranch를 대신 써도 괜찮지 않을까 생각함. 이미 초기화된 저장소라도git config --local init.defaultBranch main으로 설정하면 작동함 - 브랜치를 전환하지 않고도 다른 브랜치에서 pull 할 수 있음. 예를 들어
git pull origin main:main후git rebase main으로 처리 가능함
-
-
git branch --merged는 squash merge를 사용하는 저장소에서는 제대로 작동하지 않음
squash된 커밋의 SHA가 원래 브랜치의 HEAD와 다르기 때문임
squash된 브랜치를 안전하게 감지할 수 있는 도구가 궁금함- 나는 최근 스크립트를 수정해서 “최근 30일간 커밋 없음” + “원격에 브랜치 없음” 조건으로 삭제하도록 함
완벽하진 않지만 충분히 실용적이며, 삭제 전 항상 확인 프롬프트를 띄움
GitHub의 자동 브랜치 삭제 설정을 참고함 - squash merge뿐 아니라 rebase merge도 감지되지 않음
대부분은 원격 브랜치 삭제 이벤트에 훅을 걸어 처리함 - 나는 단순히 원격 브랜치가 사라졌을 때 로컬 브랜치를 삭제함
git gone이라는 alias를 써서git fetch -p후[gone]상태의 브랜치를 정리함 - Gerrit을 쓰는 환경이라 서버에서 rebase가 일어남
그래서git branch --merged,git cherry,git log grep세 가지 방법을 조합한 스크립트를 사용함
단, 커밋이 amend되었거나 여러 커밋이 있을 경우 오탐이 생길 수 있음 - 브랜치를 먼저 rebase 시도해보면 빈 브랜치를 감지할 수 있을 것 같음
- 나는 최근 스크립트를 수정해서 “최근 30일간 커밋 없음” + “원격에 브랜치 없음” 조건으로 삭제하도록 함
-
나는
git lint라는 alias로 병합된 브랜치를 정리함
main, master, stable 브랜치는 제외하고 삭제하며,git pull --prune && git lint조합을 자주 씀 -
Git 명령 자체는 평범하지만, 클릭하다가 Wikileaks 출처의 문서를 보게 되어 흥미로웠음
CIA의 “Fine Dining” 프로젝트는 USB에 숨겨진 악성코드를 앱처럼 위장하는 도구였음- 그건 오히려 일반적인 첩보 기술 같음. 진짜 ‘미친’ 건 MKULTRA처럼 사람 몰래 LSD를 타던 실험이었음
-
원래 문제는 단순히 병합되지 않은 브랜치 목록만 출력하는 부분으로도 해결 가능함
-
이렇게 자연스러운 작업이 여러 줄의 bash를 필요로 한다는 게 이상함
Git의 코드베이스가 이렇게 큰데 기본 기능으로 제공되지 않는 게 아쉬움
관련 블로그 글도 참고함- 하지만
xargs나 for loop를 조금만 익히면 이런 건 사소한 일임
내장 명령으로 만들려면 다양한 예외 케이스를 다뤄야 해서 오히려 복잡해질 수 있음 - “코드 줄 수”로 이런 걸 평가하는 건 이상한 기준 같음
- 하지만
-
결국 “xargs를 이제 막 배운 사람 같다”는 반응도 있었음
- 그런 태도는 게이트키핑처럼 느껴짐. 새로 배운 걸 공유하는 건 좋은 일임
나도 예전에 블로그나 글을 통해 이런 걸 배웠음 - 하지만 이걸 CIA 문서에서 배웠다는 게 세대의 단면 같음. 요즘은 학교보다 인터넷에서 배우는 시대임
- 부정적인 반응도 있었지만, 이런 유틸리티 조합이야말로 CLI의 묘미임
- CIA 출처든 뭐든, 누군가 xargs를 새로 배웠다면 그 자체로 멋진 일임
- Bell Labs 세대 입장에서는 너무 기본적인 내용처럼 느껴질 수도 있음
- 그런 태도는 게이트키핑처럼 느껴짐. 새로 배운 걸 공유하는 건 좋은 일임
-
나는 요즘 TUI 중독임. 뭔가 불편하면 Claude-code에 TUI를 만들어달라 요청함
Textual 라이브러리를 써서 Git worktree를 관리하는 TUI를 만들었고, Claude가 Python 코드를 꽤 잘 다룸-
tig라는 오래된 Git TUI도 추천받음. 영감 얻기에도 좋음 - Claude가 작성한 코드가 Git 저장소를 망가뜨릴까 걱정된다는 의견도 있었음
- TUI가 뭔지 모르는 사람도 있었음
- Git용 TUI라면 Magit을 강력 추천함. 학습에도 도움이 됨
Magit의 rebase 기능에 대한 글도 참고할 만함 - 나도 Claude로 만든 작은 도구가 많음. 혹시 오픈소스로 공개했는지 궁금함
-
-
나도 비슷한 걸 Fish shell에서 구현함
fzf로 원격에서 사라진 브랜치를 선택해 삭제하는 함수임
내 dotfiles 코드에 있음