From: Jeff King <peff@peff.net>
To: Avery Pennarun <apenwarr@gmail.com>
Cc: "Björn Steinbrink" <B.Steinbrink@gmx.de>,
"Tom Lambda" <tom.lambda@gmail.com>,
git@vger.kernel.org
Subject: Re: Question regarding git fetch
Date: Thu, 27 Aug 2009 17:34:26 -0400 [thread overview]
Message-ID: <20090827213426.GD4399@coredump.intra.peff.net> (raw)
In-Reply-To: <20090827204835.GC4399@coredump.intra.peff.net>
On Thu, Aug 27, 2009 at 04:48:35PM -0400, Jeff King wrote:
> And this matching is not really any different than what the fetch code
> does when applying the refspec to what the remote offers. So I don't
> think it should be any significant new code; it's just a matter of
> activating that matching and updating the local tracking refs based on
> what we actually fetched, instead of what the remote advertised.
Sure enough, here is a really simple proof of concept. This is the first
time I have really looked into the fetch code, so I hope I'm not totally
breaking something else. :)
Basically it works like this. Both "git fetch remote" and "git fetch
remote refspec" work by making a "ref map" via get_ref_map. This is a
list of refs, with some refs having a "peer ref" that points to the
local counterpart. Those without a peer are just stored in FETCH_HEAD.
The function works by starting with a list of possible remote refs, and
then applying the refspecs to it.
Calling fetch without explicit refspecs means we will create the map
using the configured refspecs. Calling with commandline refspecs means
we will use those. So what this patch does is to first apply the
commandline refspecs to narrow the list, and then apply the configured
refspecs on top of that to make a new list, and then concatenate the
lists.
So you will end up with "two" refs to fetch, which just happen to match
the same source. One will go to FETCH_HEAD, and one will go to the
tracking ref. I.e.:
$ git remote add origin ~/compile/git
$ git fetch origin next
From /home/peff/compile/git
* branch next -> FETCH_HEAD
* [new branch] next -> origin/next
And it should work the same if you supply a more interesting refspec,
too:
$ git fetch -v origin next:foo
From /home/peff/compile/git
* [new branch] next -> foo
= [up to date] next -> origin/next
or even a wildcard:
$ git fetch -v origin refs/heads/*:refs/foo/*
From /home/peff/compile/git
* [new branch] master -> refs/foo/master
* [new branch] next -> refs/foo/next
* [new branch] master -> origin/master
= [up to date] next -> origin/next
I haven't thought long enough to be convinced there aren't any bad side
effects, though. I guess if you had non-traditional configured refspecs,
you might be surprised to see them applied in this case. Something like:
# we usually fetch the remote's master straight into our production
# branch for deployment
$ git config remote.origin.fetch refs/heads/master:refs/heads/production
# but today let's demo it first
$ git fetch origin master:demo
I don't know if people are actually using refspecs in that way. But we
do need to consider that this is a potentially destructive change.
Anyway, here is the patch.
---
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 817dd6b..d9e44c7 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -119,6 +119,9 @@ static struct ref *get_ref_map(struct transport *transport,
const struct ref *remote_refs = transport_get_remote_refs(transport);
if (ref_count || tags == TAGS_SET) {
+ struct ref *tracking_refs = NULL;
+ struct ref **tracking_tail = &tracking_refs;
+
for (i = 0; i < ref_count; i++) {
get_fetch_map(remote_refs, &refs[i], &tail, 0);
if (refs[i].dst && refs[i].dst[0])
@@ -129,6 +132,12 @@ static struct ref *get_ref_map(struct transport *transport,
rm->merge = 1;
if (tags == TAGS_SET)
get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+
+ for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
+ get_fetch_map(ref_map, &transport->remote->fetch[i],
+ &tracking_tail, 0);
+ *tail = tracking_refs;
+ tail = tracking_tail;
} else {
/* Use the defaults */
struct remote *remote = transport->remote;
next prev parent reply other threads:[~2009-08-27 21:34 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-27 15:30 Question regarding git fetch Tom Lambda
2009-08-27 15:36 ` Avery Pennarun
2009-08-27 16:21 ` Eric Raible
2009-08-27 16:28 ` Avery Pennarun
2009-08-27 16:46 ` Björn Steinbrink
2009-08-27 17:22 ` Avery Pennarun
2009-08-27 20:48 ` Jeff King
2009-08-27 21:34 ` Jeff King [this message]
2009-08-27 21:44 ` Junio C Hamano
2009-08-27 21:50 ` Jeff King
2009-08-27 21:53 ` Jeff King
2009-08-27 22:12 ` Avery Pennarun
2009-08-27 22:16 ` Jeff King
2009-08-27 22:24 ` Avery Pennarun
2009-08-27 21:20 ` Junio C Hamano
2009-08-27 21:39 ` Jeff King
2009-08-28 13:24 ` Tom Lambda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090827213426.GD4399@coredump.intra.peff.net \
--to=peff@peff.net \
--cc=B.Steinbrink@gmx.de \
--cc=apenwarr@gmail.com \
--cc=git@vger.kernel.org \
--cc=tom.lambda@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).