2

Consider the following repository. It has a lot of private branches for team members, all under the refs/heads/team/ namespace, that I do not want to fetch, but I still do want to fetch all the rest, including any possibly newly created branches outside of that team namespace.

$ git ls-remote http://gerrit.asterisk.org/asterisk refs/heads/* | wc -l
217
$ git ls-remote http://gerrit.asterisk.org/asterisk refs/heads/* | grep -v refs/heads/team/ | wc -l
32

I am fetching fetch = +refs/heads/*:refs/remotes/golden/*, but these private branches are just overwhelming my refs/remote/golden namespace, making it harder to overview, and also require more space for the local repository.

Is it possible to fetch refs/heads/*, but exclude refs/heads/team/* ?

2 Answers2

5

Unfortunately, no.

Fortunately, you can get arbitrarily close, especially if you are willing to use a two-pass fetch every time, or a fetch followed by a delete pass (probably this will actually be more efficient, or at least time-efficient; it might take some more space, depending on how many objects wind up becoming useless).

Essentially the idea here is to list everything to take, by first running git ls-remote and then doing your own filtering and rewriting the fetch = entry (well, entries) for the remote:

git ls-remote "$remote" 'refs/heads/*' |
    (git config --unset-all "remote.$remote.fetch";
     while read hash ref; do
        case $ref in refs/heads/team/*) continue;; esac
        rmtref="refs/remotes/$remote/${ref#refs/heads/}"
        git config --add "remote.$remote.fetch" "+$ref:$rmtref"
     done)
git fetch "$remote"

(add some front end work to set $remote appropriately). The key that makes this work is that git combines and then obeys all the fetch = lines.

For the other idea, run a normal (+refs/heads/*:refs/remotes/...) fetch followed by a series of git update-ref -d refs/remotes/$remote/${ref#refs/heads/} for refs that match the unwanted form. Toss in a git gc (or git repack and/or prune) afterward if you like, to shrink the repository.

torek
  • 448,244
  • 59
  • 642
  • 775
2

Duplicate: Skip copying some branches/tags to local Git with git fetch --all

This is supported since Git 2.29:

Assuming your remote is named origin, you should be able to use git config --add remote.origin.fetch '^refs/heads/team/*' to exclude the refs/heads/team/ prefix from fetches.

mdonoughe
  • 515
  • 5
  • 12
  • Works like a charm, super, thank you! I dreamed of this feature for, like, 10 years, but missed it when it had been implemented, darn! As for the duplicate, I considered marking my own question as a duplicate, but the duplicate box will point to the whole question, and it has no accepted answer while your link is pointing to the answer directly. That will be confusing. For clarity, let's better leave it as is, and I'll just green-check your answer, so it will hopefully show up on top. – kkm inactive - support strike Apr 25 '23 at 14:47