8 ms·
Serious question: how many times the pain of going through rebases rather than merges made a difference, or even better, really paid off in engineering terms?
by epolanski 2y ago
Serious question: how many times the pain of going through rebases rather than merges made a difference, or even better, really paid off in engineering terms?
To me it's virtually zero in seven years but it might be due to the teams and projects I've been involved with.
- hansonkd 2y agoIt always seemed like a needless complexity when you can just merge and get the same result in terms of the state of the files, just with a different commit history. The only time it might make sense if you are following some arbitrary strict style guidelines for commits. Some people care more about the commit history than others, not that either way is necessarily better.
- wakawaka28 2y agoA linear commit history is objectively better. But whether it's worth the effort to maintain is up to you to decide. If your branches don't stay unmerged for long, then you're probably better off rebasing instead of generating tons of little branches for no reason.
- hansonkd 2y agoObjectively better to what? Git usage is only one part of a wider engineering org. That like saying "bugless code is objectively better" without considering time to delivery, engineering resources, etc.
- rontdrr2 2y ago[dead]
- wakawaka28 2y agoBetter to work with of course. If you have valid reasons to have branches, such as a need to ship multiple versions, I don't have a problem with that. But day-to-day work is better done via rebasing rather than making a ton of public branches that get merged. If you know what you're doing then rebasing is just as easy as merging. As others have said, git rerere helps a lot too.
- lmm 2y ago> A linear commit history is objectively better. Disagree. You can always flatten a commit graph into a linear history if you want, but you can't restore the original commit graph from a linear history. So preserving the original history is objectively better.
- wakawaka28 2y agoThe original history is usually a bunch of garbage. If you need more detail you can rebase as many commits as you like. More detailed history is sometimes a distinct problem. Imagine trying to bisect some spaghetti bowl of commits with merges to find the source of a recurring issue. It would be relatively nonsensical compared to a clean linear history. Clean history can exist with merges, but I think merging all over the place obviously encourages messy behaviors.
- lmm 2y ago> If you need more detail you can rebase as many commits as you like. You can't rebase to get back to the original commits, not without knowing what they are. > Imagine trying to bisect some spaghetti bowl of commits with merges to find the source of a recurring issue. I do it all the time (well, less so now that I work with a better team where those issues are pretty rare), it's easy, that's the whole point of the git bisect command. > It would be relatively nonsensical compared to a clean linear history. Rebased history is much harder to bisect because you often get long chain of commits that don't compile or are otherwise broken.
- kazinator 2y agoThe linear part of the history is objectively better than if that same change were collapsed into a single patch bomb. Git rebase does not destroy history, it just does not link it together. That might be a bad thing. But the individual commits all making an appearance on the destination branch is a good thing. From those who favor merge, what is bad is that there are no second parent pointers tracking where those changes came from. This coulid be obtained by reimplementing git rebase as a sequence of merges. Git rebase is a sequence of zero or more cherry picks, not merges. If git rebase merged each commit instead of cherry picking, each commit would have a parent pointing to its original. In a git bisect, there would be no need to chase those second parents; you would be looking for which merged commit introduced the breakage, and not care about its original, except in some rare situations where you want to analyze more deeply what went wrong (and then that parent pointer would be a bit handy).
- nh2 2y agogit bisect. I have a friend, he thought rebasing for linear history was not worth the effort. I told him to do it, because I once had to find a regression over thousands of commits in a merge-heavy code base and it took days. He was not convinced. Then he had to find a regression. It took over a month. With git bisect's binary search, it would have taken half a day. My friend now rebases.
- samatman 2y agoI don't understand why this would make a difference. Any given snapshot has a linear history, so it should be as bisectable as the rebased equivalent. What am I missing here?
- Arelius 2y agoAgreed… I think people like to think bisect doesn’t work with merges also.
- nh2 2y ago> Any given snapshot has a linear history Not sure what you mean. The key thing of merges is that they... merge... two histories. A git history graph tool shows that clearly then. A bisection has to choose whether to go left or right.
- lmm 2y agobisect works much better with merge than it does with rebase (with rebase it's easy to end up with a long chain of commits that don't compile, so your automated bisect script doesn't work).
- nh2 2y agoOf course all your commits need to compile and pass tests. It didn't even occur to me that anybody would permit that in their CI. If you check in commits that don't compile then you can't use automatic bisection effectively (it still does work if that happens rarely, thanks to automatic `git bisect skip`). Of course every non-building commit will make bisecting a merge history a pain even more, not sure why you think it to be better with merges than with linear history.
- globular-toast 2y agoI think you're doing it wrong. The point of rebasing is to do it often, like every day at the very least for an active integration branch. This hopefully means you'll resolve any conflicts as soon as they happen, while it's still fresh in everyone's heads. If you rebase once right at the end then, sure, it's no different to merging.
- epolanski 2y agoI'm not doing it wrong, I'm questioning whether it's worth the effort. I have spent hours rebasing on very active branches when a merge would've taken minutes (as many colleagues do) just because "it's a best practice" but I've never got to fully appreciate the benefits.
- wakawaka28 2y agoYou don't have to keep rebasing your entire history on long-running branches. That will generate a ton of conflicts. But before you wrap it up it would be preferable for you to reduce your changes into one or a handful of stand-alone commits. If you're going to rebase often onto very active branches then you need to reduce the commits as much as possible to minimize the work involved. Ideally you could get other people to coordinate their work too. The main reason people want to rebase instead of merging is to keep the commit history from looking like a bowl of spaghetti. A commit history like that is hard to navigate, and more likely to contain a lot of frivolous edits.
- hughesjj 2y agoAlso if you use rerere you don't really spend much time doing repetitive rebases after the first rebase
- globular-toast 2y agoYou should do the squashing/fixing regularly too, not once right at the end. Again, rebasing gives you the chance to fix these things as soon as it happens, rather than deal with one massive merge conflict at the end of a long running feature branch.
- PhilipRoman 2y agoIt's a big deal when maintaining a fork. It's tempting to merge upstream commits back into your branch, but you should always rebase and keep a clean patch set in such situation.
- Arelius 2y agoI tend to agree. While I am normally super pro-merging. I agree that for maintaining a fork, the patch set style rebase workflow is preferable.
- Ferret7446 2y agoI don't understand how you are using rebase with a fork. Are you rebasing all of the changes in your fork on top of upstream? That list of changes will grow larger over time; after a year, you'd be rebasing hundreds of commits whenever you want to merge upstream.
- PhilipRoman 2y agoA friendly fork generally has a natural limit on how many commits there will be on top. Personally I've done this with ~200 feature commits and it's not a big problem (as long as you use incremental rebase of course). Of course if you're planning a hard fork, merges may be unavoidable. But I've seen too many Franken-linux-kernels which were forked from 4.x with periodic merges whose correctness is impossible to verify. Inconsistencies eventually build up with each merge.
- keybored 2y agoIt isn’t always harder than doing a merge. > really paid off in engineering terms? When you want your changes accepted by upstream and they either 1. Won’t accept a merge-filled history 2. Indirectly won’t because they accept changes by email (can’t send merges by email)
- kazinator 2y agoThe main reason they should not accept merges is that they don't care about you and your repo. In order for an upstream repo to accept your work as a git merge, they would have to fetch all your objects so that they have enough of your repo in order to represent your original branch, where the parent pointers of the merge are aimed. Nobody who is anywhere near sane wants that kind of cruft.
- keybored 2y agoI don’t understand the distinction you’re making compared to what I wrote.
- hinkley 2y agoI spend a lot of time cleaning up after people who insist there are no b problems in their code despite all evidence to the contrary. That work is easier when they haven’t squashed their changes. Because I can see how they got there and if it was a mistake or a misunderstanding. People who prefer squash are an automatic red flag because they usually don’t like asking Why, which is a very important skill on products that are shipping and making money.
- epolanski 2y agoIssues should be catched by spending time in automating tests that ensure the correct functional and non functional requirements are met not by surgically maintaining a graph of codebase snapshots. History is preserved in the branch along the PRs if needed, and it rarely is. I'm not saying that rebasing is useless (I default to it), I'm debating if the effort is worth it in engineering terms, which I generally don't see because the benefits seem to be small compared to the cost.
- rontdrr2 2y ago[dead]
- hughesjj 2y agoThis argument seems weird to me because even without rerere I found myself doing a lot more work managing merge conflicts with git merge instead of git rebase As a git merge fan, are there any tips or tricks you suggest beyond the stock git experience when doing git merge to minimize the amount of merge conflicts you get? I found it was especially bad when doing a git merge on a refactor, but I admit it could just be that I abandoned git merge earlier in my career before switching to rebase and never properly learned it My most common use cases are feature or bug branches with a lifespan between less than one day and up to one month (although I absolutely have some features on pause for even over a year, in which case interactive git rebase and partially squashing WIP commits is my current method of updating) All this is for repos from literally just me, to a few changes a month between 3 devs, to 5-2 devs doing multiple commits per day, to some open source projects with commits landing every few minutes from multiple devs if it's like a release day My current biggest issue with rebase is verified commits with GitHub and a bit of guilt for rewriting committed feedback from other authors on my PRs The only time I really use git merge is when I want to see how my work interplays with more than one feature branch at once, or if the feature branch I want to integrate hasn't rebases themselves in a bit and conflicts occur
- jjmarr 2y agoI was on a team where we wrote software tests for computer hardware. Regressions were frequent. The underlying hardware wasn't very reliable because it was all very early-stage and hadn't been tested yet (as it was our job to write the tests in the first place). The linear commit history created by rebasing made it trivial to bisect and determine what introduced the problem. Huge difference to my productivity.
- Arelius 2y agoDid you ever try bisection without the linear history to compare? Or was this just conjecture?
- kazinator 2y agoI have. It was a complete fucking shitshow. In a kernel tree, doing a git bisect with the messy merge history will take you on a wild goose chase, where you land in some branch developed by an entirely different team somewhere, working on totally different hardware from you, with a different kernel version, which you have no hope of building and booting.
- Arelius 2y agoHmm, as I think about this, I'm unconvincing it's specifically a problem with merges specifically. If you were bisecting a rebase workflow and hit a block of commits that were unbuildable and unbootable close to your breakage, I'm unsure how you would progress. But the case is likely better in the merge workflow, since in all likelihood you could mark the entire tree as good, and it could stop searching all ancestors. Which is far more likely to be correct in a merge workflow. I feel like it's most likely that bisecting the linux kernel was in-fact the shotshow. Edit: upon further research, it appears that git bisect is a commonly used and useful tool in the kernel, and the correct response to landing in that branch would be `git bisect skip` which should be far more informative to the algorithm then a skip in a linear history https://nathanchance.dev/posts/working-with-git-bisect/ https://nathanchance.dev/posts/working-with-git-bisect/
- 2y ago
- Arelius 2y agoI think no. It’s the same compulsion that leads to bike shedding in code review. And honestly, there are far too many engineers that use rebase without understanding the underlying system which is dangerous in git. (Aside, I wish git would adopt hg’s stages)
- kazinator 2y agoThis branch discussion doesn't speak to the present topic (much). Merging involves rebasing, possibly requiring conflict resolution. Merge versus rebase is just git speak for two different ways of tracking things when diverging streams recombine. In a nutshell, merge creates a single new commit which brings all the cumulative changes from a source branch onto the target. The commit has two parents: the prior commit on the destination branch and the commits on the source branch. Rebase creates a new commit out of every individual commit on the branch, bringing them individually into the target branch, much as if they were being merged. However, they have only one parent: their target branch lineage. (Rebasing is way better from a conflict point of view because the changes are individually brought in. A merge creates a "patch bomb" on the destination branch in which serveral totally unrelated conflicts might have been resolved, pertaining to different commits in the original.)
- ajkjk 2y agoI frickin love rebase-only linear history. It just feels so clean. It's so much easier to understand what happened if you're just scanning the commit history. I also don't know of any pain to it, though. It's just simple and easy and clean.
- einsteinx2 2y agoMaybe it’s just the codebases I work on, but I’ve never found rebasing to be particularly painful. No more painful than merges anyway. Both have the potential for conflicts and those conflicts are resolved in a similar way. I’m genuinely curious what pain you’re referring to here that would make it not worth using rebase vs merge commits.