4 ms·
To get a commit history that makes sense. It’s not supposed to document in what order you did the work, but why and how a change was made. when I’m knee deep in
by geon 10mo ago
To get a commit history that makes sense. It’s not supposed to document in what order you did the work, but why and how a change was made. when I’m knee deep in some rewrite and realize I should have changed something else first, I can just go do that change, then come back and rebase.
And in the feature branches/merge requests, I don’t merge, only rebase. Rebasing should be the default workflow. Merging adds so many problems for no good reason.
There are use cases for merging, but not as the normal workflow.
- cluckindan 10mo agoThat is just not true. Merging is so much less work and the branch history clearly indicates when merging has happened. With rebasing, there could be a million times the branch was rebased and you would have no idea when and where something got broken by hasty conflict resolution. When conflicts happen, rebasing is equivalent to merging, just at the commit level instead of at branch level, so in the worst case, developers are met with conflict after conflict, which ends up being a confusing mental burden on less experienced devs and certainly a ”trust the process” kind of workflow for experienced ones as well.
- geon 10mo agoThe master branch never gets merged, so it is linear. Finding a bug is very simple with bisect. All commits are atomic, so the failing commit clearly shows the bug. If you want to keep track of what commits belongs to a certain pr, you can still have an empty merge commit at the end of the rebase. Gitlab will add that for you automatically. The ”hasty conflict resolution ” makes a broken merge waaaay harder to fix than a broken rebase. And rebasing makes you take care of each conflict one commit at a time, which makes it order by magnitudes easier to get them right, compared to trying to resolve them all in a single merge commit.
- cluckindan 10mo agoLinear history is nice, but it is lacking the conflict resolutions. They are never committed, and neither are the ”fix rebase” instances. Having a ”fix broken merge” commit makes it explicit that there was an issue that was fixed. Rebase sometimes seems like an attempt at saving face.
- geon 10mo agoThat’s the whole point. You do it properly, so there IS no conflict.
- cluckindan 9mo agoNo. There is a conflict during a rebase, you resolve it, and then it’s like there never was a conflict. Even if you do it properly, the workflow is erasing history of that conflict existing and needing to be resolved. It leaves no trace of what has been worked on, when, and by whom.
- geon 9mo agoCan you give an example? I think we are talking past each other. This is not my experience at all.
- cluckindan 9mo agoCreate new branch A off main. Do some work on a file, commit 1 to branch A. Meanwhile, in another branch B created off main, someone else commits changes to the same part of the same file. That other branch B gets merged to main. Now, rebase branch A onto main. The rebase stops at the commit 1 due to a conflict between main and branch A. Fix the conflict and commit. This erases commit 1 and creates new commit 1' where the conflict has never existed. History has been rewritten. Rebase successfully completes, branch A now contains different commits than previously, so it will need to be force-pushed to remote if it already exists there. The protocol has resistance against changing history. Merge branch A to main. No commit in main now contains any information that there was a conflict that was fixed. Had a pull request workflow been used, the ”merge main to A” merge commit message would detail which files were conflicting. No such commit is made when using a rebase workflow, chasing those clean fast-forward merges.
- sunshowers 10mo agoDo you know what criss-cross merges are and why they're bad?
- cluckindan 9mo agoI’m sure you’re here to educate me, but this is not about criss-cross merges between two different work branches, this is about whether it’s better to rebase a work branch onto the main branch, or to pull the changes from the main branch to the work branch.
- sunshowers 9mo agoI have an early draft of a blog post about them :) as a source control expert who built both these systems and tooling on top of them for many years, I think they're the biggest and most fundamental reason rebases/linear history are better than merges. > whether it’s better to rebase a work branch onto the main branch, or to pull the changes from the main branch to the work branch. The problem with this is that the latter has an infinitely higher chance of resulting in criss-cross merges than the former (which is 0).
- WorldMaker 9mo agoIt's definitely not 0 because rebase heavy workflows involve the rerere cache which is a minefield of per-repo hidden merge changes. You get the results of "criss-cross merges" as "ghosts" you can't easily debug because there aren't good UI tools for the rerere cache. About the best you can do is declare rerere cache bankruptcy and make sure every repo clears their rerere cache. I know that worst case isn't all that common or everyone would be scared of rebases, but I've seen it enough that I have a healthy disrespect of rebase heavy workflows and try to avoid them when given the option/in charge of choosing the tools/workflows/processes.
- sunshowers 9mo agoTo be honest I've used rebase-heavy workflows for 15 years and never used rerere, so I can't comment on that (been a happy Jujutsu user for a few years — I've always wondered what the constituency for rerere is, and I'm curious if you could tell me!) I definitely agree in general that whenever you have a cache, you have to think about cache invalidation.