On Thu, May 11, 2017 at 04:23:03PM -0500, Robert Dailey wrote:
> On Thu, May 11, 2017 at 3:17 PM, Jeff King <[email protected]> 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 <start-point> 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. I spend quite a lot of time at the end of a
series sifting through the commits via "rebase -i" and polishing them
up. I also test with "git rebase -x 'make test'".
-Peff