多くの Git ブランチがあります。すでにマージされているブランチを削除するにはどうすればよいですか? それらを1つずつ削除する代わりに、それらをすべて削除する簡単な方法はありますか?
48 に答える
アップデート:
ワークフローに master や dev などのブランチが可能な祖先として含まれている場合は、除外する他のブランチを追加できます。通常、私は「sprint-start」タグから分岐し、master、dev、qa は祖先ではありません。
まず、リモートでマージされたローカル追跡ブランチを一覧表示します (他の回答で提案されているように、-r フラグを使用してすべてのリモート追跡ブランチを一覧表示することを検討できます)。
git branch --merged
削除したくないブランチがいくつか表示される場合があります。マスターや開発など、削除したくない重要なブランチをスキップする引数をいくつか追加できます。次のコマンドは、master ブランチと dev を含むブランチをすべてスキップします。
git branch --merged| egrep -v "(^\*|master|main|dev)"
スキップしたい場合は、以下のように egrep コマンドに追加できます。ブランチskip_branch_name
は削除されません。
git branch --merged| egrep -v "(^\*|master|main|dev|skip_branch_name)"
現在チェックアウトされているブランチに既にマージされているすべてのローカル ブランチを削除するには:
git branch --merged | egrep -v "(^\*|master|main|dev)" | xargs git branch -d
master と 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
すでにマージされているリモート上のすべてのブランチを削除するには:
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
UPDATE (by @oliver; コメントに収まらないため、すでに十分な回答があります) : ブランチ ABC を使用している場合git branch -r --merged
、ブランチが指定されていないため、ABC が結果に表示されます。したがって、ブランチはデフォルトで現在のブランチになり、ブランチは常にそれ自体にマージされたものと見なされます (ブランチとそれ自体の間に違いがないためです!)。
したがって、ブランチを指定します。
git branch -r --merged master | grep -v master ...
または最初のチェックアウト マスター:
git checkout master | git branch -r --merged | grep -v ...
Adamの答えを少し拡張するだけです:
実行して、これをGit構成に追加しますgit config -e --global
[alias]
cleanup = "!git branch --merged | grep -v '\\*\\|master\\|develop' | xargs -n 1 -r git branch -d"
そして、単純なgit cleanup
.
master
これらのコマンドから, main
&develop
ブランチを除外する必要があります。
ローカル git クリア:
git branch --merged | grep -v '\*\|master\|main\|develop' | xargs -n 1 git branch -d
リモート git クリア:
git branch -r --merged | grep -v '\*\|master\|main\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin
リモート ブランチのローカル レジストリを同期します。
git fetch -p
これは、マスターを除くすべてのマージされたブランチを削除する場合にも機能します。
git branch --merged | grep -v '^* master$' | grep -v '^ master$' | xargs git branch -d
--merged オプションに commit を追加できます。このようにして、オリジン/マスターにマージされたブランチのみを削除するようにすることができます
次のコマンドは、オリジンからマージされたブランチを削除します。
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete
git push origin --delete を echo に置き換えて、どのブランチが削除されるかをテストできます
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
次の Ruby スクリプトを使用して、既にマージされているローカル ブランチとリモート ブランチを削除します。複数のリモートを持つリポジトリに対して実行していて、そのうちの 1 つだけを削除したい場合は、select ステートメントをリモート リストに追加して、必要なリモートのみを取得します。
#!/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
Git には、これを自動的に行うコマンドはありません。ただし、Git コマンドを使用して必要なものを提供するスクリプトを作成することはできます。これは、使用している分岐モデルに応じてさまざまな方法で実行できます。
ブランチが master にマージされているかどうかを知る必要がある場合、myTopicBranch がマージされている (つまり、削除できる) 場合、次のコマンドは出力を生成しません。
$ git rev-list master | grep $(git rev-parse myTopicBranch)
Git branch コマンドを使用して、Bash のすべてのブランチを解析し、すべてのブランチに対してfor
ループを実行できます。このループでは、ブランチを削除できるかどうかを上記のコマンドで確認します。
git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d
は、現在チェックアウトされているブランチおよび/または を除くすべてのローカル ブランチを削除しますmaster
。
これらのコマンドを理解しようとしている人には、次の記事が役立ちます: Git Clean: Delete Already Merged Branches, by Steven Harman。
私は git-flow 風の命名スキームを使用しているため、これは非常に安全に機能します。
git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d
fix/
基本的に、文字列またはで始まるマージされたコミットを探しますfeature/
。
Adam の更新された回答のエイリアス バージョン:
[alias]
branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"
また、複雑なエイリアスをエスケープするための便利なヒントについては、この回答を参照してください。
現在のブランチに既にマージされているすべてのローカル ブランチを削除したい場合は、以前の回答に基づいて、そうするための安全なコマンドを考え出しました。
git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d
このコマンドは、現在のブランチまたはマスター ブランチには影響しません。また、xargs の -t フラグを使用して、実行前に何をしているかを通知します。
受け入れられた解決策は非常に優れていますが、まだリモートにマージされていないローカル ブランチも削除するという 1 つの問題があります。
の出力を見ると、次のようなものが表示されます
$ 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
まだマージされていないブランチを保護します。また、マスターがそれを保護するための grep は必要ありません。
これらの回答のいくつかに基づいて、独自の Bash スクリプトも作成しました。
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
}
次のコマンドを試してください。
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 |
beforecut
を追加してorigin
.
上記のコマンドが失敗した場合は、最初にマージされたリモート追跡ブランチを削除してみてください。
git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
次にgit fetch
、リモートを再度使用して、前のgit push -vd
コマンドを再度使用します。
~/.gitconfig
頻繁に使用する場合は、エイリアスとしてファイルに追加することを検討してください。
誤っていくつかのブランチを削除した場合はgit reflog
、失われたコミットを見つけるために使用します。
master 以外のブランチから誤ってコマンドを実行しないようにするために、次の bash スクリプトを使用します。そうgit branch --merged | grep -v "\*" | xargs -n 1 git branch -d
しないと、マスターからマージされたブランチから実行すると、マスター ブランチが削除される可能性があります。
#!/bin/bash
branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||
branch_name="(unnamed branch)" # detached HEAD
branch_name=${branch_name##refs/heads/}
if [[ $branch_name == 'master' ]]; then
read -r -p "Are you sure? [y/N] " response
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
fi
else
echo "Refusing to delete branches that are not merged into '$branch_name'. Checkout master first."
fi
git cleanup
git-toolbeltのスクリプト
マスターまたは開発に既にマージされているすべてのブランチを削除します。他の枝を横に保ちます。削除に関して最も保守的になります。
ローカルとオリジン リモートの両方でブランチを削除します。
私の Bash スクリプトへの貢献は、大まかにmmrobin's answerに基づいています。
インクルードとエクスクルードを指定したり、両方ではなくローカルブランチまたはリモートブランチのみを調査/削除したりするために、いくつかの便利なパラメーターが必要です。
#!/bin/bash
# exclude branches regex, configure as "(branch1|branch2|etc)$"
excludes_default="(master|next|ag/doc-updates)$"
excludes="__NOTHING__"
includes=
merged="--merged"
local=1
remote=1
while [ $# -gt 0 ]; do
case "$1" in
-i) shift; includes="$includes $1" ;;
-e) shift; excludes="$1" ;;
--no-local) local=0 ;;
--no-remote) remote=0 ;;
--all) merged= ;;
*) echo "Unknown argument $1"; exit 1 ;;
esac
shift # next option
done
if [ "$includes" == "" ]; then
includes=".*"
else
includes="($(echo $includes | sed -e 's/ /|/g'))"
fi
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 -e "Fetching branches...\n"
git remote update --prune
remote_branches=$(git branch -r $merged | grep -v "/$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")
local_branches=$(git branch $merged | grep -v "$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")
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 [ "$remote" == 1 -a -n "$remote_branches" ]; then
echo "$remote_branches"
fi
if [ "$local" == 1 -a -n "$local_branches" ]; then
echo "$local_branches"
fi
read -p "Continue? (y/n): " -n 1 choice
echo
if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
if [ "$remote" == 1 ]; then
remotes=$(git remote)
# Remove remote branches
for remote in $remotes
do
branches=$(echo "$remote_branches" | grep "$remote/" | sed "s/$remote\/\(.*\)/:\1 /g" | tr -d '\n')
git push $remote $branches
done
fi
if [ "$local" == 1 ]; then
# Remove local branches
locals=$(echo "$local_branches" | sed 's/origin\///g' | tr -d '\n')
if [ -z "$locals" ]; then
echo "No branches removed."
else
git branch -d $(echo "$locals" | tr -d '\n')
fi
fi
fi
fi
HubFlow や GitFlow などの分岐モデルを使用している場合は、このコマンドを使用してマージされた機能分岐を削除できます。
git branch --merged | grep feature.* | grep -v "\*" | xargs -n 1 git branch -d
マージされたローカルブランチを削除し、それらのリモートを削除したい場合は、私が好むワンライナーを次に示します。
git branch --merged | xargs -I_br -- sh -c 'git branch -d _br; git push origin --delete _br'