for k in $(git branch -r --merged origin/master | cut -d" " -f 3); do
echo $k
done
I have a list of git projects that i want to clean up old branches in, what i want to do is list and delete all the branches that are merged to master.
Is there a way to do the above without cloning each repo locally?
Remove All Local Branches not on Remote First we get all remote branches using the git branch -r command. Next, we get the local branches not on the remote using the egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) command, Finally we delete the branches using the xargs git branch -d command.
Remove remote Git tracking branches Here is the Git command to remove a local tracking branch: git branch --remotes --delete origin/name-of-branch-to-remove. git branch -r -d origin/name-of-branch-to-remove.
Newer Git repositories have renamed the master branch to main. To delete all branches in Git except main, simply replace the grep for master with a grep for main: git branch | grep -v "main" | xargs git branch -D. git branch | grep -v " main$" | xargs git branch -D.
You need git ls-remote
:
NAME
git-ls-remote
- List references in a remote repositorySYNOPSIS
git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url] [--symref] [<repository> [<refs>...]]
DESCRIPTION
Displays references available in a remote repository along with the associated commit IDs.
So it works like:
% git ls-remote origin
af51dfb080728117d898e1d0a10e3fe01ed67063 HEAD
6a60cc68a2953f1a62b0dca641eb29509b5b6e8c refs/heads/expdate-fix
af51dfb080728117d898e1d0a10e3fe01ed67063 refs/heads/master
4c42e43b4ccfd37074d115f6e9a694ddb8b70d55 refs/heads/redux
fd18a67bbc5cbf8aa6cda136afa4e5c20ed2d522 refs/heads/rest
7ad17cdf8b0dcd1a29a1795a363279fb3c76ac66 refs/tags/test.key
be0b2d6881902600fb3d6686c10d0a47f1e6751a refs/tags/test.pub
To get only branches (heads), you need to narrow the refspec down:
% git ls-remote origin 'refs/heads/*'
6a60cc68a2953f1a62b0dca641eb29509b5b6e8c refs/heads/expdate-fix
af51dfb080728117d898e1d0a10e3fe01ed67063 refs/heads/master
4c42e43b4ccfd37074d115f6e9a694ddb8b70d55 refs/heads/redux
fd18a67bbc5cbf8aa6cda136afa4e5c20ed2d522 refs/heads/rest
Now you could script around this output like
git ls-remote origin 'refs/heads/*' | while read sha ref; do
# test if $sha is merged
done
To delete a branch, you need to "push nothing" to it, like in
git push origin :refs/heads/feature-x
(notice an empty string to the left of ":" which defined what to push to what is on the right side).
So we get something like
#!/bin/sh
set -e -u
git ls-remote origin 'refs/heads/*' | while read sha ref; do
# test if $sha is merged
E=`git cat-file -t "$sha" 2>&1`
test $? -ne 0 -a "${E#*git cat-file: *}" = "could not get object info" && continue
git branch --merged "$sha" && printf ':%s\0' "$ref"
done | xargs -0 git push origin
Note that we're using printf
shell builtin to delimit the names of the refs we output with the ASCII NUL character and then pass -0
to xargs
to expect NUL-terminated input.
This way we work around funky ref names (containing spaces etc).
Some explanations:
If git cat-file -t <object_sha1_name>
fails to locate the object
with the indicated SHA1 name in the local repository,
it exits with a non-zero exit code and prints
fatal: git cat-file: could not get object info
to its stderr.
So to test whether the history a remote ref points at exists in the local
repository we run git cat-file -t
on the SHA1 name of the object it
points at, grab the combined output of that command and then test
whether it exited with a non-zero exit code ($? -ne 0
) and
whether its error message indicates a missing object
(the ${VAR#PATTERN}
removes the prefix matching PATTERN
from the contents
of the variable VAR
and returns the resulting value).
If the history a remote ref points at does not exist in the local repository, it cannot be merged to any of the local refs by definition,
so if we detect such a ref, we skip its further testing with
git branch --merged
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With