Delete local Git branches after deleting them on the remote repo

GitGithubBranchPullRepository

Git Problem Overview


I want to have my local and remote repositories always in sync in terms of branches.

After a Pull Request review on GitHub, I merge and remove my branch there (remote). How could I fetch this information in my local repository and get Git to remove my local version of the branch as well?

Git Solutions


Solution 1 - Git

##The quick way

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

NB: if you're not on master, this has the potential to delete the branch. Keep reading for the "better way".

##Make sure we keep master You can ensure that master, or any other branch for that matter, doesn't get removed by greping for more. In that case you would go:

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

So if we wanted to keep master, develop and staging for instance, we would go:

git branch --merged | grep -v "\*" | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d

##Make this an alias Since it's a bit long, you might want to add an alias to your .zshrc or .bashrc. Mine is called gbpurge (for git branches purge):

alias gbpurge='git branch --merged | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d'

Then reload your .bashrc or .zshrc:

. ~/.bashrc

or

. ~/.zshrc

Solution 2 - Git

I use the same flow with GitHub, and didn't find the previous answers satisfying me, as git branch --merged lists branches which were merged, but not every of them was removed remotely in my case. So, this worked for me:

git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d

where:

  • git fetch --all -p: update local branches status
  • git branch -vv: list local branches status
  • grep ": gone]": filter deleted ones
  • awk '{ print $1 }': extract their names
  • xargs -n 1 git branch -d: pass the name to the delete command

Note: if you prefer, you could use -D instead of -d, which enforces the delete.

For example:

someUsr@someHost:~/repo$ git branch -a
basic-testing
integration-for-tests
* master
origin
playground-for-tests
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

someUsr@someHost:~/repo$ git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d
Fetching origin
Deleted branch integration-for-tests (was fbc609a).
Deleted branch playground-for-tests (was 584b900).

someUsr@someHost:~/repo$ git branch -a
basic-testing
* master
origin
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

Reference:

http://git-scm.com/book/en/v2/Git-Branching-Remote-Branches

Solution 3 - Git

try:

git pull --prune
which deletes your local branch, if its corresponding remote branch is deleted.

Updated:

The statement above is not that correct.

In fact, running git pull --prune will only REMOVE the remote-tracking branches such like

remotes/origin/fff
remotes/origin/dev
remotes/origin/master

Then, you can run git branch -r to check the remote-tracking branches left on your machine. Suppose the left branches are:

origin/dev
origin/master

which means the branch origin/fff is deleted.

So, after running git pull --prune, just run:

git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-)

you can find out all the local branches which:

  1. have no correspoding remote branches any more;
  2. can be removed safely.

then, <the command above> | xargs git branch -d can delete all of them.

Solution 4 - Git

This should work to avoid deleting the master and development branches with the accepted solution:

git branch --merged | egrep -v "^\*|master|development" | xargs -n 1 git branch -d

Solution 5 - Git

For people using powershell, this is the equivalent to the answer above:

git branch -vv | Select-String -Pattern ': gone]' | ForEach-Object{($_ -split "\s+")[1]} | %{ git branch -D $_ }
  1. Filter all the branches that are marked as gone
  2. Call git branch -D on each of the found branches

Solution 6 - Git

Very simple solution: remove your local repo and clone the remote one anew. May not seem very elegant, but it is simple and you'll understand exactly what you're doing without reading man pages :-).

Solution 7 - Git

None of this was working for me. You can see my other answer here: https://stackoverflow.com/a/34969726/550454

But essentially, I now have this in my ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d

Solution 8 - Git

In the event that you've just pushed and merged your branch to master, then do the following in git bash:

git branch -d branch_name_to_delete

If you're currently in that branch it will push you back to master. At this point do a pull with

git pull

Solution 9 - Git

I just do that to remove merged local branches:

git branch -d $(git branch --merged)

and in case you want to remove inexistent trackings too:

git pull --prune

Solution 10 - Git

I've written this one-liner to list all local branches which do not have corresponding remote branch:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -

After this done, deleting these local branches is easy with xargs:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -|xargs -r git branch -d

Solution 11 - Git

The voted answer does have the potential to delete master. Consdier the below practical example.

I had two feature branches hemen_README and hemen_BASEBOX which were merged into develop, and then develop was merged into master. The feature branches hemen_README and hemen_BASEBOX were deleted remotely but were still showing up locally. Also i am not on master locally, but on develop.

In that case

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
	* develop                      671ad6c Merged in hemen_README (pull request #1)
		hemen_BASEBOX                a535c0f added global exec paths to puppet manifest
		hemen_README                 ba87489 Updated Readme with considerable details
		master                       8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
		remotes/origin/develop       671ad6c Merged in hemen_README (pull request #1)
		remotes/origin/hemen_BASEBOX a535c0f added global exec paths to puppet manifest
		remotes/origin/hemen_README  ba87489 Updated Readme with considerable details
		remotes/origin/master        2f093ce Merged in develop (pull request #3)

So if i run the above partial command

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch --merged | grep -v "\*"
		hemen_BASEBOX
		hemen_README
		master

Notice that it shows master too, which will eventually be deleted.

In any case I was able to do it. I am sharing my session log with you on how I achieved that.

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin --dry-run
	Pruning origin
	URL: git@bitbucket.org:hemenkapadiapublic/vagrant-webdev.git
	 * [would prune] origin/hemen_BASEBOX
	 * [would prune] origin/hemen_README
	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin 
	Pruning origin
	URL: git@bitbucket.org:hemenkapadiapublic/vagrant-webdev.git
	 * [pruned] origin/hemen_BASEBOX
	 * [pruned] origin/hemen_README
	 

I just checked whay will be pruned and then pruned it. looking at branch command below we have taken care of remotes

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
	* develop                671ad6c Merged in hemen_README (pull request #1)
		hemen_BASEBOX          a535c0f added global exec paths to puppet manifest
		hemen_README           ba87489 Updated Readme with considerable details
		master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
		remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
		remotes/origin/master  2f093ce Merged in develop (pull request #3)
		

Now go ahead and delete local branches

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_BASEBOX 
	Deleted branch hemen_BASEBOX (was a535c0f).
	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_README
	Deleted branch hemen_README (was ba87489).
	

Good now the branches are as desired.

	hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
	* develop                671ad6c Merged in hemen_README (pull request #1)
		master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
		remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
		remotes/origin/master  2f093ce Merged in develop (pull request #3)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsf89View Question on Stackoverflow
Solution 1 - Gitsf89View Answer on Stackoverflow
Solution 2 - GitAlessioView Answer on Stackoverflow
Solution 3 - Gitnicky_zsView Answer on Stackoverflow
Solution 4 - GitIntrepidView Answer on Stackoverflow
Solution 5 - GitamaechlerView Answer on Stackoverflow
Solution 6 - Gituser4117783View Answer on Stackoverflow
Solution 7 - GitKarl WilburView Answer on Stackoverflow
Solution 8 - GitJoshua SchlichtingView Answer on Stackoverflow
Solution 9 - GitalacambraView Answer on Stackoverflow
Solution 10 - Gitks1322View Answer on Stackoverflow
Solution 11 - GitHemen KapadiaView Answer on Stackoverflow