Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I specify in .git/config to fetch multiple refspecs?

Tags:

git

I do not want to fetch every branch from origin because there are many. I just want to track a few (e.g., master) and my branches (organized under my_name sub-directory). I can do the following:

$ git fetch origin refs/heads/my_name/*:refs/remotes/origin/my_name/* refs/heads/master:refs/remotes/origin/master refs/heads/some_branch:refs/remotes/origin/some_branch

I want to specify the above "set" of refspecs to be the default of git fetch. I have tried

$ git config remote.origin.fetch refs/heads/my_name/*:refs/remotes/origin/my_name/*
$ git config --add remote.origin.fetch refs/heads/master:refs/remotes/origin/master

It fails:

$ git config remote.origin.fetch
refs/heads/my_name/*:refs/remotes/origin/my_name/*
error: More than one value for the key remote.origin.fetch: refs/heads/master:refs/remotes/origin/master

I also try the following but it also fails:

$ git config remote.origin.fetch 'refs/heads/my_name/*:refs/remotes/origin/my_name/* refs/heads/master:refs/remotes/origin/master refs/heads/some_branch:refs/remotes/origin/some_branch'
$ git fetch
fatal: Invalid refspec 'refs/heads/my_name/*:refs/remotes/origin/my_name/* refs/heads/master:refs/remotes/origin/master refs/heads/some_branch:refs/remotes/origin/some_branch'

Note: Git 1.7.11

like image 531
user716468 Avatar asked Mar 19 '13 18:03

user716468


People also ask

Does git fetch all fetch tags?

git fetch --tags fetches all tags, all commits necessary for them. It will not update branch heads, even if they are reachable from the tags which were fetched.

Is git fetch branch specific?

Git fetch commands and options Fetch all of the branches from the repository. This also downloads all of the required commits and files from the other repository. Same as the above command, but only fetch the specified branch.

Does git fetch update all branches?

git fetch. On its own, git fetch updates all the remote tracking branches in local repository. No changes are actually reflected on any of the local working branches.


3 Answers

You can add the following lines in your .git/config to specify multiple refspecs for fetch:

[remote "origin"]
       fetch = refs/heads/my_name/*:refs/remotes/origin/my_name/*
       fetch = refs/heads/master:refs/remotes/origin/master
       fetch = refs/heads/some_branch:refs/remotes/origin/some_branch

You can add the prefix + before the refspec, if you would like to override fetching non-fast-forward references as well, like this:

[remote "origin"]
       fetch = +refs/heads/my_name/*:refs/remotes/origin/my_name/*
       fetch = +refs/heads/master:refs/remotes/origin/master
       fetch = +refs/heads/some_branch:refs/remotes/origin/some_branch

Note that partial globbing is not supported (i.e. a/b/ca* is not supported, but a/b/* is).

10.5 Git Internals - The Refspec

like image 91
Tuxdude Avatar answered Oct 18 '22 05:10

Tuxdude


To overwrite the existing fetch refspec(s), without having to manually edit .git/config, you can use --unset-all followed by as many --add as needed.

For the example desired refspecs in the question, it would be:

git config --unset-all remote.origin.fetch
git config --add remote.origin.fetch +refs/heads/my_name/*:refs/remotes/origin/my_name/*
git config --add remote.origin.fetch +refs/heads/master:refs/remotes/origin/master

Then use git config --get-all remote.origin.fetch to verify the result.

like image 45
Shaun Avatar answered Oct 18 '22 05:10

Shaun


Note: if you want to fetch from a different refspec on a single invocation (overriding temporarily the fetch refspec registered in the config), you can do so since Git 2.1 (August 2014).

See commit c5558f8 by Junio C Hamano (gitster):

Since the introduction of opportunistic updates of remote-tracking branches, started at around f269048 (fetch: opportunistically update tracking refs, 2013-05-11) with a few updates in v1.8.4 era, the remote.*.fetch configuration always kicks in even when a refspec to specify what to fetch is given on the command line, and there is no way to disable or override it per-invocation.

Teach the command to pay attention to the --refmap=<lhs>:<rhs> command-line options that can be used to override the use of configured remote.*.fetch as the refmap.

That gives you the new option:

--refmap=<refspec>

When fetching refs listed on the command line, use the specified refspec (can be given more than once) to map the refs to remote-tracking branches, instead of the values of remote.*.fetch configuration variables for the remote repository.
See section on "Configured Remote-tracking Branches" for details.

(That Git "Configured Remote-tracking Branches" section also dates from Git 2.1: see "Having a hard time understanding git fetch")


With Git 2.25.1 (Feb. 2020), "git fetch --refmap=" option has got a better documentation.

See commit b40a502 (21 Jan 2020) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit 4b69f29, 30 Jan 2020)

fetch: document and test --refmap=""

Signed-off-by: Derrick Stolee

To prevent long blocking time during a 'git fetch' call, a user may want to set up a schedule for background 'git fetch' processes.
However, these runs will update the refs/remotes branches due to the default refspec set in the config when Git adds a remote.
Hence the user will not notice when remote refs are updated during their foreground fetches. In fact, they may want those refs to stay put so they can work with the refs from their last foreground fetch call.

This can be accomplished by overriding the configured refspec using '--refmap=' along with a custom refspec:

git fetch --refmap='' <remote> +refs/heads/*:refs/hidden/<remote>/*

to populate a custom ref space and download a pack of the new reachable objects.
This kind of call allows a few things to happen:

  1. We download a new pack if refs have updated. 2. Since the refs/hidden branches exist, GC will not remove the newly-downloaded data.
  2. With fetch.writeCommitGraph enabled, the refs/hidden refs are used to update the commit-graph file.

To avoid the refs/hidden directory from filling without bound, the --prune option can be included. When providing a refspec like this, the --prune option does not delete remote refs and instead only deletes refs in the target refspace.

Update the documentation to clarify how '--refmap=""' works and create tests to guarantee this behavior remains in the future.

So the git fetch option man page now includes:

--refmap=<refspec>:

When fetching refs listed on the command line, use the specified refspec (can be given more than once) to map the refs to remote-tracking branches, instead of the values of remote.*.fetch configuration variables for the remote repository.

Providing an empty <refspec> to the --refmap option causes Git to ignore the configured refspecs and rely entirely on the refspecs supplied as command-line arguments.
See section on "Configured Remote-tracking Branches" for details.


Note that the more aggressive updates to remote-tracking branches we had for the past 7 years or so were not reflected in the documentation, which has been corrected with Git 2.27 (Q2 2020).

See commit a440884, commit f6a65de (05 Apr 2020) by Philippe Blain (phil-blain).
(Merged by Junio C Hamano -- gitster -- in commit fdee8b1, 22 Apr 2020)

pull doc: correct outdated description of an example

Signed-off-by: Philippe Blain

Since f269048754 ("fetch: opportunistically update tracking refs", 2013-05-11, Git v1.8.4-rc0 -- merge listed in batch #0), the underlying git fetch in [git pull](https://git-scm.com/docs/git-pull) <remote> <branch> updates the configured remote-tracking branch for .

However, an example in the 'Examples' section of the git pull documentation still states that this is not the case.

Correct the description of this example.

So instead of, for git pull origin next:

This leaves a copy of next temporarily in FETCH_HEAD, but does not update any remote-tracking branches.
Using remote-tracking branches, the same can be done by invoking fetch and merge:

You now have:

This leaves a copy of next temporarily in FETCH_HEAD, and updates the remote-tracking branch origin/next.
The same can be done by invoking fetch and merge:

like image 5
VonC Avatar answered Oct 18 '22 06:10

VonC