Re: push.default???

3 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: push.default???

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:59

Paolo Bonzini [off-list ref] writes:
quoted
If a group sets up a shared public branch, it is typically for
working together on some feature.

For people used to CVS, this is a nice way to start working with git.
It requires --tracking to work properly though (--current only works
if you remember to use the same branch name).
Ok, this *is* a usecase.  Your local branch is named as a feature but
it pushes into master.  Thanks, I have something to reason about now.
:-)
I actually have been having a hard time imagining how such a set-up makes
sense, even during your absense (i.e. the timeframe we did push.default).

You are forking off of shared 'master', but you are developing a feature
on a separate branch 'feature'.

That is a sane thing to do for two reasons.  (1) Until 'feature' is done
to your own satisfaction, you do not want to contaminate your own 'master'
with the half-cooked feature development in it. (2) While you are working
on 'feature', you may want to update your own 'master' from the shared
repository to monitor how others are doing.  Having a separate, pristine
'master' branch allows you to do so more easily, than detaching HEAD at
'origin/master' every once in a while.

However, when 'feature' is fully cooked, before pushing it back to be
shared with others in the group, don't you do any testing with the work
done by others while you were working on 'feature'?  That means you first
integrate your 'feature' locally into shared 'master' and make sure all
fits together well.

Until you do that, you cannot be confident that the feature you developed
is fit for public consumption.  But if you test after merging 'feature'
into 'master', what you determined as good is in 'master', which you can
push back to the remote's 'master'.

One glitch I can think of is what would happen if you do not want to merge
your feature for final testing to master, but instead rebase your feature
on top of master (let's not discuss why you should or should not rebase at
this point; some projects seem to insist you rebase and there may be no
good technical reason but that is not the topic here).  There currently is
no easy UI other than:

	$ git checkout master
        $ git pull --rebase . feature
	$ test test test
	$ git push origin master

or even worse:

	$ git checkout feature
        $ git rebase master
        $ git checkout master
        $ git merge feature
	$ test test test
	$ git push origin master

to tell git to integrate your local work done in 'feature' to 'master' by
rebasing, instead of merging.  If you do a merge, that is quite
straightforward:

	$ git checkout master
        $ git merge feature
	$ test test test
	$ git push origin master

but instead you have to do something like:

	$ git checkout feature
        $ git rebase master
        $ test test test
        $ git push origin feature:master

and you end up needing "put my 'feature' into their 'master'".

Could it be possible that this desire to push "tracking" is not a cure for
anything real, but merely a kludge to work around a misfeature of "rebase"
UI that does not allow "integrate that branch here but do not merge it but
by first rebasing it"?  In other words, if we had "git merge --rebase" (I
know, I know, it is a terrible name.  The word "merge" in this context
means "to integrate"), the above can be done more naturally:

	$ git checkout master
        $ git merge --rebase feature
	$ test test test
	$ git push origin master

and the matching push (or "git push origin HEAD") becomes the right thing
to do, eliminating the need for "put my 'feature' into their 'master'".

For a group that sets up a shared public branch to be used for working
together on some feature, replace 'master' with 'some feature' above, and
'feature' with 'your part of the work on the feature'; the story is the
same.

Re: push.default???

From: Paolo Bonzini <hidden>
Date: 2016-06-15 22:46:59

You are forking off of shared 'master', but you are developing a feature
on a separate branch 'feature'.

However, when 'feature' is fully cooked, before pushing it back to be
shared with others in the group, don't you do any testing with the work
done by others while you were working on 'feature'?  That means you first
integrate your 'feature' locally into shared 'master' and make sure all
fits together well.

Until you do that, you cannot be confident that the feature you developed
is fit for public consumption.  But if you test after merging 'feature'
into 'master', what you determined as good is in 'master', which you can
push back to the remote's 'master'.
Here is what I think you are missing: in the proposed workflow, there is 
an entire group working on one big feature, so there is effectively one 
remote per feature.

In fact, what was not clear to me before Finn explained it is the way 
these remotes are configured and mapped to local branches.  In his 
setup, your own master branch is tracking integration/master, but your 
feature branch is tracking feature/master.  You're effectively using a 
centralized repository but splitting it across several remotes, 
presumably for two reasons: 1) access control, 2) so that people can 
choose which parts of the repository to mirror.

Mind that this is quite a mangled DVCS workflow :-) since you're 
distributing the centralized repository (!), so you're not using topic 
branches and you're not committing very often; if you were using topic 
branches you would have to use --no-track or risk pushing by mistake to 
feature/master.  You just map "svn update" to "git pull --rebase" and 
"svn commit" to "git commit + git push".

So, every time you finish some aspect of 'feature', you rebase it on top 
of the tracked branch feature/master to test it with the work done by 
others, and then push.  The rebasing is taken care of by "git pull", so 
it makes sense in this case that pushing to feature/master is done with 
plain "git push".
Could it be possible that this desire to push "tracking" is not a cure for
anything real, but merely a kludge to work around a misfeature of "rebase"
UI that does not allow "integrate that branch here but do not merge it but
by first rebasing it"?  In other words, if we had "git merge --rebase feature"
[to merge rebased feature into master, then "git push origin HEAD"] becomes the
 > right thing to do, eliminating the need for "put my 'feature' into 
their 'master'".
 >
For a group that sets up a shared public branch to be used for working
together on some feature, replace 'master' with 'some feature' above, and
'feature' with 'your part of the work on the feature'; the story is the
same.
I think this makes sense, but it is not what Finn was going after.  In 
his setup, there is no 'your part of the work on the feature', 
everything is done in a single branch.


Now, here is a plan to realize the same workflow with a different 
implementation.

1) introduce a new configuration key branch.autosetuppush that 
automatically adds a remote.*.push entry whenever a tracking branch is 
created.

I think this is also the right time to introduce per-remote autosetup 
keys remote.*.autosetup{merge,rebase,push}.  In fact I would introduce 
these per-remote configurations before, as a kind of "step 0".

2) introduce git push --current (or maybe --head-only) that uses 
whatever refspec "git push" uses, but always restrict pushing to the 
current branch.  This would only apply to "git push" without explicit 
refspecs.

3) introduce remote.*.pushHeadOnly to make "git push" always behave like 
"git push --current".

Note that the new command line option is not really needed, but it would 
make testing harder if --current behavior could be specified only with 
configuration keys.

4) introduce a --push option for "git remote add".  Every push.default 
configuration, thanks to steps 1 and 3, now maps to a simple configuration:

  --push=current -> remote.*.push = HEAD
  --push=tracking -> remote.*.autosetuppush=remote.*.pushHeadOnly=true
  --push=matching -> remote.*.push = :

In addition, --push=mirror could be implemented to do the same as --mirror.


I have a rough draft of all but the last step already implemented (I 
have not even compiled, but I wanted to measure roughly the complexity 
of the features; unless I screwed up big, it seems like a "calm" patch 
series).  I like this way more than the "magic refspec".  Unlike 
push.default, it builds entirely on the concept of refspecs.  But unlike 
the magic refspec, it fits with the rest of --track better, and it just 
uses two easily understood knobs to achieve its objective.

Paolo

Re: push.default???

From: Finn Arne Gangstad <hidden>
Date: 2016-06-15 22:46:59

On Wed, Jun 24, 2009 at 10:50:00AM +0200, Paolo Bonzini wrote:
Here is what I think you are missing: in the proposed workflow, there is  
an entire group working on one big feature, so there is effectively one  
remote per feature.
I think you are making this more complicated than it is. I just claim
that the idea that "branch names must be identical in both ends" is
not necessarily the best model.

In a sufficiently large origanisation with multiple levels of
repositories (access restrictions, locality, whatever) branch names
are not globally unique, and there is no reasonable way to check if a
branch name is used elsewhere. It is much easier to treat local branch
names as strictly local, and worry about naming (only) when you push
somewhere.

So - even if someone decided to name something "issue-331318" on a
public repository, it doesn't mean you want to call it that locally,
even if you want to push to it.

If a branch already exists on a public repo, it doesn't mean a branch
with the same name but with different contents/purpose cannot exist in
a different repo. So you may have to name the branch something else
locally. Pull knows how to deal with this, but push did not (before
"--tracking").

Another example:

You have worked for a few days on an issue, but need help from someone
else with something. You have set up a public shared repo named
"public", and do:

git push public HEAD:fred-helpme

Fred wants to name it something else that makes him remember what this
branch is about, and does:

git fetch public
git checkout -b tmp-help-john public/fred-helpme
<hack hack>
git commit
git push   (no more arguments, and no need to remember what it was named)

You then fetch and look at what Fred has done, and maybe you just use
it, or maybe you don't. Afterwards git push public :fred-helpme to get
rid of the temporary shared branch.

- Finn Arne
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help