51 comments

[ 3.2 ms ] story [ 104 ms ] thread
rebase for lyfe! Just don't force push on master.
I force push master when I know it's safe. If you aren't confident, don't do it. Don't piss off your coworkers. But this dogma is ridiculous.
But how can you know it's safe in a collaborative project? What if someone else merges a PR right before you push?
1. Rebase onto master.

2. Pull master just before you push.

3. If there are new commits, rebase onto master again.

If everyone on the team follows these 3 rules, it won't get too messy to untangle.

Unless I'm missing something, there's a race condition between "check if there are new commits to pull before force pushing" and "new commits come in". This workflow might work for a very small team but for a larger team it is bound to cause problems.
He may have editted his comment, but it doesnt mention `force`. As written, there is no race condition.
You've probably seen it in other comments, but if not, `--force-with-lease`
Right. As logn as you døn't force-push, then you can rebase until the problems are all gone. Although, this 3-step solution works best with proper team communication and planning.
Bluff ;) - tell them they did something wrong. It's their fault. They don't know how to use git.

There's an xkcd about this I think.

--force-with-lease instead of --force. It does the same thing as force but checks to make sure the branch hasn't changed since you fetched it. Still very likely to piss off your co-workers, though.
The problem is not if someone merges a PR before you push, but if someone branches off of the current tip of master, works on it, you remove that tip, and your colleague now is based on a history that doesn't exist, has to resolve your conflicts.
They're the same conflicts they'd have to fix if I pushed a new commit or merged a PR; assuming I made the same changes to code when I force pushed.
You can use chat. Say "@channel I need to fix to master, nobody merge for a minute".
This article has been written a million times already. It's another holy war. Vim, spaces, rebase. The sad part is that IMO merge people are on that side because they are afraid of rebase or don't understand it.
Teaching anything has to be done many times. Depending on the audience the degree of specificity that one goes into while teaching is variable. I personally read this as an attempt to teach and that teaching to be directed at newcomers to git. Nothing more.

Anyone reading something like this as a newcomer is free to go on to become an expert and for their own opinions and practices. For an experienced practitioner to read a "Tutorial" and deem it dogmatic because it doesn't adhere to their specific and experienced approach ignores the fact that the practitioner has the benefit of significant experience that a new learner does not.

> The sad part is that IMO merge people are on that side because they are afraid of rebase or don't understand it.

Not necessarily. I understand rebase, but it is often a much more complex operation than a marge, and for (often) little gain (cleaner log). So it's a tradeoff. When the team is small enough that log pollution isn't too much of an issue, it's not worth rebasing, IMO.

With all respect, I disagree. For me rebase has identical difficulty but more flexibility. You could call that "much more complex" and I can call it "just as easy but way more powerful" and we'd both be right, I suppose.

I use the rebase flow on my solo projects as well as advocate for it on large teams. Even (especially) when it's just me, having a tidy history saves me tons of time; especially when I'm prone to constant distraction by business-y things.

Edit: s/I/I'm/

Why is this downvoted? (serious question)

Where can I find the "code of conduct" for HN?

One can only speculate on why either downvotes or upvotes occur, but it's fairly safe to assume someone disagreed with something said in the comment.

The comment complains that the article provides nothing new and is feeding the rebase-vs-merge holy war. I would disagree with that, and it suggests to me the commenter didn't read the article. It's usually considered bad form to make comments on the headline without reading the article. This article in particular steers clear of all the holy war aspects of the rebase-vs-merge debate. I didn't downvote, but I speculate that's why it got downvoted.

In the HN FAQ is a link to guidelines: https://news.ycombinator.com/newsfaq.html https://news.ycombinator.com/newsguidelines.html

One of which is "Please resist commenting about being downvoted. It never does any good, and it makes boring reading." which is why you'll rarely see discussions about downvotes, and why usually speculation is all you get. ;)

Thank you for the links to guidelines. This helps.
I read it. I thought it was a blog post and not part of their guide; so I can take back the timeliness/repetitive part of my complaint.

I'm not complaining that it's feeding the holy war, just pointing out that it is one. My complaint is that we try to solve these issues with dogma, rather than expecting everyone to have a strong understanding of git, at which point all of the problems just sort of stop happening.

Then I'm another example in a long line of examples that demonstrate that speculation doesn't always produce high quality results.

I've seen the holy war too, and I was impressed that this article took special care to stay completely out of it. I didn't see any dogma at all in this case, I saw helpful suggestions educating people about git and about when to make the call.

Whatever, speculation is WAY more fun than empathy. (-:
I downvoted it because of the suggestion that the only reason anyone would be a "merge person" is because they are afraid or stupid.

It isn't helpful in any discussion to just say "side X are afraid and stupid.", and especially not without a good justification.

No-one has (I believe) ever thought "Oh wow, I didn't realise I was being afraid and/or stupid, thanks for telling me. Now I'll change sides".

You're right. I'm frustrated from years of arguing against FUD; I didn't mean to say that 100% of merge-folk are ignorant or afraid, or that none of them have well reasoned points. I should have written "I'm saddened by how often I run into staunch defenders of the merge flow who, when put to the test, can't execute the equivalent rebase" because it happens all the time.
Not sure how I feel about the not rebasing PRs rule, especially with CI on PRs becoming more common. I'd much rather have a PR get rebased than have an extra "Fix whitespace to satisfy linter" commit.
It says to merge PRs but also mentions that rebasing the branch being pulled first is a good practice. This would be a fast forward merge, effectively serving the same purpose as a rebase, no?

As for the example of a "linter" commit, I feel that lends itself more naturally to teaching git commit, git commit --amend, or rewriting history. Which the OP is not about.

Clean project history is overrated.

If you work on a sizeable team with code review before merge workflow, the tip of the repository will be moving faster than is pleasant or safe to rebase, and every so often, commits will exist in multiple different branches (in order to prevent blocking development pending a code review). You do not want to be rebasing commits such that they appear in multiple different branches with different hashes etc. It's a recipe for pain. And being blocked until code is reviewed and merged is hardly more productive.

Even working like this, git bisect works just as well to find a commit, and git log on an individual file works just as poorly as it always does (e.g. changes in merge conflict resolution are hidden by default).

Rebase if the commits only exist in your local repo. That's fine. But no more.

I totally agree. I think your code should be clean and your history should be accurate. I think as developers we're very focussed on writing clean code and documentation. We should try to write clear commit messages that relay the intention. But we shouldn't worry about adding one more commit if it makes the code better. I wrote about it in detail in http://docs.gitlab.com/ce/workflow/gitlab_flow.html#squashin... Of course rebasing is fine if you have not pushed your branch yet.

BTW some teams do prefer a rebase workflow and we want to support them in GitLab too, showing a diff with the changes in an MR if the commit was overwritten

> Clean project history is overrated.

I go back and forth on this issue.

On one hand, I like having commits that do one thing. Makes it easier to "read" a project's history, to revert things, to track down bug introductions.

On the other hand, I like having a history of the mess of how I actually implemented something, because it's more accurate and more detailed, both of which help when I go all DETECTIVE-MODE: ACTIVATE.

But on the other hand, the mess often includes such uselessly awful commit messages, and lots of terrible code that only existed for like 2 hours until I realized it was the wrong way to do it, and scrapped it. That's kind of a red earring.

So I don't really have a firm opinion on it anymore. I just go with whatever I feel that day. That said, I'm a team of 1 and have been for about 4 years, so it doesn't matter too much in my case.

> On the other hand, I like having a history of the mess of how I actually implemented something, because it's more accurate and more detailed, both of which help when I go all DETECTIVE-MODE: ACTIVATE.

The "mess of how things were implemented" has 0 value for your fellow coworkers when it comes to understanding the code and tracking down bugs.

Each and every commit should as much as possible be "atomic" with a clear message describing what was done (not the how) and why.

It is in the commit message that the developper should go on explaining their implementation decisions.

What I picture is a feature branch with multiple small commits leading to the full implementation of the feature. When comes the time to rebase and merge in master, the merge commit could include a detailed explanation of the implementation choices that were made.

  > I'm a team of 1 and have been for about 4 years
What kind of work do you do?
I work full time on a pretty standard low traffic online store web app written entirely in Clojure.
Ah! I remember you from #clojure. Been reading some Uncle Bob recently, turned on to him partly because I remember you speaking about him.
Why not rebase master into your branch, rebase your branch locally to clean it up, then merge it back into master? That way you get the best of both worlds.
I disagree, depending on your environment... it might be mission critical.

In our continuous deploy environment, we're a revert first ask questions later shop. That means when we find something wrong we revert, and that happens a lot. Since we revert so often it is ESSENTIAL that history is clean. Sometimes your code is reverted before you have a chance to be consulted. It always sucks, but if it happens you want to be sure that your change isn't only partially reverted.

But you can pretty easily revert a merge by providing the hash of the commit in master before the merge occurred. It can get tedious but it's better than risking multiple people rebasing the master branch. Another downside to doing rebase onto master is, if you don't squash, if you want to revert a rebase that's 50 commits in size, you have to go back to before the entire rebase and revert to there (or 100, 200+, that would be much more tedious and potentially error prone than reverting a merge). The only solution I can think of that doesn't have potential for rebase conflict is to make it one person's sole responsibility to rebase other branches onto master.
Rebasing isn't just about a clean project history, IMO. I'd much rather find out about a merge conflict I've created when applying a small commit to the tip of master, than when smashing two development histories together.
Absolutely. I can do without the monster-merge-from-hell (been there, done that). When rebasing is part of the established workflow, developers can rebase their feature-branches to be up-to-date with master when the time comes to offer it as a merge request (and solve any conflicts there with local knowledge of the branch). When developers are comfortable with rebasing, it is also easier to stimulate cleaning up the branch before offering it for inclusion by using interactive rebase to squash commits and edit commit messages.
There is nothing stopping you from merging the mainline history into your feature branch to pull in the latest changes. In fact you should be doing this every-so-often for any long-lived feature branch, but always before merging into the mainline.
I do integrate every so often. By fetching master and rebasing on it ;)
I quite like that this outlines the benefits of both non-judgementally, and provides guidelines about when to use each in different situations. I've seen too many discussions where people argue that one is better than the other, when as I see it, they are two different tools and they both have legitimate uses. There's a little overlap, a few cases where your own preferences can allow you to choose freely, but by and large they don't really contend with each other. You can largely have a clean and accurate history and a feature branch workflow with PRs, while using both rebasing and merging.
We've started using mercurial evolve at my company. It feels like the best of both worlds. I can rebase and get all the nice clean history I want, but under the hood the original work is still there. It also allows for safely editing public history, without getting into a weird state where you edited a commit that someone else committed on top of.
Where I work we merge with the no fast forward option - this keeps an accurate git feature topology where merges are represented as their own commit. We've found it gives us the best of best worlds: adding clarity/readability to the history while avoiding problematic rebases.

I haven't personally really noticed any downsides with that approach, can anyone else think of any?

For our (smallish, fast moving) team we disabled history rewrites on all branches on the server, have all the developers manage their git workflow using the (very awesome) osx app called gitup, and have everybody rebase and resolve conflicts before pushing. We always rebase and only merge in unusual circumstances where preserving the merge conflict resolution decisions might make sense (which almost never occurs). Everybody on our team including very junior developers and designers are able to quickly pick up this workflow and almost never have problems - and when they do it's always obvious that they should get help from someone -- and typically this is exactly the scenario where some analysis is needed -- so its a good use of time for a second pair of eyes.
I'd be interested to know how this scales on a larger team. Looking at the number of open PRs on some of our repos, I would guess doing this in a larger organization would cause an unnecessary amount of busy work when everyone scrambles to rebase after each merge.
I think it would scale pretty far based on my experience with the process on our team. I'd see more blockers to scaling team size coming more from other factors rather than the merge strategy -- things like the quality of tests and probability of problematic merge conflicts -- which I think would depend ultimately more on the code organization/team-member communication than the merge strategy.

I think Facebook uses a souped up version of this strategy (based on how I interpret their presentation on it anyway). It seems like the engineer ships off a commit, and then it goes into a review branch where it gets automatically rebased against master continuously while waiting for review. When it passes review it goes onto master as the newest commit -- if a conflict happens before the review completes or during the final rebase then the engineer is notified to resolve the conflict and push again -- I think review needs to happen again in this case -- but it makes sense to do so as the first review was done without awareness of the change that caused the conflict ... I'm sure I don't describe their actual process accurately but I think it something along these lines ...

Did anyone else to the following when they were new to git and had to rebase? 1 - Rebase. If no conflicts, great! otherwise, 2 - Abort rebase and merge.

:-)

When I started using git I remembered feeling overwhelmed by rebase because with a merge you only resolved conflicts once, whereas with a rebase you had to continually fix conflicts without knowing when it would end.

It took me a while to finally understand how rebase properly worked and I can finally use it correctly now.