News for hackers. Stuff that matters.
Re:Please use git pull --rebase by ultimoo on Monday April 29, 2013 @09:27PM (#5629942)
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.

Re:Please use git pull --rebase by sitharus on Monday April 29, 2013 @11:50PM (#5630331)
As someone who works with a fairly large number of committers with many branches, I prefer merges to rebases.

The reason is simple, you always know _why_ something happened, which is quite important when looking for clues in the history. When trying to figure out what old code was intended to do it's much better to see it in the original context, not a re-written to merge context. As a benefit it also preserves change dates.

Re:Please use git pull --rebase by erso on Tuesday April 30, 2013 @12:04AM (#5630368)
The thing is, you don't know _why_ something happened any more with a merge strategy than a rebase strategy.

In fact, you know less.

It's as if someone was doing work against an old, old, old version of your code. Say they did a bunch of work, months out of date, and then wanted to merge it in. Almost assuredly there'd be tons of conflicts, the code wouldn't match up at all with the current state of the world, and what they did in the commits would be entirely useless knowledge without also knowing what resolutions to the conflicts happened as part of the merge commit.

So anyone that looks back at those commits that were made against the old codebase have to know that what they're looking at is horseshit which had to be patched up before it could be merged in.

If they had used a rebase strategy they'd have updated their commits to the current state of the codebase such that they could be cleanly applied. Now you still know what feature(s) were added, but in a way that actually took into account the current state of origin when the commits were rebased.

Re:Please use git pull --rebase by jamie_ca on Tuesday April 30, 2013 @02:04AM (#5630637)
> they'd have updated their commits to the current state of the codebase such that they could be cleanly applied.

Yes!

> If they had used a rebase strategy

No....

Take your out-of-date branch, merge master into it, and clean it up _in the branch_. It's not 2011 anymore, there's lots of tooling that makes viewing changelogs on a branch compare easy (Github's pull requests being probably the most common).

Rebasing removes your changes from the _context_ they were originally made, which makes following along through the project's history harder than it needs to be. It also creates revisions of the codebase that never actually existed, which means it's difficult if not impossible to use git-bisect to track down when a really gnarly bug was introduced (I've actually needed to resort to that 3 or 4 times in the past few years, to help track down the cause of the bug).

Re:Please use git pull --rebase by erso on Tuesday April 30, 2013 @08:05AM (#5631621)
Except this idea of the context in which you wrote the code doesn't actually matter to anyone.

More likely you're going to piss off everyone that has to deal with your merge strategy because your commits that couldn't be merged into master are broken, having been fixed as part of the merge commit(s).

Such commits:

* Aren't able to be bisected (they're broken, remember?)

* Aren't able to be blamed (the collective merge commits and the actual commits have to be considered at the same time)

* Aren't able to be rebased later when you decide, actually, this merging shit is ridiculous (the -p option to rebase is dangerous and doesn't always work the way you think it will)

* Aren't able to be traversed cleanly in a log because they're probably split up with merges of master into your branch all over, because hey, you wanted to stay up to date.

* Basically aren't understandable by anyone, including you.

Being that it's not 2011 anymore (sorry, what?), you should learn how to use Git properly, understand what effects your workflow have both to you and to those that read your code (including you!), and those that choose to use Git's tools.

I once had a situation on a client project while at Pivotal where a guy had been working on a branch for 2 months, continuously merging master into his branch. It was a shitshow. He had 45 commits of his own plus 10-15 merge commits from origin/master. Doing a git log of that nonsense was basically impossible to read, impossible to code review (the client's process at the time), and when merged back into master would have been the most crazy ass log --graph I can imagine (because everyone else was doing similar nonsense). We're talking a 10-pair dev team all merging origin/master into their local master. The log was unreadable, unusable, not to be understood by anyone.

Luckily I was able to remove all the merge commits via the 2-argument form of rebase --onto, (http://krishicks.com/blog/2012/05/28/git-rebase-onto/) which then gave him the freedom to squash, reorder, fixup, and split his commits as he felt necessary to maintain his and everyone else's sanity. In the end he filtered it down to something like 20 very clean, green commits that could be reviewed by another person and understood, and rebased on top of origin/master.

Re:Please use git pull --rebase by base698 on Monday April 29, 2013 @11:35PM (#5630285)
Git's commit log is a hash tree (like the bitcoin block chain). When you commit you get a SHA for that commit. Part of the SHA contains the SHA of the commit before it. When you rebase it changes the SHA's of all the commits you've made. That's a lot of why you end up with conflicts when you don't know what you're doing. Never rebase if you've pushed the commits to a central repo because git will detect conflicts of the changes. You end up with duplicate commits with different SHAs after you resolve the conflicts and continue.
Re:Please use git pull --rebase by bxbb on Tuesday April 30, 2013 @01:09AM (#5630512)
> Never rebase if you've pushed the commits to a central repo because git will detect conflicts of the changes.

the manual already cover this issue[1]. In short, rebase when you pull if you prefer to, but always merge when you push.

[1] http://git-scm.com/book/en/Git-Branching-Rebasing#The-Perils...

Re:Please use git pull --rebase by base698 on Tuesday April 30, 2013 @01:36AM (#5630580)
http://2.bp.blogspot.com/-NBip49LJnRs/UUxapwtg5XI/AAAAAAAACm...

After reading this thread how many people would you guess have done that? Fairly good advice but if you wait for everyone to finish the book you'll wait forever. Better educate constructively when needed.

Re:Please use git pull --rebase by erso on Tuesday April 30, 2013 @08:30AM (#5631707)
What you've said here is at best disingenuous, at worst outright wrong and confusing.

The changing of the SHA per se has nothing to do with why a conflict might arise. The conflict may arise because a particular commit could not cleanly be applied to the new base. The contents of the commit need not even change, which you can verify by looking at the actual contents of the commit, meaning the blobs that it contains. The blobs may stay the same (and indeed, will unless there's a conflict during the rebase), while the SHA changes.

> Part of the SHA contains the SHA of the commit before it.

This is incorrect.

A commit SHA has a tree SHA and a parent SHA associated with it. It's the parent SHA (the base of the commit) that changes when you rebase, which is a cascading change that continues down the tree in order as commits are applied. The SHA only changes because the SHA is a hash of the contents of the changeset and the time at which the commit was created.

You can see the commits along with their parent and tree hashes by doing `git log --format=raw`.

> Never rebase if you've pushed the commits to a central repo because git will detect conflicts of the changes.

This is also incorrect (or at least badly worded and disingenuous).

Git only knows that the changes you're attempting to push will cause you to lose data, which it says explicitly when you rebase a commit that's been pushed to the remote.

You should of course avoid rebasing commits that are on the remote unless you are the sole committer on the remote branch (meaning nobody else is pulling from that branch). You have to force push the branch when you do so, which is fine when you're the only person looking at it and disastrous when not.

Re:Please use git pull --rebase by noamsml on Tuesday April 30, 2013 @02:50AM (#5630742)
I don't get why people like rebasing as an alternative to merging. It works kind of OK for small histories, but if you do something slightly complex or your history is not meticulous, rebasing becomes extremly tedious. The worse example is a conflict in a reverted commit. A merge will flatten the diff and skip the reverted commit entirely, while a rebase will require you to fix the conflict twice. And while a merge is tedious to revert, it is possible. Good luck saving a branch ravaged by a bad rebase.
Re:Please use git pull --rebase by lotyrin on Tuesday April 30, 2013 @03:26AM (#5630831)
> Good luck saving a branch ravaged by a bad rebase.

Git rebase --abort before you've finished screwing up, or if it's too late, use the reflog and reset back to before you started.

Re:Please use git pull --rebase by __--__ on Tuesday April 30, 2013 @04:32PM (#5634686)
If you're working on a large team, this becomes a more pernicious problem. I've seen rebases change histories to the point that whole branches become incompatible with master. When you have 15 people all merging branches into master, complete with binary files, conflicts are frequent and often involve files you personally didn't change. People resolve the conflicts to the best of their ability, but they have no idea why certain things conflict and bugging your co-workers every time you merge a branch is unrealistic. So we guess and whole features get wiped off the face of the repository.

My team now has a merge only policy and it's reduced the number of conflicts and borked merges.

Re:Please use git pull --rebase by dustingetz on Monday April 29, 2013 @09:59PM (#5630038)
what's the idea behind no feature branches?
Re:Please use git pull --rebase by ajross on Monday April 29, 2013 @11:55PM (#5630344)
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.

Re:Please use git pull --rebase by jcrites on Tuesday April 30, 2013 @06:33PM (#5635310)
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.

Re:Please use git pull --rebase by jcoder on Monday April 29, 2013 @10:07PM (#5630060)
If I understand GP, it's the idea that when your work on a feature branch is complete, you use rebase to base that branch on the current tip of the branch you are integrating to, e.g., "master", so the result does not reveal the presence of a branch.
Re:Please use git pull --rebase by sanderjd on Monday April 29, 2013 @10:15PM (#5630075)
If I understand the poster you're replying to, he understood that, but doesn't understand why you would want that. I'm in the same boat - why are people willfully throwing away useful history?
Re:Please use git pull --rebase by erso on Monday April 29, 2013 @11:59PM (#5630351)
There's a simple concept at work here: origin wins.

Whatever is on origin at the moment of you wanting to merge your code is what your code has to work against.

When you use a rebase strategy you're allowed the opportunity to make sure your commits actually work on top of what's on origin, and fix merge issues with those commits as they happened.

So you rebase, run into a conflict, fix the conflict, run your tests, make sure everything's green, and continue the rebase.

When you do the same thing with a merge strategy what happens is you end up fixing the conflicts as part of the merge, and your fixes are hidden in the merge commit.

This means your commits prior to the merge commit are broken. They didn't take into account the work that was on origin at the time, and thus they are useless without considering the conflicts that were resolved during the merge.

The history you describe is not useful unless it's green and could be applied to origin without conflict. The only way to ensure this, both before and after your commits end up on origin is to do so via a rebase strategy.

Re:Please use git pull --rebase by stfsbrb on Tuesday April 30, 2013 @05:48AM (#5631217)
Thank you for this. I cannot believe how many people are glossing over the fact that commits which have to be fixed up in a merge are probably broken. Rebasing is not a way of hiding this, it is a way of _going back and fixing it_.
Re:Please use git pull --rebase by sanderjd on Tuesday April 30, 2013 @10:33AM (#5632368)
Thanks for the well reasoned response! Your points are all reasonable, and I understand the pragmatism in wanting only fully-green commits to be on origin. I just think merge commits for logical chunks of work are more important. I read history to understand developer intention and process more than I bisect history to find problems. Those conflicted commits aren't broken, they represent the best effort at the time the changes were made and merely need to be merged together with the world as it is now.
Re:Please use git pull --rebase by erso on Tuesday April 30, 2013 @10:41AM (#5632411)
I'm not sure I understand.

If I'm making a change to some code and someone else makes a different change to it and pushes their change to origin before me, I do a rebase and see that they made the change, fix my commit (which is broken at that point in time), resolving the merge conflict, and continue on.

Instead of seeing some changes that have no basis in reality because they were fixed as part of resolving the conflict when doing the merge, you see only their changes applied on top of the correct state of the world, which gives you a clearer idea of what changes they made.

You can still get logical chunks of work with a rebase strategy: you simply rebase on top of the remote and then do a non-fast forward merge, via merge --no-ff.

Re:Please use git pull --rebase by sanderjd on Tuesday April 30, 2013 @11:07AM (#5632587)
It's simple: you're into working off of the newest state of the world as much as possible and I'm into working off of a snapshot of the world as much as possible and then merging in my snapshot plus modifications when I'm done. I think your way sounds like it deals with changes to the world more often than I want to, and also loses the context of what your commits looked like when you actually made them, but it's a fine way of doing things, and is especially useful if you're submitting changes to a project for somebody else to merge.
Re:Please use git pull --rebase by andrewflnr on Monday April 29, 2013 @10:32PM (#5630124)
Define "useful history". ;)

There's history in the sense of "log of everything that happened" but also in the sense of a nice record of decisions that were made, documentation essentially. I'm guessing "no feature branches" aims more for the latter. Personally, I'm not sure why we shouldn't have both.

Re:Please use git pull --rebase by SoftwareMaven on Monday April 29, 2013 @11:13PM (#5630228)
Both would be nice. I generally restructure commits before pushing them to master in order to make them easier to read, which is nice for others. However, I think about the code in the order I built it, especially when I need to remember why I did something. Unfortunately, that information gets lost if I forget.

On the whole, I think restructuring is good (I haven't always felt this way), but something is lost in the process.

Re:Please use git pull --rebase by sanderjd on Tuesday April 30, 2013 @10:25AM (#5632331)
Feature branches, merge commits, and small (possibly broken!) commits are all better documentation of the process of developing a feature than big "cleaned up" commits.
Re:Please use git pull --rebase by turtlepower on Monday April 29, 2013 @11:46PM (#5630315)
In this case I'd like to be able to revert the merge.
Re:Please use git pull --rebase by manojlds on Monday April 29, 2013 @10:29PM (#5630115)
No feature branches as in NO feature branches and use feature flags / toggles instead - http://martinfowler.com/bliki/FeatureToggle.html
Re:Please use git pull --rebase by mh- on Monday April 29, 2013 @11:51PM (#5630332)
Feature branches and feature flags are orthogonal.

I have no idea how toggles could negate the need for isolated development branches on an 'important' codebase with multiple contributors working on the same areas of concern.

Re:Please use git pull --rebase by benjiweber on Tuesday April 30, 2013 @01:03AM (#5630501)
It is certainly possible to avoid feature branches with multiple contributors working on the same areas. We've even been pretty successful performing major refactorings to substantial codebases in this way.

The key is to do continuous integration properly - i.e. actually integrate your changes with the rest of the team several times a day. We actually deploy to production several times of day. This requires you to break down changes into very small steps that can be completed, tested, and deployed in an hour or so.

Each small change is far less likely to break something, or cause performance degradation. If it does, then you know exactly what caused it without painful debugging. Each small change is unlikely to cause significant merge pain for the rest of the team.

This requires you to have excellent automated testing and rapid <5min deploys.

There are also tools like branch by abstraction and feature toggles which can help but are only tools. The key is how you work as a team.

Feature branches are another way of working. They may be the only way of working in many cases (e.g. distributed team of sporadic contributors). Feature branches are almost the opposite of continuous integration. By definition changes on the branch are not integrated.

Re:Please use git pull --rebase by draebek on Monday April 29, 2013 @10:52PM (#5630191)
Re:Please use git pull --rebase by dmead on Tuesday April 30, 2013 @04:24AM (#5630975)
hi dustin!