Merge branch 'jc/fetch-pull-refmap'
* jc/fetch-pull-refmap: docs: Explain the purpose of fetch's and pull's <refspec> parameter. fetch: allow explicit --refmap to override configuration fetch doc: add a section on configured remote-tracking branches fetch doc: remove "short-cut" section fetch doc: update refspec format description fetch doc: on pulling multiple refspecs fetch doc: remove notes on outdated "mixed layout" fetch doc: update note on '+' in front of the refspec fetch doc: move FETCH_HEAD material lower and add an example fetch doc: update introductory part for clarity
This commit is contained in:
commit
a668853c67
@ -72,6 +72,14 @@ endif::git-pull[]
|
|||||||
setting. See linkgit:git-config[1].
|
setting. See linkgit:git-config[1].
|
||||||
|
|
||||||
ifndef::git-pull[]
|
ifndef::git-pull[]
|
||||||
|
--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.
|
||||||
|
|
||||||
-t::
|
-t::
|
||||||
--tags::
|
--tags::
|
||||||
Fetch all tags from the remote (i.e., fetch remote tags
|
Fetch all tags from the remote (i.e., fetch remote tags
|
||||||
|
@ -17,22 +17,20 @@ SYNOPSIS
|
|||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Fetches named heads or tags from one or more other repositories,
|
Fetch branches and/or tags (collectively, "refs") from one or more
|
||||||
along with the objects necessary to complete them.
|
other repositories, along with the objects necessary to complete their
|
||||||
|
histories. Remote-tracking branches are updated (see the description
|
||||||
|
of <refspec> below for ways to control this behavior).
|
||||||
|
|
||||||
The ref names and their object names of fetched refs are stored
|
By default, any tag that points into the histories being fetched is
|
||||||
in `.git/FETCH_HEAD`. This information is left for a later merge
|
also fetched; the effect is to fetch tags that
|
||||||
operation done by 'git merge'.
|
|
||||||
|
|
||||||
By default, tags are auto-followed. This means that when fetching
|
|
||||||
from a remote, any tags on the remote that point to objects that exist
|
|
||||||
in the local repository are fetched. The effect is to fetch tags that
|
|
||||||
point at branches that you are interested in. This default behavior
|
point at branches that you are interested in. This default behavior
|
||||||
can be changed by using the --tags or --no-tags options, by
|
can be changed by using the --tags or --no-tags options or by
|
||||||
configuring remote.<name>.tagopt, or by using a refspec that fetches
|
configuring remote.<name>.tagopt. By using a refspec that fetches tags
|
||||||
tags explicitly.
|
explicitly, you can fetch tags that do not point into branches you
|
||||||
|
are interested in as well.
|
||||||
|
|
||||||
'git fetch' can fetch from either a single named repository,
|
'git fetch' can fetch from either a single named repository or URL,
|
||||||
or from several repositories at once if <group> is given and
|
or from several repositories at once if <group> is given and
|
||||||
there is a remotes.<group> entry in the configuration file.
|
there is a remotes.<group> entry in the configuration file.
|
||||||
(See linkgit:git-config[1]).
|
(See linkgit:git-config[1]).
|
||||||
@ -40,6 +38,10 @@ there is a remotes.<group> entry in the configuration file.
|
|||||||
When no remote is specified, by default the `origin` remote will be used,
|
When no remote is specified, by default the `origin` remote will be used,
|
||||||
unless there's an upstream branch configured for the current branch.
|
unless there's an upstream branch configured for the current branch.
|
||||||
|
|
||||||
|
The names of refs that are fetched, together with the object names
|
||||||
|
they point at, are written to `.git/FETCH_HEAD`. This information
|
||||||
|
may be used by scripts or other git commands, such as linkgit:git-pull[1].
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
include::fetch-options.txt[]
|
include::fetch-options.txt[]
|
||||||
@ -49,6 +51,55 @@ include::pull-fetch-param.txt[]
|
|||||||
include::urls-remotes.txt[]
|
include::urls-remotes.txt[]
|
||||||
|
|
||||||
|
|
||||||
|
CONFIGURED REMOTE-TRACKING BRANCHES[[CRTB]]
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
You often interact with the same remote repository by
|
||||||
|
regularly and repeatedly fetching from it. In order to keep track
|
||||||
|
of the progress of such a remote repository, `git fetch` allows you
|
||||||
|
to configure `remote.<repository>.fetch` configuration variables.
|
||||||
|
|
||||||
|
Typically such a variable may look like this:
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
[remote "origin"]
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
This configuration is used in two ways:
|
||||||
|
|
||||||
|
* When `git fetch` is run without specifying what branches
|
||||||
|
and/or tags to fetch on the command line, e.g. `git fetch origin`
|
||||||
|
or `git fetch`, `remote.<repository>.fetch` values are used as
|
||||||
|
the refspecs---they specify which refs to fetch and which local refs
|
||||||
|
to update. The example above will fetch
|
||||||
|
all branches that exist in the `origin` (i.e. any ref that matches
|
||||||
|
the left-hand side of the value, `refs/heads/*`) and update the
|
||||||
|
corresponding remote-tracking branches in the `refs/remotes/origin/*`
|
||||||
|
hierarchy.
|
||||||
|
|
||||||
|
* When `git fetch` is run with explicit branches and/or tags
|
||||||
|
to fetch on the command line, e.g. `git fetch origin master`, the
|
||||||
|
<refspec>s given on the command line determine what are to be
|
||||||
|
fetched (e.g. `master` in the example,
|
||||||
|
which is a short-hand for `master:`, which in turn means
|
||||||
|
"fetch the 'master' branch but I do not explicitly say what
|
||||||
|
remote-tracking branch to update with it from the command line"),
|
||||||
|
and the example command will
|
||||||
|
fetch _only_ the 'master' branch. The `remote.<repository>.fetch`
|
||||||
|
values determine which
|
||||||
|
remote-tracking branch, if any, is updated. When used in this
|
||||||
|
way, the `remote.<repository>.fetch` values do not have any
|
||||||
|
effect in deciding _what_ gets fetched (i.e. the values are not
|
||||||
|
used as refspecs when the command-line lists refspecs); they are
|
||||||
|
only used to decide _where_ the refs that are fetched are stored
|
||||||
|
by acting as a mapping.
|
||||||
|
|
||||||
|
The latter use of the `remote.<repository>.fetch` values can be
|
||||||
|
overridden by giving the `--refmap=<refspec>` parameter(s) on the
|
||||||
|
command line.
|
||||||
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@ -76,6 +127,19 @@ the local repository by fetching from the branches (respectively)
|
|||||||
The `pu` branch will be updated even if it is does not fast-forward,
|
The `pu` branch will be updated even if it is does not fast-forward,
|
||||||
because it is prefixed with a plus sign; `tmp` will not be.
|
because it is prefixed with a plus sign; `tmp` will not be.
|
||||||
|
|
||||||
|
* Peek at a remote's branch, without configuring the remote in your local
|
||||||
|
repository:
|
||||||
|
+
|
||||||
|
------------------------------------------------
|
||||||
|
$ git fetch git://git.kernel.org/pub/scm/git/git.git maint
|
||||||
|
$ git log FETCH_HEAD
|
||||||
|
------------------------------------------------
|
||||||
|
+
|
||||||
|
The first command fetches the `maint` branch from the repository at
|
||||||
|
`git://git.kernel.org/pub/scm/git/git.git` and the second command uses
|
||||||
|
`FETCH_HEAD` to examine the branch with linkgit:git-log[1]. The fetched
|
||||||
|
objects will eventually be removed by git's built-in housekeeping (see
|
||||||
|
linkgit:git-gc[1]).
|
||||||
|
|
||||||
BUGS
|
BUGS
|
||||||
----
|
----
|
||||||
|
@ -12,9 +12,23 @@ ifndef::git-pull[]
|
|||||||
endif::git-pull[]
|
endif::git-pull[]
|
||||||
|
|
||||||
<refspec>::
|
<refspec>::
|
||||||
The format of a <refspec> parameter is an optional plus
|
Specifies which refs to fetch and which local refs to update.
|
||||||
`+`, followed by the source ref <src>, followed
|
When no <refspec>s appear on the command line, the refs to fetch
|
||||||
by a colon `:`, followed by the destination ref <dst>.
|
are read from `remote.<repository>.fetch` variables instead
|
||||||
|
ifndef::git-pull[]
|
||||||
|
(see <<CRTB,CONFIGURED REMOTE-TRACKING BRANCHES>> below).
|
||||||
|
endif::git-pull[]
|
||||||
|
ifdef::git-pull[]
|
||||||
|
(see linkgit:git-fetch[1]).
|
||||||
|
endif::git-pull[]
|
||||||
|
+
|
||||||
|
The format of a <refspec> parameter is an optional plus
|
||||||
|
`+`, followed by the source ref <src>, followed
|
||||||
|
by a colon `:`, followed by the destination ref <dst>.
|
||||||
|
The colon can be omitted when <dst> is empty.
|
||||||
|
+
|
||||||
|
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
|
||||||
|
it requests fetching everything up to the given tag.
|
||||||
+
|
+
|
||||||
The remote ref that matches <src>
|
The remote ref that matches <src>
|
||||||
is fetched, and if <dst> is not empty string, the local
|
is fetched, and if <dst> is not empty string, the local
|
||||||
@ -24,55 +38,34 @@ is updated even if it does not result in a fast-forward
|
|||||||
update.
|
update.
|
||||||
+
|
+
|
||||||
[NOTE]
|
[NOTE]
|
||||||
If the remote branch from which you want to pull is
|
When the remote branch you want to fetch is known to
|
||||||
modified in non-linear ways such as being rewound and
|
be rewound and rebased regularly, it is expected that
|
||||||
rebased frequently, then a pull will attempt a merge with
|
its new tip will not be descendant of its previous tip
|
||||||
an older version of itself, likely conflict, and fail.
|
(as stored in your remote-tracking branch the last time
|
||||||
It is under these conditions that you would want to use
|
you fetched). You would want
|
||||||
the `+` sign to indicate non-fast-forward updates will
|
to use the `+` sign to indicate non-fast-forward updates
|
||||||
be needed. There is currently no easy way to determine
|
will be needed for such branches. There is no way to
|
||||||
or declare that a branch will be made available in a
|
determine or declare that a branch will be made available
|
||||||
repository with this behavior; the pulling user simply
|
in a repository with this behavior; the pulling user simply
|
||||||
must know this is the expected usage pattern for a branch.
|
must know this is the expected usage pattern for a branch.
|
||||||
+
|
ifdef::git-pull[]
|
||||||
[NOTE]
|
|
||||||
You never do your own development on branches that appear
|
|
||||||
on the right hand side of a <refspec> colon on `Pull:` lines;
|
|
||||||
they are to be updated by 'git fetch'. If you intend to do
|
|
||||||
development derived from a remote branch `B`, have a `Pull:`
|
|
||||||
line to track it (i.e. `Pull: B:remote-B`), and have a separate
|
|
||||||
branch `my-B` to do your development on top of it. The latter
|
|
||||||
is created by `git branch my-B remote-B` (or its equivalent `git
|
|
||||||
checkout -b my-B remote-B`). Run `git fetch` to keep track of
|
|
||||||
the progress of the remote side, and when you see something new
|
|
||||||
on the remote branch, merge it into your development branch with
|
|
||||||
`git pull . remote-B`, while you are on `my-B` branch.
|
|
||||||
+
|
+
|
||||||
[NOTE]
|
[NOTE]
|
||||||
There is a difference between listing multiple <refspec>
|
There is a difference between listing multiple <refspec>
|
||||||
directly on 'git pull' command line and having multiple
|
directly on 'git pull' command line and having multiple
|
||||||
`Pull:` <refspec> lines for a <repository> and running
|
`remote.<repository>.fetch` entries in your configuration
|
||||||
|
for a <repository> and running a
|
||||||
'git pull' command without any explicit <refspec> parameters.
|
'git pull' command without any explicit <refspec> parameters.
|
||||||
<refspec> listed explicitly on the command line are always
|
<refspec>s listed explicitly on the command line are always
|
||||||
merged into the current branch after fetching. In other words,
|
merged into the current branch after fetching. In other words,
|
||||||
if you list more than one remote refs, you would be making
|
if you list more than one remote ref, 'git pull' will create
|
||||||
an Octopus. While 'git pull' run without any explicit <refspec>
|
an Octopus merge. On the other hand, if you do not list any
|
||||||
parameter takes default <refspec>s from `Pull:` lines, it
|
explicit <refspec> parameter on the command line, 'git pull'
|
||||||
merges only the first <refspec> found into the current branch,
|
will fetch all the <refspec>s it finds in the
|
||||||
after fetching all the remote refs. This is because making an
|
`remote.<repository>.fetch` configuration and merge
|
||||||
|
only the first <refspec> found into the current branch.
|
||||||
|
This is because making an
|
||||||
Octopus from remote refs is rarely done, while keeping track
|
Octopus from remote refs is rarely done, while keeping track
|
||||||
of multiple remote heads in one-go by fetching more than one
|
of multiple remote heads in one-go by fetching more than one
|
||||||
is often useful.
|
is often useful.
|
||||||
+
|
|
||||||
Some short-cut notations are also supported.
|
|
||||||
+
|
|
||||||
* `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
|
|
||||||
it requests fetching everything up to the given tag.
|
|
||||||
ifndef::git-pull[]
|
|
||||||
* A parameter <ref> without a colon fetches that ref into FETCH_HEAD,
|
|
||||||
endif::git-pull[]
|
endif::git-pull[]
|
||||||
ifdef::git-pull[]
|
|
||||||
* A parameter <ref> without a colon merges <ref> into the current
|
|
||||||
branch,
|
|
||||||
endif::git-pull[]
|
|
||||||
and updates the remote-tracking branches (if any).
|
|
||||||
|
@ -45,6 +45,8 @@ static struct transport *gsecondary;
|
|||||||
static const char *submodule_prefix = "";
|
static const char *submodule_prefix = "";
|
||||||
static const char *recurse_submodules_default;
|
static const char *recurse_submodules_default;
|
||||||
static int shown_url = 0;
|
static int shown_url = 0;
|
||||||
|
static int refmap_alloc, refmap_nr;
|
||||||
|
static const char **refmap_array;
|
||||||
|
|
||||||
static int option_parse_recurse_submodules(const struct option *opt,
|
static int option_parse_recurse_submodules(const struct option *opt,
|
||||||
const char *arg, int unset)
|
const char *arg, int unset)
|
||||||
@ -69,6 +71,19 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
|
||||||
|
{
|
||||||
|
ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "git fetch --refmap='' origin foo"
|
||||||
|
* can be used to tell the command not to store anywhere
|
||||||
|
*/
|
||||||
|
if (*arg)
|
||||||
|
refmap_array[refmap_nr++] = arg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct option builtin_fetch_options[] = {
|
static struct option builtin_fetch_options[] = {
|
||||||
OPT__VERBOSITY(&verbosity),
|
OPT__VERBOSITY(&verbosity),
|
||||||
OPT_BOOL(0, "all", &all,
|
OPT_BOOL(0, "all", &all,
|
||||||
@ -107,6 +122,8 @@ static struct option builtin_fetch_options[] = {
|
|||||||
N_("default mode for recursion"), PARSE_OPT_HIDDEN },
|
N_("default mode for recursion"), PARSE_OPT_HIDDEN },
|
||||||
OPT_BOOL(0, "update-shallow", &update_shallow,
|
OPT_BOOL(0, "update-shallow", &update_shallow,
|
||||||
N_("accept refs that update .git/shallow")),
|
N_("accept refs that update .git/shallow")),
|
||||||
|
{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
|
||||||
|
N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -278,6 +295,9 @@ static struct ref *get_ref_map(struct transport *transport,
|
|||||||
const struct ref *remote_refs = transport_get_remote_refs(transport);
|
const struct ref *remote_refs = transport_get_remote_refs(transport);
|
||||||
|
|
||||||
if (refspec_count) {
|
if (refspec_count) {
|
||||||
|
struct refspec *fetch_refspec;
|
||||||
|
int fetch_refspec_nr;
|
||||||
|
|
||||||
for (i = 0; i < refspec_count; i++) {
|
for (i = 0; i < refspec_count; i++) {
|
||||||
get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
|
get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
|
||||||
if (refspecs[i].dst && refspecs[i].dst[0])
|
if (refspecs[i].dst && refspecs[i].dst[0])
|
||||||
@ -307,12 +327,21 @@ static struct ref *get_ref_map(struct transport *transport,
|
|||||||
* by ref_remove_duplicates() in favor of one of these
|
* by ref_remove_duplicates() in favor of one of these
|
||||||
* opportunistic entries with FETCH_HEAD_IGNORE.
|
* opportunistic entries with FETCH_HEAD_IGNORE.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
|
if (refmap_array) {
|
||||||
get_fetch_map(ref_map, &transport->remote->fetch[i],
|
fetch_refspec = parse_fetch_refspec(refmap_nr, refmap_array);
|
||||||
&oref_tail, 1);
|
fetch_refspec_nr = refmap_nr;
|
||||||
|
} else {
|
||||||
|
fetch_refspec = transport->remote->fetch;
|
||||||
|
fetch_refspec_nr = transport->remote->fetch_refspec_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < fetch_refspec_nr; i++)
|
||||||
|
get_fetch_map(ref_map, &fetch_refspec[i], &oref_tail, 1);
|
||||||
|
|
||||||
if (tags == TAGS_SET)
|
if (tags == TAGS_SET)
|
||||||
get_fetch_map(remote_refs, tag_refspec, &tail, 0);
|
get_fetch_map(remote_refs, tag_refspec, &tail, 0);
|
||||||
|
} else if (refmap_array) {
|
||||||
|
die("--refmap option is only meaningful with command-line refspec(s).");
|
||||||
} else {
|
} else {
|
||||||
/* Use the defaults */
|
/* Use the defaults */
|
||||||
struct remote *remote = transport->remote;
|
struct remote *remote = transport->remote;
|
||||||
|
@ -447,6 +447,43 @@ test_expect_success 'explicit pull should update tracking' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
|
||||||
|
cd "$D" &&
|
||||||
|
(
|
||||||
|
cd three &&
|
||||||
|
test_must_fail git fetch --refmap="*:refs/remotes/none/*"
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
|
||||||
|
cd "$D" &&
|
||||||
|
git branch -f side &&
|
||||||
|
(
|
||||||
|
cd three &&
|
||||||
|
git update-ref refs/remotes/origin/master base-origin-master &&
|
||||||
|
o=$(git rev-parse --verify refs/remotes/origin/master) &&
|
||||||
|
git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin master &&
|
||||||
|
n=$(git rev-parse --verify refs/remotes/origin/master) &&
|
||||||
|
test "$o" = "$n" &&
|
||||||
|
test_must_fail git rev-parse --verify refs/remotes/origin/side &&
|
||||||
|
git rev-parse --verify refs/remotes/other/master
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
|
||||||
|
cd "$D" &&
|
||||||
|
git branch -f side &&
|
||||||
|
(
|
||||||
|
cd three &&
|
||||||
|
git update-ref refs/remotes/origin/master base-origin-master &&
|
||||||
|
o=$(git rev-parse --verify refs/remotes/origin/master) &&
|
||||||
|
git fetch --refmap="" origin master &&
|
||||||
|
n=$(git rev-parse --verify refs/remotes/origin/master) &&
|
||||||
|
test "$o" = "$n" &&
|
||||||
|
test_must_fail git rev-parse --verify refs/remotes/origin/side
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'configured fetch updates tracking' '
|
test_expect_success 'configured fetch updates tracking' '
|
||||||
|
|
||||||
cd "$D" &&
|
cd "$D" &&
|
||||||
|
Loading…
Reference in New Issue
Block a user