[RFC PATCH] proposal for refs/tracking/* hierarchy

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

 



From: Jacob Keller <jacob.keller@xxxxxxxxx>

Historically, git has tracked the status of remote branches (heads) in
refs/remotes/<name>/*. This is necessary and useful as it allows users
to track the difference between their local work and the last known
status of the remote work.

Unfortunately this hierarchy is limited in that it only tracks branches.
Additionally, it is not feasible to extend it directly, because the
layout would become ambiguous. For example, if a user happened to have
a local branch named "notes" it could be confusing if you tried to add
"refs/remotes/origin/notes/<remote notes refs" as this would collide
with the already existing refs/remotes/origin/notes branch that existed.

Instead, lets add support for a new refs/tracking/* hierarchy which is
laid out in such a way to avoid this inconsistency. All refs in
"refs/tracking/<remote>/*" will include the complete ref, such that
dropping the "tracking/<remote>" part will give the exact ref name as it
is found in the upstream. Thus, we can track any ref here by simply
fetching it into refs/tracking/<remote>/*.

Add support to tell a new remote to start tracking remote hierarchies
via "--follow" which will track all refs under that section, ie:

git remote add --follow notes origin <url> will cause

+refs/notes/*:refs/tracking/origin/notes/* to be added as a fetch
refspec for this remote.

This ensures that any future refs which want a method of sharing the
current remote status separate from local status could use
refs/tracking

A long term goal might be to deprecate refs/remotes/ in favor of
refs/tracking (possibly adding in magic to convert refs/remotes directly
into refs/tracking so that old stuff still works?).

Things not yet thought through:

1) maybe we should create a configurable default so that some known set
   of default refs get pulled (ie: notes, grafts, replace, etc?)
   Possibly with some sort of easy way to add or subtract from the list
   in config...

2) so far, there's no work done to figure out how to remove
   refs/tracking when a remote is dropped. I *think* we can just delete
   all refs under refs/tracking/<name> but I'm not completely certain

3) adding magic to complete refs under tracking, such as for git-notes
   or similar may wish to understand shorthand for referencing the
   remote version of notes

4) adding support for clone.. (this is weird because git-clone and
   git-remote don't both use the same flow for setup.. oops??)

5) tests, documentation etc. (This is primarily an RFC, with the goal of
   providing a known location for remote references such as notes to
   reside)

6) we probably want to enable notes and grafts and other similar things
   to use the remote tracking data if its available.

7) what about tags? Currently we fetch all tags into refs/tags directly,
   which is a bit awkward, if for example you create a local tag and
   a remote creates a tag with the same name, you simply don't get that
   new version. This is good, but now you have no idea how to tell if
   your tags are out of date or not. refs/tracking can partially resolve
   this since remote tags will always be "exactly" what the remote has.
   Unfortunately, I don't know how we'd resolve them into local tags...

Probably other things missing too...

Signed-off-by: Jacob Keller <jacob.keller@xxxxxxxxx>
---
 builtin/remote.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/builtin/remote.c b/builtin/remote.c
index f1a88fe26589..dffe3892be11 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -122,6 +122,16 @@ static void add_branch(const char *key, const char *branchname,
 	git_config_set_multivar(key, tmp->buf, "^$", 0);
 }
 
+static void add_tracking(const char *key, const char *namespace,
+			 const char *remotename, struct strbuf *tmp)
+{
+	strbuf_reset(tmp);
+	strbuf_addch(tmp, '+');
+	strbuf_addf(tmp, "refs/%s/*:refs/tracking/%s/%s/*",
+		    namespace, remotename, namespace);
+	git_config_set_multivar(key, tmp->buf, "^$", 0);
+}
+
 static const char mirror_advice[] =
 N_("--mirror is dangerous and deprecated; please\n"
    "\t use --mirror=fetch or --mirror=push instead");
@@ -149,6 +159,7 @@ static int add(int argc, const char **argv)
 	int fetch = 0, fetch_tags = TAGS_DEFAULT;
 	unsigned mirror = MIRROR_NONE;
 	struct string_list track = STRING_LIST_INIT_NODUP;
+	struct string_list follow = STRING_LIST_INIT_NODUP;
 	const char *master = NULL;
 	struct remote *remote;
 	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
@@ -164,6 +175,8 @@ static int add(int argc, const char **argv)
 			    N_("or do not fetch any tag at all (--no-tags)"), TAGS_UNSET),
 		OPT_STRING_LIST('t', "track", &track, N_("branch"),
 				N_("branch(es) to track")),
+		OPT_STRING_LIST(0, "follow", &follow, N_("namespace"),
+				N_("refs namespaces to follow in refs/tracking")),
 		OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")),
 		{ OPTION_CALLBACK, 0, "mirror", &mirror, N_("push|fetch"),
 			N_("set up remote as a mirror to push to or fetch from"),
@@ -207,6 +220,11 @@ static int add(int argc, const char **argv)
 		}
 	}
 
+	for (i = 0; i < follow.nr; i++) {
+		add_tracking(buf.buf, follow.items[i].string,
+			     name, &buf2);
+	}
+
 	if (mirror & MIRROR_PUSH) {
 		strbuf_reset(&buf);
 		strbuf_addf(&buf, "remote.%s.mirror", name);
-- 
2.13.0.615.gb09ed6e59a40




[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]

  Powered by Linux