
Please use git pull --rebase - bitsweet
https://coderwall.com/p/7aymfa
======
ultimoo
While the idea of rebasing history while pulling in new changes may appeal to
some users or uses, I disagree with the absolute "one true way" sounding note
of OP's article.

Git supports first class merging, and it is git's default behavior. It enables
us to port over entire strings of commits related to a feature to other
branches, or enables us to revert (un-merge) these strings of commits. Heck,
--rebase doesn't even allow one to pull when there are uncommitted changes in
the working directory.

On the other hand, --rebase is neater when it comes to the modern mantras of
"commit frequently", "no feature branches", "deploy master to production". So
in short this sounds more like an editor or a tab v/s spaces flame war.

~~~
dustingetz
what's the idea behind no feature branches?

~~~
ajross
There are "feature branches", and there are "patch sets with four patches and
three merge commits that are there just because the submitter did a bunch of
pulls while working on it."

If you're dealing with a large code base with many submitters, you _have_ to
demand that individual submissions apply cleanly. That is isomorphic to
demanding that they be rebased.

~~~
jcrites
I am personally a proponent of rebasing, but I'm reading through the recent
Hacker News threads to get a sense of the arguments on both sides.

> If you're dealing with a large code base with many submitters, you have to
> demand that individual submissions apply cleanly. That is isomorphic to
> demanding that they be rebased.

To play devil's advocate for the merge perspective: wouldn't this also be
achieved if the commit author had merged master into his branch first before
submitting? It will apply cleanly because conflicts were fixed during the
merge, rather than because it was rebased.

------
benjamincburns
I humbly submit that this is a holy war. I personally am on the side of
"history is just another part of the project to be maintained," but tread
carefully friends; there's dogma at work here.

On one hand it's good to preserve things exactly as they happened. How else
will we blame Dumb Steve guilt-free when someone branches from an arbitrary
hash to give a one-off release to an angry customer, thereby bifurcating the
state handling logic that allows the machine to be certain that it's not
emptying a crucible on a crate of orphaned puppies? Think of the puppies!

On the other hand, it's good to align commits to units of work. It's cool that
you've forked the project to handle massively concurrent input caused by edge
case X (sorry, I used up most of my creativity on the last paragraph), but
really I just want your cool configuration parsing piece. Can I cherry-pick
that, please?

Git was designed to give you the choice. Do you care about preserving the
ability to perform an arbitrary audit, or do you care about treating
development as a series of portable patches? You decide, and then do what's
right for you.

------
wonnage
While this makes sense when dealing with a central repo (which I agree is the
vast majority of use cases), it's inaccurate. You're rewriting history so that
it looks like your work happened on top of $REMOTE's work, when in reality it
was the other way around. This becomes a problem if you're working with
multiple remotes, and which remote you pulled from, and when you did it
becomes an actual concern.

Concrete example: if I'm the maintainer of wonnage/foo and bar submits a pull
request from bar/foo, using git pull bar --rebase doesn't make a whole lot of
sense.

~~~
kelnos
Of course, that's absolutely correct. But that's the _minority_ use case, at
least in my experience. Git's default is set up that way because of how the
Linux kernel maintainers work, which isn't how most organizations who use git
work.

Even though git is distributed, most orgs have a central repo that they use as
the source of truth. When contributors pull from this central repo, IMO they
should be rebasing, not merging. When the maintainer pulls from other people,
yes, he should of course be merging.

The merge commit that a contributor implicitly creates when they resync with
upstream (without rebasing) is ugly and confusing. It provides no useful
information and only serves to clutter the project's history, not make it
clearer.

~~~
jedbrown
A topic branch workflow is tremendously useful even without separate people in
the "developer" and "integrator" roles. For example, we have about 20 people
regularly developing code and about five of us "integrate", first to 'next',
then to 'master' when a feature has stabilized. We don't explicitly pass an
integrator token so there is a possible race to the integration branch, but
since we only merge there, it's actually pretty rare in practice. If you lose
the race, the polite thing to do is discard your old merge, fast-forward, and
repeat the merge. This preserves first-parent.

[http://git-blame.blogspot.com/2012/03/fun-with-first-parent....](http://git-
blame.blogspot.com/2012/03/fun-with-first-parent.html)

------
oneandoneis2
Um.. No.. if you use rebase regularly, you're doing something very wrong.

In this case, the problem is that development isn't being done on a branch.
One of the most important features of Git is how easy it is to fork & merge -
there's no excuse for doing your work on master.

Work on a branch, merge your branch into master when it's finished. History is
completely accurate, you only get one merge commit.

Don't mess up history just to work around bad workflow. Fix the problem at its
source.

~~~
eloisant
Indeed when you do work on a feature branch, you shouldn't rebase.

But when you're working on master, or a branch that's also remote, then you
_have_ to rebase. If you don't then you get completely meaningless merge
commits. If 3 people merge when they just want to push a commit it then you're
history becomes a tangled unusable mess.

~~~
Cthulhu_
Then those three should've worked on their own feature branch. In fact, one
could consider a local copy of master (or, commits made on master on one
user's machine) as a feature branch, all named 'master'.

Another thing, a developer doesn't need to obsessively pull every couple of
minutes. If they're fixing a bug and deciding against using a branch for that
(seeing that it could be just one commit), they only pull twice; once before
they start working, and again when they're done and want to push to master.

If there's more than one person fixing the same bug simultaneously, then it's
yet another process bug.

------
aiiane
Perhaps better stated as "please, oh please, actually pay attention to
history" - there are times when rebase is appropriate and times when merge is
better.

~~~
khasinski
Yes, but I used the title for people to actually start using rebase. Caring
about history beyond avoiding useless merges and broken commits is another
step I'd like at least my co-workers to take ;)

------
pwim
Rather than always using

    
    
      git pull --rebase
    

you can set up your git config to always rebase when pulling.

    
    
      git config master.rebase true
    

sets it up for master of the current repo

    
    
      git config --global branch.autosetuprebase always
    

sets it up for all new branches.

~~~
nahname
I would recommend that you do not do this. I rebase probably 80% of my pull
requests, but sometimes you do want a merge commit. Instead, I setup an alias
for git pull --rebase

This also helps when pairing with someone else. The process of handling a
rebase conflict vs pull/merge (regular pull) is quite different.

~~~
wanderr
if you want to do a merge commit sometimes, but pull --rebase most of the
time, why not make pull --rebase the default, and do a fetch && merge when
that's what you want?

~~~
Zombieball
Because what if you 'already' created a merge?

Example: I am working on a local branch feature/xyz. I decide I am done my
work and merge feature/xyz -> master. I get ready to push and realize I am 5
commits behind origin/master. How do I fetch them now?

If you use git --rebase it will clobber your feature branch merge commit. On
the other hand if you do a fetch & merge this also probably is not what you
want (you will have a merge-commit on top of your merge commit, dawg). git
rebase -p is probably the best option in this scenario.

~~~
erso
I would ignore everything base698 says below.

In this case, you have a merge commit from a branch on to master, which would
look like:

    
    
        A-B(master)----F (merge commit)
            \         /
             C-D-----E (topicA)
    

Once you find out your master (B) is behind, because say there's G-H-I on
origin, you'd want to rebase onto that. So you use the 3-argument form of git
rebase --onto:

git rebase --onto origin/master C~1 E

Which would take C's old base, C~1 (B), and replace it with origin/master, but
only up to E.

Or, if you still had the branch around that you merged into master (which you
do, in many forms, including the reflog, even after you delete the branch).

git rebase --onto origin/master topicA

I wrote a blog post on the different uses of git rebase --onto:
<http://krishicks.com/blog/2012/05/28/git-rebase-onto/>

~~~
Zombieball
Ah awesome, I love there are so many things to learn about git.

I knew about git rebase -p and its nuances, but haven't known about the --onto
until now. The 3-argument form of git rebase --onto in your blog post was
great, thanks!

------
redshirtrob
I like this philosophy for small, easily testable commits (e.g. minor bug-
fixes). However, I _never_ recommend others to use this workflow.

I feel like rebasing is the type of feature you really need to understand to
use. If you understand the concept and how to apply it, you can do powerful
things. If you don't, you'll munge your repo and end up begging the local git
guru to bail you out of your mess.

While I don't enjoy looking at a commit history with a bunch of useless
merges, it's better than encouraging users to perform an operation they don't
understand.

~~~
jen_h
No kidding. Nothing makes you miss svn more than an inappropriate rebase. I've
done it twice now, & sorely regretted. Heck, once, I was bit so badly by it
that I actually said something positive about Rational Clearcase.

------
Smudge
As a quick illustration, this is what can happen to the commit tree when just
one of your team members doesn't rebase by default:

<http://pastebin.com/cnPbg0vm>

------
pcl
So it definitely keeps history nice and pretty, and I use it for simple
commits all the time.

However, sometimes I do 'git pull --no-ff' explicitly, because I want a more-
complex multi-commit sequence of operations to stand out as a unit of work.

I really wish git had a primary concept of such a thing. I understand that hg
might, but haven't had an opportunity to get that far into an hg project yet.

~~~
X-Istence
What do you mean a primary concept?

~~~
pcl
The use case that comes to mind first is 'git bisect'. I love that feature,
but I also love to leave a messy trail of commits in my history. In other
words, I expect that there will be commits in my history where a full test run
might not work, or maybe even things might not compile.

Of course, that sort of thing royally messes with 'git bisect'.

If git had a primary concept of "here's a synchronization point", then it'd be
much easier to build tools like 'git bisect' (and even 'git log' etc.) around
those sorts of paradigms. That'd offer the best of both worlds -- rich,
detailed history showing how something got done, but also points at which it
was believed that all was good in the world.

A push is (should be?) a natural synchronization point, for example.

~~~
to3m
Some form of nested commit would be useful for this I suppose - it would be
arranged with something like an interactive rebase, that would squash a
sequence of commits into one (for the purposes of log and bisect and the
like), while leaving the original ones still accessible. This would give you
your neat history for most purposes without losing the original commit
comments and original sets of individual changes.

This is of course a bit like how branches are merged together ordinarily, at
least if you don't go around deleting them the moment you're done with them.
And sure enough it looks like you can sort of persuade git bisect to treat
ordinary branch merges like this:

[http://stackoverflow.com/questions/5638211/how-do-you-get-
gi...](http://stackoverflow.com/questions/5638211/how-do-you-get-git-bisect-
to-ignore-merged-branches)

------
comex
This has been mentioned in another comment, but not a top level one, so here
it is again:

Rebasing multiple commits means putting commits into the history that do not
correspond to any actual historical version. If you manually test each commit
to ensure that the merged version still compiles and runs, or you're sure that
the changes don't conflict and don't get unlucky, then you have something akin
to a patch set, a semantic rather than actual history that is easier to read
and perform operations like git bisect on. But otherwise, you can end up with
broken commits in the history that, when retrieved for bisection or other
purposes, obscure whatever is actually supposed to be observed.

Regardless of whether merging or rebasing produces 'better' history, if you're
lazy, merging lets you stay that way without creating _broken_ history.

------
khasinski
OP here,

I do prefer feature branches (especially git flow:
<https://coderwall.com/p/d1pkgg> ), but for day to day 'agile' development in
a small team we don't use them often. YMMV.

But for pulling changes working on local branch git pull --rebase (or
autorebased branch) is many times more readable (and avoid ugly merge bubbles
in history).

Branch when you need branches, merge when you mean merging, rebase when you're
just updating your codebase from shared repository. Keep your local (not
pushed/pull-requested yet) branches dirty (commit often!), rebase them into a
clean, obvious history before you share them.

Remember - commit history is for other people to __READ __.

------
zerohp
Rebase only if you treat it like a centralized version control system.

Using it all the time breaks a lot of good DVCS workflows.

------
johnpmayer
If you're going to rebase every pull, you may as well just use SVN.

~~~
rcfox
Git has benefits over Subversion besides the crazy commit graphs. I'm not sure
there's really any reason to be using SVN when you could be using Git in the
exact same style, and have the benefit of offline access to the repository.

Actually, I'd be interested in hearing about any sort of layers on top of git
that make it work like SVN (ie: same commands, same workflow, etc.) It would
probably help convince some people to move away from SVN.

~~~
mh-
such a layer would be difficult to provide in a way that isn't misleading, if
the hypothetical subversion expatriate currently uses any functionality
involving multiple _(SVN)_ branches.

------
Randgalt
No rebase please. Let's keep the history accurate.

~~~
mpyne
That's just it. It _does_ keep the history accurate, if you're literally just
trying to grab updates from upstream. Unless you're actually working on, or
merging, a separate branch then normally rebase is what you want.

~~~
DoubleCluster
It does NOT keep history accurate. You have absolutely no guarantee that all
rebased commits work as intended or can even be built. The only thing that can
be rebased safely is a single commit, for the rest you should learn to live
with a messy history. It doesn't really matter anyway as long as you have
procedures to prevent criss-cross merges.

~~~
mpyne
If you require that each individual commit meets semantic criteria then you
can still require that to occur during a git rebase by rewriting the commit.
Which you should probably be doing anyways, if you're pulling breaking changes
from upstream.

------
ricardobeat
Be careful though, rebase doesn't preserve merge commits. If you want to
rebase after a merge you need

    
    
        git fetch && git rebase -p
    

I recommend using git-up[1] which solves everything in a single command.

[1] <https://github.com/aanand/git-up>

~~~
Zombieball
This is very good advice!

git --rebase will clobber local merge commits (e.g. when closing off a feature
branch & getting ready to push the merged results).

I threw together a quick custom action you can use with Sourcetree to utilize
git rebase -p. Interested folks can nab it here:
<https://gist.github.com/dgourlay/5465540> Install instructions here:
<http://www.derekgourlay.com/archives/478>

I think I may need to give git-up a look over though.

Thanks!

~~~
jcrites
> local merge commits (e.g. when closing off a feature branch & getting ready
> to push the merged results

Why not rebase the feature branch onto the master branch? Then the merge from
feature to master will be a fast forward commit rather than a merge commit.

Developing this way one can mostly avoid actual merges. And the repository
history is simple and linear afterward. I've been working this way for a while
and I have found it effective.

    
    
      % git checkout feature
      % git rebase master
      % git checkout master
      % git merge --ff-only feature
    

(-ff-only isn't needed, but I like to confirm to catch mistakes)

Any commits that you have made locally (and haven't pushed anywhere public)
are safe to reorganize in this way, and it results in simpler history.

~~~
ricardobeat
If your workflow is based on very small feature branches, that's fine, but
when your branch is more heavy on changes it's good to preserve the merge
commit (and be able to undo it).

~~~
Zombieball
Yes this is precisely what I had in mind, for larger features I personally
prefer to see merge commits and not rebase the branch onto master. I believe
it is one place where merge commits definitely add value and make sense.

------
justin_vanw
Rebase is nice if you have very careful code review policies. Otherwise, if
you don't have humans carefully reading every merge, it is a huge waste of
time.

Rebasing also increases the number of conflicts you will have to resolve. I've
seen this 'always rebase' advice over and over in the last few years, it's
stupid advice that betrays a lack of understanding about how git works. There
is no advantage whatsoever unless you also squash your commits, and even then
there is no advantage unless you are submitting to a project with very careful
code review practices (Linux kernel, a project that uses the gerrit code
review tool, etc).

------
dscrd
Or just use mercurial which tends to do the Right Thing by default more often.

~~~
lysium
In what way do you think is mercurial's "Right Thing" a different "Right
Thing" than what git does (by default)?

~~~
dscrd
In the way whereby nobody ever complains about usability issues like this one.

------
reyan
Or use git-smart (<https://github.com/geelen/git-smart>). It adds three
commands to git. One of them 'smart-pull' which "will detect the best way to
grab the changes from the server and update your local branch, using a git
rebase -p if there's no easier way. It'll also stash/pop local changes if need
be."

~~~
ultimoo
While such wrappers around git always pique my interest and and are created
with noble intentions, I am yet to find a team of developers who use such
tooling around git. There are dozens of wrappers and workflows around git that
have been created in the last 3-5 years and frankly it only complicates the
shared vocabulary that developers use when communicating with one another.
Also, distribution of such wrappers is usually in the form of rubygems which,
although a low-barrier distribution mode, is complicated to use with rvm or
rbenv of existing projects .

~~~
mbillie1
The only git-related tool I like is tig - it's an interactive git log, where
you can scroll through commits and view diffs (and lots of other things)
without having to copy+paste or use awk or whatnot. This tool (git-smart)
seems like... I don't know. For me, I'd rather have my team suffer the
learning pains of git than rely on a tool that, in some cases, will fail and
leave them even more helpless than they were when they struggled to learn git.

I do recommend checking out tig though; that's the one that I have kept. It's
also not a gem, it is available through yum or apt (and probably pacman, brew,
etc).

~~~
ultimoo
Yes, I am actually guilty of using `tig` for a long time too. :-)

------
tootie
"to keep the repository clean"

Seems like not a worthy objective. Has anyone here ever had a project saved by
a tidy commit history?

~~~
darrencauthon
Totally agree. At best this rebase talk is navel-gazing, and at worst it's a
technique that turns Git into a complicated, scary place for those just want
to get work done.

I have introduced git and hg to many people, but I've always tried to tie it
into what people do already. Without source control, practically everybody did
the same thing: They'd work a little bit, they'd save, they'd work a little
bit, they'd save... etc. Using branching for organizing work and a nice cheat-
sheet of a few git commands, most non-technical people will be off-and-
running.

It all works until the programmers make it complicated with the rebasing. The
price of the tidy commit history is the loss of confidence of the rest of the
team. I'd rather have the people.

Case in point: <https://vimeo.com/60788996>

~~~
base698
It's only complicated because people don't realize how it works. Half the
people in this thread advocating to use rebase aren't saying when it's ok and
when it's not ok and why.

When it's ok: You are working on your own line and the commits you've made are
not in a central repo.

Why: Git commits are a hash tree and when you change one commit it changes all
the SHAs that come after it. This makes git see your commits pushed remote as
different then the ones that are local. The commits have the same changes so
it puts duplicate conflict markers everywhere.

Most people love it once they realize how it works.

A lot of people use version control also as a backup in case their hard drive
fails. Because of this they are scared of staying on a topic branch for very
long, so they push then rebase often leading to conflicts which are scary.

<https://en.wikipedia.org/wiki/Hash_tree>

------
jayferd
I've been telling people lately to always fetch and merge --ff-only
separately, which is more commands but less confusing behavior. If you've got
merge.defaultToUpstream set to true, you can alias ff = merge --ff-only. That
way you can be careful about rebases, and don't have them automatically
happening behind your back. So the workflow is:

    
    
        % git fetch # can never fail with a conflict
        % git ff    # tries to fast-forward
        # if fast-forward fails, then
        % git rebase origin/upstreambranch

------
stasm
There is history and there is cleanness, as Linus Torvalds explained in
<http://lwn.net/Articles/328438/>.

The git way of doing what the OP wants to do is to develop all code on local
branches. They're cheap and you can have as many of them as you want.

Just never commit directly to master and set it to track upstream/master.
Synchronize with upstream by pulling into your local master, and then rebase,
merge & diff your local branches at will.

------
djbender
Mislav has a great article on this topic:
<http://mislav.uniqpath.com/2013/02/merge-vs-rebase/>

------
voyou
From the article:

"When working on a project you usually synchronize your code by pulling it
several times a day."

Do you? Am I alone in thinking that seems like a really bizarre workflow?

~~~
khasinski
From my experience it is common for a group of developers co-working on some
feature to share codebase very often.

Also in an actively developed project there are likely to be many new commits
every single day, and you want to be up to date with remote codebase to ease
the pain of merging your features into it.

If you rebase your work onto master often you'll greatly speed up the release
of your feature when it is ready. You'll also avoid late surprises when
something you depend on elsewhere in codebase change.

You can also notify your co-workers about inconsistencies between developed
features and detect incompatibilities early.

It also works in macro scale - projects released often with small changes
shorten the feedback loop and can be adjust properly for their requirements.

------
orefalo
Can't agree more, I'll push it even further...

Use G2! which does pull --rebase magically on your behalf.

<http://orefalo.github.io/g2/>

<https://github.com/orefalo/g2>

------
bnegreve
I try to avoid rebasing everything all the time because it changes the commit
dates which can be confusing when you are tracking some particular changes.

------
rachbelaid
why not changing your config for the no-feature branch to avoid that people
forgot the --rebase arguments

git config branch.master.rebase true git config branch.develop.rebase true

This will make any pull be a pull --rebase on the master/develop

------
winstonchurch
This is a TERRIBLE rule: they have no clue how git works.

Read: <http://goo.gl/ONw7Q>

~~~
mortehu
To quote the page you linked:

> People can (and probably should) rebase their _private_ trees (their own
> work).

------
lurker14
Is coderwall some sort of troll site, like the the Swedish Lemon Angels recipe
in How to Play With Your Food?

I keep seeing bad advice posted there and popping up on HN.

