Re: [question] how can i verify whether a local branch is tracking a remote branch?
- From
Michael J Gruber <git@drmicha.warpmail.net>
- Date
- Apr 6, 2009, 12:00 UTC
- Message-ID
- <49D9EEE2.3000607@drmicha.warpmail.net>
- In-Reply-To
- <20090406043426.GC12341@coredump.intra.peff.net>
Jeff King venit, vidit, dixit 06.04.2009 06:34:
Show 89 quoted lines
> On Sun, Apr 05, 2009 at 11:25:29PM +0200, Paolo Ciarrocchi wrote:
>
>> An example:
>> $ git clone -n URL temp
>> $ cd temp
>> $ git branch -r
>> origin/master
>> origin/foo
>> Origin/bar
>> $ git checkout --track -b foo origin/foo
>>
>> Now, how can I know that foo is tracking origin/foo ?
>
> Doing it right is hard. You have to:
>
> 1. check branch.foo.merge and branch.foo.rebase; if no value, it is not
> tracking anything; if it is, remember that value as $m
>
> 2. check branch.foo.remote for the remote name, $r
>
> 3. check the fetch refspecs for remote $r; these can come from
> the config, or from .git/remotes/* files. Maybe even .git/branches
> files; I don't even remember how those work.
>
> 4. find the refspec that fetches from $m; then find the matching
> destination for that refspec. That is the tracking branch.
>
> E.g., in your example (and using a modern git):
>
> 1. $m is refs/heads/foo
> 2. $r is origin
> 3. The fetch refspec is in remote.origin.fetch, and is generally
> "refs/heads/*:refs/remotes/origin/*"
> 4. So refs/heads/foo becomes refs/remotes/origin/foo.
> refs/remotes/origin/foo is your tracking branch.
>
> Steps 1 and 2 are easy, but 3 and 4 are a bit nasty. You can fake it by
> assuming that "refs/heads/$m" on "$r" is always "refs/remotes/$r/$m",
> which is true for very vanilla setups.
>
> There is C code that does this, but there is not a good way of accessing
> it from the command-line. The best you can do is "git remote show
> origin", which on recent git versions should show something like:
>
> ...
> Local branches configured for 'git pull':
> foo merges with remote foo
> ...
>
> But of course that implies that you already guessed the remote "origin".
> And it's not using plumbing, so it's not very suitable for scripts.
>
> I don't think it would be unreasonable to expose this functionality via
> "for-each-ref". Something like this (which would need cleanup,
> documentation, and perhaps a :short variant):
>
> ---
> diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
> index 5cbb4b0..3f418e4 100644
> --- a/builtin-for-each-ref.c
> +++ b/builtin-for-each-ref.c
> @@ -8,6 +8,7 @@
> #include "blob.h"
> #include "quote.h"
> #include "parse-options.h"
> +#include "remote.h"
>
> /* Quoting styles */
> #define QUOTE_NONE 0
> @@ -66,6 +67,7 @@ static struct {
> { "subject" },
> { "body" },
> { "contents" },
> + { "tracking" },
> };
>
> /*
> @@ -699,6 +701,18 @@ static void populate_value(struct refinfo *ref)
> v->s = s;
> }
> }
> + if (!strcmp(name, "tracking")) {
> + struct branch *branch;
> + if (prefixcmp(ref->refname, "refs/heads/"))
> + continue;
> + branch = branch_get(ref->refname + 11);
> + if (branch && branch->merge && branch->merge[0] &&
> + branch->merge[0]->dst)
> + v->s = branch->merge[0]->dst;Isn't that missing out on those cases where you --track (i.e. follow) a local (upstream) branch? See 5e6e2b4 (Make local branches behave like remote branches when --tracked, 2009-04-01)
Show 12 quoted lines
> + else > + v->s = NULL; > + free(branch); /* XXX should also free other parts? */ > + } > } > > grab_values(ref->value, 0, obj, buf, size); > > > > >
If we hook it up into git-branch there would be to useful directions:
- "git branch --follows foo" could list all branches which follow foo, analogous to --contains. It gives you all your feature work on top of foo, all branches affected by rebasing foo etc.
- "git branch --whatever foo" could list the branch whoch foo follows.
I just notices that "git branch -v foo" does not give me the "-v" output for foo... Improving that would open up the possibility to go for -vv foo.
Michael