Re: Best "triangle" workflow setup?

2017-05-13 Thread Jeff King
On Fri, May 12, 2017 at 09:53:23AM -0500, Robert Dailey wrote:

> Thanks, just curious, where in the git documentation is the "origin"
> to "origin/HEAD" resolution documented? I checked the git-revisions
> page but it doesn't seem to mention it there. Thanks for explaining
> though.

In gitrevisions(7), the  section, rule 6:

  otherwise, refs/remotes//HEAD if it exists.

And then the contents of origin/HEAD are discussed a bit in
git-remote(1), under set-head.

> Also is there a similar mechanism for "track same-named branch on
> specified remote"? Something like "origin/."? I follow git-flow
> development process, so topic branches on hotfix or release branches
> will track origin/master (since origin/HEAD still points to master or
> develop). But I want to track "origin/release/1.2.3" without typing
> the full thing. Basically would be nice if there was a lazy shorthand
> for it similar to the "origin/HEAD" example you gave.

No, I don't think there's a shorthand for "the same-named branch". But
there are two things that might help:

  1. If you're always branching from release/1.2.3 instead of "master",
 you can use "git remote set-head" to change it.

  2. If you want a local branch "foo" to track refs/remotes/origin/foo
 (which already exists) then the checkout-dwim should work for you:

$ git checkout foo
Branch foo set up to track remote branch foo from origin.
Switched to a new branch 'foo'

-Peff


Re: Best "triangle" workflow setup?

2017-05-12 Thread Robert Dailey
On Thu, May 11, 2017 at 6:36 PM, Jeff King  wrote:
> On Thu, May 11, 2017 at 04:23:03PM -0500, Robert Dailey wrote:
>
>> On Thu, May 11, 2017 at 3:17 PM, Jeff King  wrote:
>> > I think you want:
>> >
>> >   [push]
>> >   default = current
>> >   [remote]
>> >   pushDefault = myfork
>> >
>> > to make "git push" do what you want. And then generally have branches
>> > mark their counterparts on "origin" (which you can do either at creation
>> > time, or probably by using "git push -u origin my-topic" when you push
>> > them).
>>
>> So without the `pushDefault` setting, `current` will default to a
>> remote named `origin` if there is no tracking branch set, correct? So
>> `pushDefault` is effectively overriding this built-in default? In
>> addition, it seems like since this overrides `branch.name.remote`,
>> that this effectively makes the remote tracking branch *only* for
>> `pull`. Is this a correct understanding?
>
> Right. The general idea of a triangular workflow is that where you pull
> from is not the same as where you push to. We have branch.*.pushremote
> if you really wanted to do it on a per-branch basis, but in my
> experience you almost always want to use "myfork", because you can't
> push to "origin" in the first place. :)
>
>> > This is similar to what I do for my git.git workflow, though I usually
>> > have origin/master as the branch's upstream. I.e., I'd create them with:
>> >
>> >   git checkout -b my-topic origin
>>
>> I'm looking through the `git checkout` and `git branch` documentation,
>> but I don't see any mention of it being valid to use a remote name as
>> the  parameter (you're using `origin` in the above
>> example). Am I misunderstanding? Did you mean origin/my-topic?
>
> Using "origin" there will resolve to "origin/HEAD", i.e., origin/master.
> So basically I am saying that all of my topic branches are based on
> master, and if I were to rebase them (for example), I'd want to rebase
> the whole thing.
>
> If I were to "git pull", they'd also pull from master, which may or may
> not be what you want (though with pull.rebase, perhaps). I don't
> generally use "git pull" at all for my git.git workflow.

Thanks, just curious, where in the git documentation is the "origin"
to "origin/HEAD" resolution documented? I checked the git-revisions
page but it doesn't seem to mention it there. Thanks for explaining
though.

Also is there a similar mechanism for "track same-named branch on
specified remote"? Something like "origin/."? I follow git-flow
development process, so topic branches on hotfix or release branches
will track origin/master (since origin/HEAD still points to master or
develop). But I want to track "origin/release/1.2.3" without typing
the full thing. Basically would be nice if there was a lazy shorthand
for it similar to the "origin/HEAD" example you gave.


>> > And then rebasing always happens on top of master (because "origin"
>> > doesn't even have my topic branch at all). If I want to compare with
>> > what I've pushed to my fork, I'd use "@{push}".
>>
>> Can you explain more about how your rebase chooses master instead of
>> your same-named remote tracking branch? Maybe provide some examples of
>> your rebase command and respective configuration (unless what you've
>> already provided is sufficient). As for @{push}, I haven't used this
>> before, so I'll dig in the docs and learn about it.
>
> The default for "git rebase" (if you don't specify a base) is the
> configured upstream, which in my case is origin/master. Most of my
> rebasing is "rebase -i" to rewrite bits, so it automatically picks all
> the commits on my topic branch.
>
> Maybe it would help to set up a trivial example:
>
>   # just a helper to make dummy commits
>   commit() { echo "$1" >"$1" && git add "$1" && git commit -m "$1"; }
>
>   # some parent repo
>   git init parent
>   (cd parent && commit one)
>
>   # and imagine you have a public fork, too
>   git clone --bare parent myfork.git
>
>   # and then you have your local clone; in real life this is obviously
>   # the only one that would actually be on your machine, but this is a
>   # toy example
>   git clone parent local
>   cd local
>
>   # set up our triangular config
>   git remote add myfork ../myfork.git
>   git config remote.pushdefault myfork
>   git config push.default current
>
>   # now let's try a topic branch
>   git checkout -b topic origin
>   commit two
>   commit three
>
>   # config will show our topic based on origin/master:
>   #  [branch "topic"]
>   # remote = origin
>   # merge = refs/heads/master
>   less .git/config
>
>   # this should default to all the commits in our topic (i.e., two, three)
>   git rebase -i
>
>   # let's imagine upstream makes more commits on master. We can "pull
>   # --rebase" to put our work on top
>   (cd ../parent && commit four)
>   git pull --rebase
>
>   # pushes go to the matching branch on myfork
>   git push
>
>   # if you want to see what you haven't 

Re: Best "triangle" workflow setup?

2017-05-11 Thread Jeff King
On Thu, May 11, 2017 at 04:23:03PM -0500, Robert Dailey wrote:

> On Thu, May 11, 2017 at 3:17 PM, Jeff King  wrote:
> > I think you want:
> >
> >   [push]
> >   default = current
> >   [remote]
> >   pushDefault = myfork
> >
> > to make "git push" do what you want. And then generally have branches
> > mark their counterparts on "origin" (which you can do either at creation
> > time, or probably by using "git push -u origin my-topic" when you push
> > them).
> 
> So without the `pushDefault` setting, `current` will default to a
> remote named `origin` if there is no tracking branch set, correct? So
> `pushDefault` is effectively overriding this built-in default? In
> addition, it seems like since this overrides `branch.name.remote`,
> that this effectively makes the remote tracking branch *only* for
> `pull`. Is this a correct understanding?

Right. The general idea of a triangular workflow is that where you pull
from is not the same as where you push to. We have branch.*.pushremote
if you really wanted to do it on a per-branch basis, but in my
experience you almost always want to use "myfork", because you can't
push to "origin" in the first place. :)

> > This is similar to what I do for my git.git workflow, though I usually
> > have origin/master as the branch's upstream. I.e., I'd create them with:
> >
> >   git checkout -b my-topic origin
> 
> I'm looking through the `git checkout` and `git branch` documentation,
> but I don't see any mention of it being valid to use a remote name as
> the  parameter (you're using `origin` in the above
> example). Am I misunderstanding? Did you mean origin/my-topic?

Using "origin" there will resolve to "origin/HEAD", i.e., origin/master.
So basically I am saying that all of my topic branches are based on
master, and if I were to rebase them (for example), I'd want to rebase
the whole thing.

If I were to "git pull", they'd also pull from master, which may or may
not be what you want (though with pull.rebase, perhaps). I don't
generally use "git pull" at all for my git.git workflow.

> > And then rebasing always happens on top of master (because "origin"
> > doesn't even have my topic branch at all). If I want to compare with
> > what I've pushed to my fork, I'd use "@{push}".
> 
> Can you explain more about how your rebase chooses master instead of
> your same-named remote tracking branch? Maybe provide some examples of
> your rebase command and respective configuration (unless what you've
> already provided is sufficient). As for @{push}, I haven't used this
> before, so I'll dig in the docs and learn about it.

The default for "git rebase" (if you don't specify a base) is the
configured upstream, which in my case is origin/master. Most of my
rebasing is "rebase -i" to rewrite bits, so it automatically picks all
the commits on my topic branch.

Maybe it would help to set up a trivial example:

  # just a helper to make dummy commits
  commit() { echo "$1" >"$1" && git add "$1" && git commit -m "$1"; }

  # some parent repo
  git init parent
  (cd parent && commit one)

  # and imagine you have a public fork, too
  git clone --bare parent myfork.git

  # and then you have your local clone; in real life this is obviously
  # the only one that would actually be on your machine, but this is a
  # toy example
  git clone parent local
  cd local

  # set up our triangular config
  git remote add myfork ../myfork.git
  git config remote.pushdefault myfork
  git config push.default current

  # now let's try a topic branch
  git checkout -b topic origin
  commit two
  commit three

  # config will show our topic based on origin/master:
  #  [branch "topic"]
  # remote = origin
  # merge = refs/heads/master
  less .git/config

  # this should default to all the commits in our topic (i.e., two, three)
  git rebase -i

  # let's imagine upstream makes more commits on master. We can "pull
  # --rebase" to put our work on top
  (cd ../parent && commit four)
  git pull --rebase

  # pushes go to the matching branch on myfork
  git push

  # if you want to see what you haven't pushed yet, you can use @{push}
  commit five
  git log @{push}..

  # likewise, if you wanted to rebase only commits that you've been
  # working on since your last push:
  git rebase -i @{push}

  # Now imagine "origin" picks up your branch...
  (cd ../parent && git fetch ../myfork.git topic:topic)

  # Depending on your project's workflow, you may want to consider that
  # the new base for further development (and never rebase or rewrite
  # any commits that origin has). You do that by re-pointing your
  # @{upstream} config.
  git fetch
  git branch --set-upstream-to=origin/topic topic

  # now a "rebase -i" would show only the commits origin doesn't have
  # (five and six in this case)
  commit six
  git rebase -i


Hopefully that shows off some of the ways you can use the upstream and
push config in practice.  Some people may not be as excited about the
"rebase" default as I am. 

Re: Best "triangle" workflow setup?

2017-05-11 Thread Robert Dailey
On Thu, May 11, 2017 at 3:17 PM, Jeff King  wrote:
> I think you want:
>
>   [push]
>   default = current
>   [remote]
>   pushDefault = myfork
>
> to make "git push" do what you want. And then generally have branches
> mark their counterparts on "origin" (which you can do either at creation
> time, or probably by using "git push -u origin my-topic" when you push
> them).

So without the `pushDefault` setting, `current` will default to a
remote named `origin` if there is no tracking branch set, correct? So
`pushDefault` is effectively overriding this built-in default? In
addition, it seems like since this overrides `branch.name.remote`,
that this effectively makes the remote tracking branch *only* for
`pull`. Is this a correct understanding?

> This is similar to what I do for my git.git workflow, though I usually
> have origin/master as the branch's upstream. I.e., I'd create them with:
>
>   git checkout -b my-topic origin

I'm looking through the `git checkout` and `git branch` documentation,
but I don't see any mention of it being valid to use a remote name as
the  parameter (you're using `origin` in the above
example). Am I misunderstanding? Did you mean origin/my-topic?

> And then rebasing always happens on top of master (because "origin"
> doesn't even have my topic branch at all). If I want to compare with
> what I've pushed to my fork, I'd use "@{push}".

Can you explain more about how your rebase chooses master instead of
your same-named remote tracking branch? Maybe provide some examples of
your rebase command and respective configuration (unless what you've
already provided is sufficient). As for @{push}, I haven't used this
before, so I'll dig in the docs and learn about it.

Thanks for your advice, so far I like this direction but seems like
there is more for me to learn!


Re: Best "triangle" workflow setup?

2017-05-11 Thread Jeff King
On Thu, May 11, 2017 at 02:41:41PM -0500, Robert Dailey wrote:

> What I want (as a default) is for `git pull` to pull from the
> same-named branch on the upstream repository, but for `git push` to
> push to the same-named branch on the fork repository. However to
> override this behavior for when I want to push directly to upstream
> repo, I should be able to use an explicit `git push origin my-topic`
> (but `git push` by default will act as `git push fork my-topic`).

I think you want:

  [push]
  default = current
  [remote]
  pushDefault = myfork

to make "git push" do what you want. And then generally have branches
mark their counterparts on "origin" (which you can do either at creation
time, or probably by using "git push -u origin my-topic" when you push
them).

This is similar to what I do for my git.git workflow, though I usually
have origin/master as the branch's upstream. I.e., I'd create them with:

  git checkout -b my-topic origin

And then rebasing always happens on top of master (because "origin"
doesn't even have my topic branch at all). If I want to compare with
what I've pushed to my fork, I'd use "@{push}".

-Peff