Re: Question regarding git fetch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]