본문 바로가기

개발 이야기/Git

[Git] merge된 local 브랜치 한번에 쉽게 정리하기

Git 전략에 따라서 작업하는 방식은 여러가지가 존재하지만, 대부분은 local에서 특정 브랜치를 생성하고 작업이 완료되면 최종적으로 masterdevelop 같은 특정 브랜치로 merge하게 된다.

 

이런 경우 조금만 작업이 많아지면 local에 브랜치가 무한정 쌓이게 되는데, 아래처럼 git-prune.sh 라는 스크립트로 만들어서 사용하면 특정 로컬 브랜치 기준으로 merge된 브랜치를 깔끔하게 삭제할 수 있다.

 

#!/bin/bash

cbranch=$(git rev-parse --abbrev-ref HEAD); git checkout -q $cbranch && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base $cbranch $branch) && [[ $(git cherry $cbranch $(git commit-tree $(git rev-parse $branch"^{tree}") -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done

 

스크립트를 이해하기 위해서는 아래처럼 3단계로 접근하면 된다.

 

(1) 먼저 cbranch=$(git rev-parse --abbrev-ref HEAD); git checkout -q $cbranch는 현재 HEAD의 브랜치 이름을 cbranch에 저장(앞으로 기준이 될 브랜치)하고 해당 브랜치로 checkout한다. 그리고 git for-each-ref refs/heads/ "--format=%(refname:short)"명령어를 통해 현재 로컬의 브랜치 이름을 모두 가져온다.

 

(2) (1) 마지막에서 가져온 로컬 브랜치들을 순회한다. 각각 브랜치의 mergeBase(commit 해쉬값)를 설정(mergeBase=$(git merge-base $cbranch $branch))하면서 동시에 [[ $(git cherry $cbranch $(git commit-tree $(git rev-parse $branch"^{tree}") -p $mergeBase -m _)) == "-"* ]]을 만족하는 브랜치는 git branch -D $branch 명령어를 통해 삭제한다.

 

(3) (2)의 명령어를 조금 더 깊게 살펴보면 git rev-parse $branch"^{tree}"은 브랜치 tree 자체의 commit 해시값을 의미하고, $(git commit-tree $(앞에서 구한 트리 commit 값) -p $mergeBase -m \_)을 통해서 $mergeBase를 부모로하는 commit object를 생성한다. 그리고 마지막 [[ $(git cherry $cbranch $(앞에서 생성된 commit 해시값) == "-"\* ]]은 앞에서 생성한 commit object를 기준으로 현재 브랜치(기준 브랜치)에 이미 merge가 완료된(git cherry에서 (-)은 이미 merge가 완료된 것을 의미) 브랜치를 확인한다.

 

솔직히 스크립트만 보면 숨이 턱 막히는 느낌일 수 있다. 하지만 시간을 좀 투자해서 차근차근 명령어 하나씩 살펴보면 이해 할 수 있다. 물론 굳이 이해하지 않고 유용하게만 사용해도 그게 어디인가. 아래는 스크립트에서 나온 명령어들의 공식 문서 링크이다. 관심있다면 참고하면 좋을 것 같다.

 

git-scm.com/docs/git-merge-base

Git - git-merge-base Documentation

After working on the topic branch created with git switch -c topic origin/master, the history of remote-tracking branch origin/master may have been rewound and rebuilt, leading to a history of this shape: o---B2 / ---o---o---B1--o---o---o---B (origin/maste

git-scm.com

git-scm.com/docs/git-rev-parse

Git - git-rev-parse Documentation

A revision parameter typically, but not necessarily, names a commit object. It uses what is called an extended SHA-1 syntax. Here are various ways to spell object names. The ones listed near the end of this list name trees and blobs contained in a commit.

git-scm.com

git-scm.com/docs/git-cherry

Git - git-cherry Documentation

git-cherry - Find commits yet to be applied to upstream

git-scm.com