What are the differences between git remote prune, git prune, git fetch --prune, etc

git remote prune origin safe
git prune local branches not on remote
git gc --prune=now
what is the git command to see all the remote branches?
what is the command to delete a remote branch in git?
git remote update origin --prune
git fetch vs pull
git push --prune

My situation is this... someone working on the same repo has deleted a branch from his local & remote repo...

Most people who have asked about this kind of problem on Stack Overflow, or other sites have the issue of branches still showing in their remote tracking branch list git branch -a at the bottom:

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted

However, in MY situation the branch that shouldn't be there, is local:

* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah

When I do any of the following, it doesn't get removed locally:

$ git prune

I also tried:

$ git remote prune origin
$ git fetch --prune

More useful info: When I check git remote show origin this is how it looks:

* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push  URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
 master                        tracked
 develop                       tracked
 feature_blah                  tracked
 other123                      tracked
 other444                      tracked
 other999                      tracked
Local branches configured for 'git pull':
 develop                      merges with remote develop
 feature_blah                 merges with remote other999
 master                       merges with remote master
 random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for 'git push':
 develop         pushes to develop     (local out of date)
 master          pushes to master      (up to date)
 feature_blah    pushes to feature_blah(up to date)

Notice that it's only in the section titled Local branches configured for 'git pull':

Why?

I don't blame you for getting frustrated about this. The best way to look at is this. There are potentially three versions of every remote branch:

  1. The actual branch on the remote repository (e.g., remote repo at https://example.com/repo.git, refs/heads/master)
  2. Your snapshot of that branch locally (stored under refs/remotes/...) (e.g., local repo, refs/remotes/origin/master)
  3. And a local branch that might be tracking the remote branch (e.g., local repo, refs/heads/master)

Let's start with git prune. This removes objects that are no longer being referenced, it does not remove references. In your case, you have a local branch. That means there's a ref named random_branch_I_want_deleted that refers to some objects that represent the history of that branch. So, by definition, git prune will not remove random_branch_I_want_deleted. Really, git prune is a way to delete data that has accumulated in Git but is not being referenced by anything. In general, it doesn't affect your view of any branches.

git remote prune origin and git fetch --prune both operate on references under refs/remotes/... (I'll refer to these as remote references). It doesn't affect local branches. The git remote version is useful if you only want to remove remote references under a particular remote. Otherwise, the two do exactly the same thing. So, in short, git remote prune and git fetch --prune operate on number 2 above. For example, if you deleted a branch using the git web GUI and don't want it to show up in your local branch list anymore (git branch -r), then this is the command you should use.

To remove a local branch, you should use git branch -d (or -D if it's not merged anywhere). FWIW, there is no git command to automatically remove the local tracking branches if a remote branch disappears.

Git Prune, The git prune command is a housekeeping utility that cleans up What's the Difference Between Git Prune, Git Fetch --prune, and Git Remote  Now you can change the setting to prune remote branches on every fetch. In my opinion this should be the default value. In my opinion this should be the default value. Another nice addition to the Git settings in Visual Studio 2017 Update 5 is the ability to Rebase your changes when you pull.

git remote prune and git fetch --prune do the same thing: deleting the refs to the branches that don't exist on the remote, as you said. The second command connects to the remote and fetches its current branches before pruning.

However it doesn't touch the local branches you have checked out, that you can simply delete with

git branch -d  random_branch_I_want_deleted

Replace -d by -D if the branch is not merged elsewhere

git prune does something different, it purges unreachable objects, those commits that aren't reachable in any branch or tag, and thus not needed anymore.

git-fetch Documentation, When I do any of the following, it doesn't get removed locally: $ git prune. I also tried: $ git remote prune origin $ git fetch --prune. More useful  Is there any difference between git gc and git repack -ad; git prune? The difference is that by default git gc is very conservative about what housekeeping tasks are needed. For example, it won't run git repack unless the number of loose objects in the repository is above a certain threshold (configurable via the gc.auto variable).

In the event that anyone would be interested. Here's a quick shell script that will remove all local branches that aren't tracked remotely. A word of caution: This will get rid of any branch that isn't tracked remotely regardless of whether it was merged or not.

If you guys see any issues with this please let me know and I'll fix it (etc. etc.)

Save it in a file called git-rm-ntb (call it whatever) on PATH and run:

git-rm-ntb <remote1:optional> <remote2:optional> ...

clean()
{
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  RBRANCHES=()
  while read REMOTE; do
    CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "\033[32m Keeping $i \033[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
  done
}

clean $@

What are the differences between git remote prune, git , With git remote prune origin I can remove the local branches that are not on the -p, --prune After fetching, remove any remote-tracking branches which no longer too many edge cases (like a branch having "master" as part of its name, etc). prune origin --dry-run to see what it would do without making any changes. git remote prune <name> From the docs: prune. Deletes all stale remote-tracking branches under <name>. These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in “remotes/<name>”.

Note that one difference between git remote --prune and git fetch --prune is being fixed, with commit 10a6cc8, by Tom Miller (tmiller) (for git 1.9/2.0, Q1 2014):

When we have a remote-tracking branch named "frotz/nitfol" from a previous fetch, and the upstream now has a branch named "**frotz"**, fetch would fail to remove "frotz/nitfol" with a "git fetch --prune" from the upstream. git would inform the user to use "git remote prune" to fix the problem.

So: when a upstream repo has a branch ("frotz") with the same name as a branch hierarchy ("frotz/xxx", a possible branch naming convention), git remote --prune was succeeding (in cleaning up the remote tracking branch from your repo), but git fetch --prune was failing.

Not anymore:

Change the way "fetch --prune" works by moving the pruning operation before the fetching operation. This way, instead of warning the user of a conflict, it automatically fixes it.

git, Without this option old data in .git/FETCH_HEAD will be overwritten. --dry-run Show what would be done, without making any changes. -p, --prune Before fetching, remove any remote-tracking references that no longer exist on the remote. for another commit that's doesn't have the previous commit as an ancestor etc. This runs git fsck --unreachable using all the refs available in refs/, optionally with additional set of objects specified on the command line, and prunes all unpacked objects unreachable from any of these head objects from the object database. In addition, it prunes the unpacked objects that are also found in packs by running git prune-packed

git-fetch - Download objects and refs from another , The "fetch" command is indispensable for staying up-to-date in a project: only when a "git fetch" will you be informed about the changes your colleagues pushed to the To see new remote branches, commits, tags, etc., you have to explicitly tell Git to A useful parameter, however, is "prune": this tells Git to remove any  Since it is now possible to delete local git branches the remaining problem is that remote-tracking refs are accumulated over time and clutter the checkout and other menus. I think it would make sense if one could enable the --prune flag when vscode does it's periodic git fetch so that refs which don't exist anymore on the server are

git fetch - Downloading Remote Data, Summary During development, users may be deleting, force pushing etc to branches Commits · Branches · Tags · Contributors · Graph · Compare · Locked Files Granted, this could be resolved by having git fetch --prune in the pipeline, but —prune doesn't delete any local branches though, it only deletes the remote  Today’s menu of git tips says “pruning stale remote-tracking branches”: You probably know git remote command. It shows information about your remote repositories. Try this one out: $ git remote show origin. What you might not know is that this command allows you to prune all your local branches that track an already-deleted remote branch.

git fetch should use --prune (#5035) · Issues · GitLab.org / gitlab , Different repos can be connected with eachother and share the differences of data. Few repos with full access, few with read-only access etc. Any changes in the remote branch will be tracked by the local branches and 'git status' will show you the --Review what is going to pruned git fetch --prune --dry-run origin From​  The Difference between GIT Fetch and GIT Pull can be explained with the following scenario: (Keeping in mind that pictures speak louder than words!, I have provided pictorial representation) Let's take an example that you are working on a project with your team members.

Comments
  • git branch -d the_local_branch
  • Thanks, but I'm just curious as to why it might have occurred.
  • There was a subtle difference when dealing with branch hierarchy (x/y): it has been fixed (see my answer below)
  • This does a better job of addressing the overall question by explaining the pertinent differences. It also answers additional questions I had from the one above.
  • This command will show a list of all local branches that don't have a corresponding remote branch. You could pipe this to xargs git branch -D, but note that any new branches you've created but never pushed to the server would be deleted, so tread carefully: git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}'
  • @Seed No it doesn't. :-( It only deletes the local remote tracking refs. I just double-checked this with version 2.7.0.
  • @BlueRaja-DannyPflughoeft Be careful with that approach. For instance, depending on how you do your stable branches, they may appear to be merged into the master branch, and you would end up removing them. It's not a big loss here since you aren't removing them from the server, but if you had any special configuration you set for it then that would be lost when the branch is deleted.
  • @Cloud Not entirely true. References can be packed (see the packed-refs file in the .git area), so it's not necessarily a simple matter of deleting them via file explorer. Better to use the commands to make sure both are taken care of correctly.
  • I know it seems obvious, but git prune looks not only for branches and tags, but all other refs as well.
  • So in my case, why wouldn't git prune work? Because it does't care about local branches, but remote references? Thanks for the concise info.
  • @hvd what kind of refs are there other than branches and tags?
  • @gogogadgetinternet yes exactly. (supposing you meant git remote prune)
  • IMO the git naming convention of using "prune" for both object-collection and reference-cleanup is where the confusion sets in. But that's just one of many UI puzzlements, in git. :-)
  • Thanks! Nice touch with the colored output ;-)