Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop fetching a given branch from a given remote?

Tags:

git

I've just added a new remote to my local repository and fetched, now I got all the branches from the new remote fetched. There's one branch I have no interest, and I want to stop fetching it when I do git fetch <new remote>.

How do I stop fetching such remote branch?

I've done git branch -d -r <new remote>/<non-wanted branch> but I need to do something more to stop refetching it at each git fetch <new remote>.

like image 507
pepper_chico Avatar asked Sep 18 '13 03:09

pepper_chico


1 Answers

As opatut noted, there's little if any benefit to "not fetching" the remote's branch references: just don't use the ones you don't care about.

If you have some automated thingy that insists on using them [edit: and want to blacklist certain branches—if you just want to white-list, see below], there are two workarounds:

  • delete them every time (requires doing something after git fetch)
  • use the trick described below (also requires doing something after git fetch)

A "remote branch" is simply a reference of the form refs/remotes/rmt/br, where rmt is the name of the remote (e.g., origin) and br is the name of the branch (e.g., master). What creates them is this line that you will see in your repo's .git/config file (run git config -e to bring it up in your editor):

fetch = +refs/heads/*:refs/remotes/origin/*

This tells git fetch that it should take all the ref names matching refs/heads/* and update them (forcibly, because of the + character—otherwise they would be limited to fast-forward updates) but change their name to refs/remotes/origin/*, where the * part obviously matches.

Thus, if you change this to:

fetch = +refs/heads/*:refs/real-remotes/origin/*

the git fetch operation will update (or create if needed) refs/real-remotes/origin instead of refs/remotes/origin.

You can then do:

git for-each-ref refs/real-remotes/origin/

to enumerate all these refs (with all the options available in git for-each-ref), and run them through scripts that remove any black-listed ones and update the remaining ones in refs/remotes/origin/. For instance:

git for-each-ref refs/real-remotes/origin/ |
while read sha1 reftype refname; do
    shortname=${refname#refs/real-remotes/origin/}
    if [ $shortname != master ]; then
        git update-ref refs/remotes/origin/$shortname $sha1
    fi
done

This updates everything except master (which is a very odd thing to do, but hey, we have just done it). (Side note: it "hard-links", as it were, a remote ref that is symbolic, e.g., if there's a HEAD that is a ref: ref/remotes/origin/master this turns it into whatever that would refer to. Use git symbolic-ref to test for such refs, although it's up to you to figure out what to do with them, once you find any.)

(The primary difference between this and explicitly deleting some particular remote branch is that this version leaves the remote branch around, without updating it. For instance, this leaves origin/master unmoved; the "real" remote master is now only in refs/real-remotes/origin/master.)

[Edit: if you just want to white list particular branches, just list them explicitly:

fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/devel:refs/remotes/origin/devel

Use as many fetch = lines as needed. Note that git fetch will error out if the remote no longer has one of these branches, though.]

like image 138
torek Avatar answered Oct 21 '22 08:10

torek