Re: [PATCH] Teach 'git pull' the '--rebase' option

Previous thread: [PATCH] Fix generation of perl/perl.mak by Alex Riesen on Thursday, October 25, 2007 - 1:17 pm. (3 messages)

Next thread: git-fast-import segfaults by cpettitt on Thursday, October 25, 2007 - 5:29 pm. (7 messages)
From: Johannes Schindelin
Date: Thursday, October 25, 2007 - 3:54 pm

When calling 'git pull' with the '--rebase' option, it performs a
fetch + rebase instead of a fetch + pull.

This behavior is more desirable than fetch + pull when a topic branch
is ready to be submitted.

fetch + rebase might also be considered a better workflow with shared
repositories in any case, or for contributors to a centrally managed
project, such as Wine -- or Git.

For your convenience, you can set the default behavior for a branch by
defining the config variable branch.<name>.rebase, which is
interpreted as a bool.  This setting can be overridden on the command
line by --rebase and --no-rebase.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-pull.txt |    6 ++++++
 git-pull.sh                |   11 ++++++++++-
 t/t5520-pull.sh            |   22 ++++++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index e1eb2c1..c3ce8ee 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -33,6 +33,12 @@ include::urls-remotes.txt[]
 
 include::merge-strategies.txt[]
 
+\--rebase::
+	Instead of a merge, perform a rebase after fetching.
+
+\--no-rebase::
+	Override earlier \--rebase.
+
 DEFAULT BEHAVIOUR
 -----------------
 
diff --git a/git-pull.sh b/git-pull.sh
index 74bfc16..b5ecb80 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -16,6 +16,9 @@ test -z "$(git ls-files -u)" ||
 	die "You are in the middle of a conflicted merge."
 
 strategy_args= no_summary= no_commit= squash=
+curr_branch=$(git symbolic-ref -q HEAD)
+curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
+rebase=$(git config --bool branch.$curr_branch_short.rebase)
 while :
 do
 	case "$1" in
@@ -43,6 +46,12 @@ do
 		esac
 		strategy_args="${strategy_args}-s $strategy "
 		;;
+	-r|--r|--re|--reb|--reba|--rebas|--rebase)
+		rebase=true
+		;;
+	--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
+		rebase=false
+		;;
 ...
From: Linus Torvalds
Date: Thursday, October 25, 2007 - 4:04 pm

I'd like there to be some *big*warning* about how this destroys history 
and how you must not do this if you expose your history anywhere else.

I think it's a perfectly fine history, but if you have already pushed out 
your history somewhere else, you're now really screwed. In ways that a 
*real* merge will never screw you.

So the "--rebase" option really is only good for the lowest-level 
developers. And that should be documented.

		Linus
-

From: Johannes Schindelin
Date: Thursday, October 25, 2007 - 4:10 pm

Hi,


Fair enough.

How about this in the man page:

\--rebase::
	Instead of a merge, perform a rebase after fetching.
	*NOTE:* Never do this on branches you plan to publish!  This
	command will _destroy_ history, and is thus only suitable for
	topic branches to be submitted to another committer.

Ciao,
Dscho

-

From: Jeff King
Date: Friday, October 26, 2007 - 4:43 am

Reasonable, although perhaps it should mention what I suspect might be a
common workflow for this feature: CVS emulation. I.e., there is a
central repo, which is the only thing considered "published". Developers
make commits in their local repo, and then rebase their changes onto the
HEAD before pushing. The only difference from CVS is that you don't
actually get to commit in CVS, you have to do the rebase with your
working tree. :)

I'm imagining a "pull.rebase = 1" config option, and handing this out to
developers accustomed to CVS.

-Peff
-

From: Jeff King
Date: Friday, October 26, 2007 - 4:45 am

Actually, I think I've just restated Junio's comment somewhat, so the
change you made in response to him is an improvement. Sorry for the
noise.

-Peff
-

From: Junio C Hamano
Date: Thursday, October 25, 2007 - 4:54 pm

Nits.

(1) This "operation" will "rewrite"  history.

    You are not describing a command, but just one mode of operation
    of a command, whose other modes of operation do not share this
    history altering behaviour.

    The history is rewritten and made hard to work with for others
    who have previous incarnation of that history.  If it happens
    that nobody shared that previously published history nobody
    needs to suffer.  In that sense, there is something _usable_
    depending on who you are.  Destroy feels a bit too strong a
    word.

(2) This is not suitable for people who publish their trees and
    let others fetch and work off of them.

    Rebase is fine for e-mail submitting contributors as your
    description above suggests, but as your proposed commit log
    message said, it is also perfectly appropriate if your
    interaction with the outside world is "fetch + rebase +
    push".  You are not limited to "submitted to another
    committer".
-

From: Johannes Schindelin
Date: Friday, October 26, 2007 - 2:52 am

Hi,



Well, originally I did not want to document it at all.  But I already 
heard the complaints about that in my inner ear.  So I documented it, 
sparsely, in the hope that those who do not know the implications will not 
dare to use it.  After Linus' complaint, I tried to make this shooing away 
more explicit.

I do not want to go into _that_ many details here, since the place to look 
for it is git-rebase.txt.  Probably I should have done that in the first 
place.

So how about this instead:

\--rebase::
        Instead of a merge, perform a rebase after fetching.
        *NOTE:* This is a potentially _dangerous_ mode of operation.  
	It rewrites history, which does not bode well when you
	published that history already.  Do _not_ use this option
	unless you have	read gitlink:git-rebase[1] carefully.

Hmm?

Ciao,
Dscho

-

From: Junio C Hamano
Date: Tuesday, November 27, 2007 - 5:11 pm

Okay.
-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 6:11 am

When calling 'git pull' with the '--rebase' option, it performs a
fetch + rebase instead of a fetch + pull.

This behavior is more desirable than fetch + pull when a topic branch
is ready to be submitted and needs to be update.

fetch + rebase might also be considered a better workflow with shared
repositories in any case, or for contributors to a centrally managed
repository, such as WINE's.

As a convenience, you can set the default behavior for a branch by
defining the config variable branch.<name>.rebase, which is
interpreted as a bool.  This setting can be overridden on the command
line by --rebase and --no-rebase.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	On Tue, 27 Nov 2007, Junio C Hamano wrote:

	> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
	> 
	> > ...
	> > I do not want to go into _that_ many details here, since the 
	> > place to look for it is git-rebase.txt.  Probably I should 
	> > have done that in the first place.
	> >
	> > So how about this instead:
	> >
	> > \--rebase::
	> > 	Instead of a merge, perform a rebase after fetching.
	> > 	*NOTE:* This is a potentially _dangerous_ mode of operation.
	> > 	It rewrites history, which does not bode well when you
	> > 	published that history already.  Do _not_ use this option
	> > 	unless you have	read gitlink:git-rebase[1] carefully.
	> >
	> > Hmm?
	> 
	> Okay.

	I also added documentation for the branch.<name>.rebase variable.

 Documentation/config.txt   |    7 +++++++
 Documentation/git-pull.txt |   10 ++++++++++
 git-pull.sh                |   11 ++++++++++-
 t/t5520-pull.sh            |   22 ++++++++++++++++++++++
 4 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 645514d..7bebc9a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -360,6 +360,13 @@ branch.<name>.mergeoptions::
 	option values containing whitespace characters are currently not
 ...
From: Jonathan del Strother
Date: Wednesday, November 28, 2007 - 6:15 am

Don't you mean fetch + merge ?

-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 7:02 am

Hi,


Obviously.

Thanks,
Dscho

-

From: Steven Grimm
Date: Wednesday, November 28, 2007 - 1:35 pm

I wonder if this shouldn't be branch.<name>.pulltype or something like  
that, so we can represent more than just "rebase or not." Values could  
be "rebase", "merge" (the default) and maybe even "manual" to specify  
that git-pull should neither merge nor rebase a particular branch even  
if it matches a wildcard refspec.

Not too sure about that last suggestion but it seems like there might  
be other settings than "rebase" and "merge" in the future even if  
that's not one of them.

-Steve
-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 1:40 pm

Hi,


I am not convinced that this is a good thing... We already have 
branch.<name>.mergeOptions for proper merges, and I want to make clear 
that this is about rebase, and not about merge.

Ciao,
Dscho

-

From: Lars Hjemli
Date: Wednesday, November 28, 2007 - 2:10 pm

Maybe branch.<name>.pullOptions ?

--
larsh
-

From: Junio C Hamano
Date: Wednesday, November 28, 2007 - 2:55 pm

Maybe not make this part of git-pull at all?  merge and rebase have
totally different impact on the resulting history, so perhaps a separate
command that is a shorthand for "git fetch && git rebase" may help
unconfuse the users.
-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 2:58 pm

Hi,


Not so sure about that.  We already have too many commands, according to 
some outspoken people, and this would add to it.

Besides, the operation "pull" is about getting remote changes incorporated 
in your current branch.  IMHO "pull = fetch + merge" is only a technical 
detail, and we should not be bound by it too much.

Ciao,
Dscho

-

From: Steven Grimm
Date: Wednesday, November 28, 2007 - 3:06 pm

Yeah, I agree. I almost never use "pull" as is because I almost always  
want to rebase. That is, it's basically clutter for me as a command  
right now, and it would remain so even if a separate fetch+rebase  
command were added.

I think this may be a difference in perspective based on how one uses  
git. If I were an integrator I would probably use "pull" as is a lot  
more because I would want the merges represented explicitly in my  
history. But most of the time I'm working as a leaf node in the tree  
of repositories, interacting only with a central integration repo, and  
I basically never want a give-me-the-remote-changes operation (which  
is really more of a "sync me up with the latest changes from the rest  
of the team" operation) to put a merge in my history.

What's more, when I'm introducing git to new people in my environment,  
right now I tell them about fetch and rebase and pretty much have to  
tell them to avoid running "pull" until they're comfortable with git,  
since I know their histories would be full of meaningless merges  
otherwise. It'd be nice to have new people run one less command as  
part of their normal day-to-day work.

-Steve
-

From: J. Bruce Fields
Date: Wednesday, November 28, 2007 - 3:33 pm

What they're really complaining about is the size and complexity of the
interface, and the lack of a clearly identified subset for them to learn
first.

This has so far mainly manifested itself in complaints about the number
of commands, because that's currently where a lot of our complexity is.
But they *will* complain about proliferation of commandline switches and
config options too.  (I've heard complaints about the number of switches
required on the average cvs commandline, for example.)

We're stuck expanding the interface here, whether we expand it by
another command or another commandline switch.

So, how do you decide whether to make it a new command or not?

	- Look at existing documentation that talks about pull: if that
	  documentation will still apply to the new pull, that weighs
	  for keeping it the same command.  If theat documentation would
	  apply only without having a certain config value set, then I
	  think it's better as a separate command.

	- Will this make it more or less simple to identify the subset
	  of the git syntax that a user will have to do a given job?  If
	  there are jobs for which someone might only ever need the new
	  fetch+rebase, or for which they would only ever need the
	  traditional pull, then I think it would keep the two separate,
	  to make it easier for a learner to skip over information about
	  the one they're not using.

I've got no proposal for an alternate name.  All that comes to mind is
the portmanteau "freebase", which is terrible....

--b.
-

From: J. Bruce Fields
Date: Wednesday, November 28, 2007 - 3:47 pm

Actually, considering the second point: people that are using
fetch+rebase don't necessarily need or (for now) want to understand pull
at all.  But they certainly *do* have to understand rebase.  Would it be
possible to add this to rebase instead of to pull?

	git rebase --url git://x.org/x.git master

where --url means "interpret <upstream> as a branch from the given
remote repository.

That interacts poorly with --onto, though.

--b.
-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 4:12 pm

Hi,


I was briefly considering it.

But the point is this: I know exactly if I want to rebase my branch onto 
upstream, or if I want to merge it.  There is not much point in mixing the 
two.

So my rationale was: if we already have an existing framework to integrate 
remote changes with our current branch, why not just go ahead and use it?  
That's the reason BTW why I originally wanted a "rebase" merge stragegy.  
Even if it is not technically a merge.

I really rather have no user-friendly support for fetch+rebase (and utter 
a friendly, but loud curse everytime I made a "git pull" by mistake) than 
yet another command.

Ciao,
Dscho

-

From: Junio C Hamano
Date: Wednesday, November 28, 2007 - 4:32 pm

I suspect that people who do not like the two modes of checkout will
certainly not appreciate the overloading two behaviours to create
different kind of histories and two different ways to continue when the
integration do not go smoothly upon conflicts these two behaviours have.

However, I agree very much with an earlier comment made by Daniel about
our UI being task oriented instead of being command oriented, and I
actually consider it a good thing.  So it does not bother me too much
that "git pull --rebase" has a quite different workflow from the regular
"merge" kind of pull.

So let's queue "pull --rebase" and see what happens.


-

From: J. Bruce Fields
Date: Wednesday, November 28, 2007 - 4:56 pm

What I'm really most worried about isn't the commandline switch but the
config option--it makes the same commandlines silently behave in very
different ways.

I really don't want every tutorial that mentions "git pull" to have to
say "the following applies only if git.<current-branch>.rebase is
false".  And it'll be either that or risk having a lot of people saying
"I typed in exactly that commandline, but this happened....".

A default to "false" does at least require positive acknowledgement, but
if this is expected to be used by newbies, they're going to be told to
set that config before they understand the difference it makes.

--b.
-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 5:16 pm

Hi,


Hey, why not just special case "mergeOptions = rebaseInstead"?

Ciao,
Dscho

-

From: Andreas Ericsson
Date: Thursday, November 29, 2007 - 1:36 am

I've used the --rebase option to git pull, explained it to my co-workers
and also made sure they're using a version of git that has it. So far
there hasn't been a single complaint about "git pull" being any harder
to grok.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
-

From: Nicolas Pitre
Date: Wednesday, November 28, 2007 - 8:23 pm

Well, the idea is that once all those plumbing commands are hidden away 
in some libexec dir, that makes a _lot_ of breathing room for a few 
more porcelain commands if needed.


Nicolas
-

From: Jon Loeliger
Date: Wednesday, November 28, 2007 - 2:59 pm

At long last, we can revive "git update"!

jdl

-

From: Johannes Schindelin
Date: Wednesday, November 28, 2007 - 3:02 pm

Hi,


No, we cannot.  By now, too many aliases are called "update".

Ciao,
Dscho

-

From: Björn
Date: Saturday, December 1, 2007 - 1:37 pm

Hm, why not tackle the whole thing the other way around? IMHO the
primary action is the merge/rebase, not the fetch. So choosing which
action you want in addition to the fetch seems a bit backwards. git-svn
already includes a fetch from svn in its rebase operation, which is
really handy, because you rebase quite often with that beast.

And it's likely that you want to merge with/rebase against the latest available
remote commit all the time anyway and on the few(?) occassions
where you have no connectivity, but already fetched some remote stuff
which you want to incorporate into your local branches now, it's
hopefully bearable to pass --no-fetch.

So how about adding --fetch/--no-fetch (maybe with a configurable
default?) to git-merge/git-rebase and deprecate git-pull over time?

Björn
-

From: Karl
Date: Monday, December 3, 2007 - 6:10 am

FWIW, I like this idea. rebase/merge is the complicated part of the
operation, so the UI should focus on that. Updating or not updating
the remote-tracking branch that is merged from/rebased on is a simple
binary choice, so a flag is perfect.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle
-

From: Linus Torvalds
Date: Thursday, October 25, 2007 - 4:36 pm

Well, it really needs explanation of what "destroy" means. 

Also, it's not strictly even necessary to publish things for this to cause 
problems. It's perfectly sufficient to just do development on two private 
developer machines, and do things like keeping the two machines in sync by 
pulling things between them manually...

So even "normal" developers who never publish a git tree to others may 
actually hit this issue.

			Linus
-

From: Linus Torvalds
Date: Thursday, October 25, 2007 - 4:49 pm

.. or any branch use, for that matter.

I do agree that "git merge --rebase" is potentially convenient, I'm just 
not sure it's a great idea to document as such. People shouldn't do it 
unless they really *really* understand the implications, and I think the 
implications are much easier to understand if you instead teach them 
"fetch+rebase", and perhaps even keep the "merge --rebase" option entirely 
undocumented.

				Linus
-

Previous thread: [PATCH] Fix generation of perl/perl.mak by Alex Riesen on Thursday, October 25, 2007 - 1:17 pm. (3 messages)

Next thread: git-fast-import segfaults by cpettitt on Thursday, October 25, 2007 - 5:29 pm. (7 messages)