Ramkumar Ramachandra <artag...@gmail.com> writes:

> Junio C Hamano wrote:
>>>> rev-parse (with an option, maybe) may be a better place for
>>>> this.
>>> Er, no.  I actually want things like diff @{p}..HEAD.  I want it to be
>>> a first-class revision, just like @{u}.
>> I think Duy's suggestion makes perfect sense; rev-parse already has
>> a mechanism to expand @{u} to the full name, so if you are hooking
>> into the same codepath as @{u} to implement the "I publish there"
>> information, which I think you should, you already should have it
>> for free.
> *scratches head*
> Okay, I'm not understanding this.
> ...  How do I get "I publish
> there" information for free?

That is not what I said.

Let's step back a bit and think what it means that @{u} can be used
to name "The latest, as best of my knowledge, of the possibly moving
ref that my work is based on".  You can do so by

 (1) having a ref that points at such commit and having a mechanism
     to keep the ref up to date;

 (2) having a mechansim to turn @{u} to such a ref; and

 (3) letting get_sha1() machinery to read from that ref when an
     object name is needed for @{u}.

None of the above is what rev-parse does, but because you have (2),
rev-parse --symbolic-full-name can just ask (2) for a refname.

That is what I meant by "for free", and "which I think you should"
refers to all of these three things you would do to keep track of
"The latest, as best of my knowledge, of the possibly moving ref
that points at the commit I pushed the last time" for your @{p} in a
way similar to how @{u} works.

If I understand correctly the discussion so far, for a given branch
B, "git push" (no arguments to specify to which repository to push
nor what branch to update) would decide what the user did not say by
looking at:

    - branch.B.pushremote (and using remote.pushdefault and
      branch.B.remote as fallbacks) to find what repository R to
      push to;

    - branch.B.push (or mapping B through remote.R.push refspecs as
      a fallback logic) to find what destination branch D at R is
      updated by B.

Then after "git push" succeeds, it would look at remote.R.fetch
refspecs to pretend as if we fetched immediately from R, which is
how we keep track of the "last pushed" state, which is (1) of the
necessary three.

It follows that for B@{p} to be "The last pushed" for B, it has to
resolve to a remote tracking branch for D from R.  That (i.e. find R
and D and then map it through R's fetch refspec) is the logic we
need for (2).  That is very similar for B@{u}, which should be to
find the repository O it comes from by looking at branch.B.remote
(or 'origin'), and then where branch.B.merge from O is stored in our
ref namespace (e.g. refs/remotes/origin/topic) by mapping it through
the remote.O.fetch refspec.

Once you have (2), the implementation of (3) is quite obvious.  We
know where in the codeflow @{u} is turned into a ref; we can do the
same for @{p} by calling the logic (2) from the same place to turn
@{p} into a ref.

It is worth noting that @{p} has one error case that @{u} does not,
whose only error case is essentially that the branch you are asking
for @{u} does not have "upstream" configured.

For "git push" to work, you only need to be able to compute R and D
for B.  But R does not necessarily need to have fetch refspec for a
triangular pushing to work, hence we may not be recording what we
pushed the last time, violating (1), which in turn means (2) may not
have an answer.

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to