Reputation: 5248
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?
Upvotes: 191
Views: 80175
Reputation: 2464
I wanted a PowerShell implementation like amaechler's answer, but I also wanted the git remote prune origin
behavior and git prune-branches
alias from Karl Wilbur's answer.
Adding remote prune
was straightforward:
git remote prune origin; git branch -vv | Select-String -Pattern ': gone]' | %{($_ -split '\s+')[1]} | %{ git branch -d $_ }
Adding the prune-branches
alias was more difficult. Due to the command line chaining by git, cmd, and PowerShell (with different quoting syntaxes), I couldn't get a single-line config alias
command to work. However, if you execute the following three lines in a PowerShell console, then it will add the git prune-branches
alias globally:
$command = "git remote prune origin; git branch -vv | Select-String -Pattern ': gone]' | %{(`$_ -split '\s+')[1]} | %{ git branch -d `$_ }"
$base64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command))
git config --global alias.prune-branches "!powershell.exe -EncodedCommand $base64"
Note: If you're merging via squash commits, you'll need to change the -d
parameter to -D
in the last call to git branch
. Otherwise, you'll get errors like The branch 'x' is not fully merged
because squashing only preserves file changes not commit history. See this answer for more info.
Upvotes: 0
Reputation: 3773
try:
git pull --prune
which deletes your local branch, if its corresponding remote branch is deleted.
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:
then, <the command above> | xargs git branch -d
can delete all of them. So, the final command is:
git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-) | xargs git branch -d
Upvotes: 82
Reputation: 935
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 $_ }
git branch -D
on each of the found branches (using -D
to delete a branch irrespective of its merged status).Upvotes: 22
Reputation: 3450
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
Upvotes: 7
Reputation: 577
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
Upvotes: 2
Reputation: 3193
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 statusgit branch -vv
: list local branches statusgrep ": gone]"
: filter deleted onesawk '{ print $1 }'
: extract their namesxargs -n 1 git branch -d
: pass the name to the delete commandNote: 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
Upvotes: 117
Reputation: 5248
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".
You can ensure that master
, or any other branch for that matter, doesn't get removed by grep
ing 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
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
Upvotes: 198
Reputation: 35815
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
Upvotes: 1
Reputation: 6217
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
Upvotes: 7
Reputation:
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 :-).
Upvotes: 13
Reputation: 341
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
Upvotes: 24
Reputation: 1
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: [email protected]: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: [email protected]: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)
Upvotes: -2