我可以在 .git/config 中指定获取多个 refspecs 吗?

43

我不想从源获取每个分支,因为有很多。 我只想跟踪一些分支(例如master)和我的分支(在my_name子目录下组织)。 我可以执行以下操作:

$ 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

我希望将上述的“set” refspec指定为git fetch的默认设置。我已经尝试过。

$ 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

它失败了:

$ 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

我也尝试了以下方法,但它也失败了:

$ 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'

注意:Git 1.7.11


1
注意:自Git 2.1(2014年8月)以来,您可以使用新的fetch选项“--refmap = <refspec>”在每次调用时覆盖fetch refspec(仅适用于一个命令)。请参见下面的我的答案 - VonC
4个回答

46

你可以在你的.git/config中添加以下行以指定多个用于fetch的refspecs:

[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

如果您想覆盖获取非快进引用,可以在refspec之前添加前缀+,例如:

[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

请注意,不支持部分通配符(即a/b/ca*不受支持,但支持a/b/*)。

10.5 Git 内部原理 - 引用规范


1
我意识到 "git config remote.origin.fetch" 报告的错误并不意味着它不能使用多个值。我只需要使用 "git config --get-all remote.origin.fetch" 以不同的方式查询它即可。 - user716468
2
@Tuxdude,谢谢你的回复。有没有一条命令可以实现上述功能?我正在尝试让我的文档对新开发人员保持简洁,我希望他们可以通过“git config remote.origin.fetch”指定多个refspecs,而不是编辑他们的git配置文件。 - danjah
@Danjah 像“+refs/heads/master:refs/remotes/origin/master”这样的东西会起作用。 - jmnas

33

如果想要覆盖现有的fetch refspec(而不必手动编辑.git/config),您可以使用--unset-all,然后跟随需要的任意数量的--add

对于问题中所需的参考规范示例,应为:

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

然后使用 git config --get-all remote.origin.fetch 来验证结果。


正是我需要的!实际上,当版本标签被更新时,这可以防止旧标签成为障碍,并在没有对新标签产生任何影响和缓存的情况下进行更新。你甚至可以毫无问题地回到旧标签。 - taranaki
另一个要考虑的选项是使用 git config --fixed-value --unset,然后跟着使用 git config --add,如果它是在许多人可能使用的脚本中完成的。 - Noel Yap

6
注意:如果你想要在单次调用中从不同的refspec获取(暂时覆盖在配置中注册的fetch refspec),自Git 2.1(2014年8月)以来,你可以这样做。
参见提交 c5558f8,由Junio C Hamano(gitster提供。
自从远程跟踪分支的机会主义更新引入以来,始于f269048fetch:机会主义地更新跟踪引用,2013-05-11),在v1.8.4时代进行了一些更新,即使在命令行上给出了指定要获取的refspec,remote.*.fetch配置总是会启动,并且没有办法在每次调用时禁用或覆盖它。教导该命令注意--refmap=<lhs>:<rhs>命令行选项,可用于覆盖已配置的remote.*.fetch作为refmap。这提供了新选项:
--refmap=<refspec>

当从命令行获取列出的引用时,使用指定的refspec(可以多次给出)将引用映射到远程跟踪分支,而不是使用远程存储库的remote.*.fetch配置变量的值。
有关详细信息,请参见“配置的远程跟踪分支”部分。
(该Git“配置的远程跟踪分支”部分也来自Git 2.1:请参见“难以理解git fetch”)

在Git 2.25.1(2020年2月)中,“git fetch --refmap=”选项有了更好的文档。

参见提交 b40a502(2020年1月21日),由Derrick Stolee (derrickstolee)执行。
(由Junio C Hamano -- gitster --提交4b69f29中合并,2020年1月30日)

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.

因此,git fetch 选项手册页面现在包括:
--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.


请注意,过去7年左右我们对远程跟踪分支进行的更激进的更新没有体现在文档中,这已在Git 2.27(2020年第二季度)中得到纠正。
请参见提交a440884提交f6a65de(由Philippe Blain (phil-blain)于2020年4月5日完成)。
(由Junio C Hamano -- gitster --合并于提交fdee8b1,2020年4月22日)

拉取文档:更正一个示例的过时描述

由Philippe Blain签署

自从f269048754 ("fetch: opportunistically update tracking refs",2013年5月11日,Git v1.8.4-rc0 -- 合并 列在 批次 #0中),[git pull](https://git-scm.com/docs/git-pull) <remote> <branch> 中的git fetch会更新已配置的远程跟踪分支。

然而,在 git pull 文档的“示例”部分中,有一个示例仍然说明这不是情况。

更正此示例的描述。

所以,不要使用 git pull origin next 命令:

这会在 FETCH_HEAD 中暂时留下一个 next 的副本,但不会更新任何远程跟踪分支。
使用远程跟踪分支,可以通过调用 fetch 和 merge 命令来完成相同的操作:

现在你有:

这会在 FETCH_HEAD 中暂时留下一个 next 的副本,并且更新远程跟踪分支 origin/next
可以通过调用 fetch 和 merge 命令来完成相同的操作:


使用--refmap的一个实际示例将在这里非常有用。我不确定任何地方都存在单个清晰的示例。 - Paul

2

回答关于refmap缺乏示例的投诉。这是一个从VSO(Visual Studio Online)检出拉取请求的示例,而不与配置进行交互。

$ git fetch --refmap='+refs/pull/*/merge:refs/remotes/origin/pr/*' origin refs/pull/1415/merge $ git checkout pr/1415


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接