Question

Here is the scenario: Someone has a git repository (on github if that matters) which I've forked. In my branch, I've created lots of branches with changes that the upstream has pulled. Or in some cases applied the diff of my branch instead of properly pulling the branch.

What I want to find is a list of all my branches that has been fully merged into upstreams master branch. That way I can then safely delete those branches because git branch and other tools list 30+ branches and it looks cluttered.

I thought I explained properly why this question is different from the linked one: Or in some cases applied the diff of my branch instead of properly pulling the branch e.g. git branch --mergedis not a full answer, but oh well...

No correct solution

OTHER TIPS

Depending on how often you wish to do that, you may want to do it manually (explained first) or script it (explained afterwards).

In the below it is assumed there is an "upstream" remote pointing at the repòsitory you forked e.g.:

$ git remote -v
origin git@github.com:you/repo.git (fetch)
origin git@github.com:you/repo.git (push)
upstream git://github.com/original/repo.git (fetch)
upstream git://github.com/original/repo.git (push)

List all local branches that are merged

To get a list of branches that have already been merged with the upstream master:

$ git fetch upstream
$ git branch --merged upstream/master
my-feature
my-other-feature
master

You can then delete them:

$ git branch -d my-feature
$ git branch -d my-other-feature

If changes were applied manually, they may not be in the upstream history, and so the local branch with the equivalent code changes may not be listed. Branches where this is the case should be detected manually.

Delete local references to remote branches that don't exist

If you have local branches that represent a remote branch which has already been deleted (the branch was for a pull request, and after merging the pull request you deleted the branch via github's gui) there is a standard git command for cleaning up these branch references:

$ git remote prune origin

Delete remote branches which have been merged

To get a list of remote branches in your fork which have been merged, is similar to the first command - but use the -r switch (remote branches):

$ git branch -r --merged upstream/master
origin/my-feature
origin/my-other-feature
upstream/someone-elses-branch

To delete your own remote branches that have been merged:

$ git push origin :my-feature
$ git push --delete origin my-other-feature # equivalent, just different syntax

Script solution

Be careful using a scripted solution as it's quite easy to accidentally delete a branch you didn't intend to. That said, remember that branches are just references/names - deleting a branch (by accident) doesn't mean the contents are lost they can easily be recovered (just check git reflog for example).

The below script deletes local and remote branches which begin with "feature" - this is one way to ensure your own up-to-date master branch, for example, doesn't get deleted by accident.

#!/bin/bash
# E.g. save as ~/bin/git-cleanup, make executable and have ~/bin in your path
# call as `git cleanup`

echo -n "Fetching latest ... "
git fetch origin
git fetch upstream
echo "done"

echo "Deleting merged local feature branches ... "
branches=`git branch --no-color --merged upstream/master`
for branch in $branches;
do
    if [[ "$branch" =~ ^feature ]]; then
        git branch -d $branch;
    fi
done
echo "done"

echo "Deleting local refs to remote branches that don't exist ... "
git remote prune origin
git remote prune upstream
echo "done"

echo "Deleting merged remote feature and hotfix branches ... "
branches=`git branch -r --no-color --merged upstream/master`
for branch in $branches;
do
    if [[ "$branch" =~ ^(origin)\/(feature.*$) ]]; then
        remote=${BASH_REMATCH[1]};
        branch=${BASH_REMATCH[2]};
        git push $remote :$branch;
    fi
done

echo "done"

echo ""
echo "all finished"

If you have updated your fork with the latest commits from the upstream repo (the one you have forked), you can then follow "How can I delete all git branches which are already merged?".

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d 

But that will only list merged branches (through pull requests for instance), not cherry-picking (when only the diff of one branch is applied to another).

For the second category, you might have to diff those local branches and see if they still have differences that aren't part of the main branches yet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top