6 ms·
I have never understood the "squash a branch to one commit before merging" attitude. I prefer small commits, both during code review and later, during looking
by mbork_pl 3y ago
I have never understood the "squash a branch to one commit before merging" attitude. I prefer small commits, both during code review and later, during looking into repo history (which is needed once in a while) or bisecting.
Also, technically, "squashing to one commit before merging" is rebasing, so apparently rebasing is a normal part of your workflow, too.
That said, our discussion only confirms that Git is pretty versatile and flexible. (Of course, the UI is terrible, but Magit helps a lot in that department.)
- jkubicek 3y ago> I have never understood the "squash a branch to one commit before merging" attitude. I prefer small commits, both during code review and later, during looking into repo history (which is needed once in a while) or bisecting. I 100% agree. You don't have to make massive feature branches for your changes. If your feature branch is huge, it's a sign that you probably should be breaking your work up into smaller chunks. > Also, technically, "squashing to one commit before merging" is rebasing, so apparently rebasing is a normal part of your workflow, too. Yeah, I know ¯\_(ツ)_/¯ This gets brought up every time I have this discussion, and it's correct, but also a little misleading. Squash-merges are never going to be any more challenging to make than regular old merges. Rebase conflicts are where people run into real trouble.
- yencabulator 3y agoYou can get merge conflicts just as well as rebase conflicts. Especially for squash merges, which really are rebases.
- jkubicek 3y agoThat's true, but merge conflicts are the easiest possible conflicts to resolve. Main branch and my branch both changed this line, no matter what, you must resolve that conflict. Rebase conflicts might be just as easy or they might be an order of magnitude more complex and confusing. They'll never be easier than a merge conflict.
- ChrisSD 3y agoI'm not sure I understand. Why would rebasing ever be more complicated? They're the same thing at the end of the day, no? Main branch and my branch both changed this line no matter what, you must resolve that conflict.
- jkubicek 3y agoImage you have a feature branch where you changed a block of code two times and are rebasing that branch onto main, where that block of code was also changed. During the rebase, you'll need to resolve that conflict twice. If you had merged main into your branch you would only have to resolve it once. No matter how complex your branch gets or how much it diverges from main, you'll only ever need to resolve a conflict once. For rebasing you may need to resolve conflicts multiple times for changes you may have made hours/days/weeks ago. If you're strict about rebasing and keeping your working branch clean and remembering what you were doing in that commit from three weeks ago the rebase process might not be that bad, but it can never be easier than a merge. Rebase conflicts are like short-selling stocks; there's no upper limit on how bad it can get.
- IlliOnato 3y agoIt seems there are 2 types of rebases involved here. I never rebase a feature branch on top of the changes in the main branch. The branching point of a branch always stays the same. But I use rebase for editing commits in my feature branch all the time, i.e. I rebase interactively one feature-branch commit on top of another feature-branch commit.
- seba_dos1 3y agoMerge conflicts are often much harder to resolve than rebase conflicts. I often find myself going through individual commits in order to understand how to resolve such conflict anyway, which rebase does for me automatically (especially with diff3), providing enough context right away. In many cases, it's much simpler to follow the changes step-by-step. Sometimes I even ended up resolving merge conflicts by rebasing and then rewinding back and committing the resulting state as a merge. It was easier that way. Sure, there are cases where rebasing naively gets super annoying as each commit conflicts on cherry picking, but you can end up with pretty nightmarish merges just as well if you're not careful.
- samus 3y agoRebase conflicts are just the dual to merge conflicts. Instead of applying the end result of my work, I apply my work step by step. I don't see the final big picture, but move towards it. This is of course a nightmare if the branch is long-running, because then it becomes easy to forget what I was thinking and doing when making the first few commits. But this is where organizing and crafting good commits (good commit messages are just the beginning), and frequent rebases on top of the source branch help. Frequent rebasing also makes it possible to start working on a feature that depends on somebody else's in-progress work. It works best if the other person also frequently commits, publishes and rebases their work to keep the trouble with rebasing to a minimum. Git serves many kinds of dealing with concurrent activities in other branches well. Maybe too well :-)
- jrockway 3y agoBecause the evolution of the topic branch is largely irrelevant to future analysis. If you write tests firsts, then you have a commit in the repo where tests can never pass; fun for bisecting. If you write the code first, then you have a commit with a bunch of dead code in it because the tests appear in the next commit. I would say that my average topic branch looks like: "edit the protos and rebuild them", "add feature", "add tests", "add CLI", "fix lint". There is no value in checking that into the main history in that order; the first commit doesn't compile because the API servers don't implement the API server interface anymore. The second commit is a bunch of dead code. The third commit is somewhat useful except the code doesn't follow the style guide and static checks fail. The fourth commit at least un-deadifies the code; something calls it now. The last commit is something that can be checked in. I really see no value in preserving that history; the set of commits makes more sense as one commit. You could redo this to "edit the protos, and rebuild them, and add stubs that return Unimplemented", "add feature and tests to replace the stubs that return Unimplemented", "add CLI binding", which could stand alone if you felt like it. It is more work for the author, though, because you had to write code that you are literally going to delete in the next commit. Why bother? Personally, when I'm reviewing code, the more context I have, the better. If there is a design doc for the feature and someone sends me just the protos that they describe in the design doc and the design doc is actually good, fine. I got the context and this just speeds things along. If there isn't, how do I know this API is even right? If I see how it's implemented across the client and the server, then it's easy to make suggestions for improvement. If it's just the API, it sounds right, but I don't know if you can actually implement that feature until I see it done, right? More importantly, how do I know this set of 3 patches isn't going to be followed by "oops, forgot this in the protos", "oops, forgot this in the server", "oops, forgot this in the tests", and "oops, forgot this in the CLI"? Now we've turned one commit into 8. Why? Because "small PRs are good"? Prove it. I had to do 8 code reviews instead of 1. You had to write code that you're literally deleting the commit after you added it. Why bother? I'm unconvinced that the history of "do it", "oops fix it" is more useful when doing archaeology than "do it right the first time".
- jkubicek 3y ago> You had to write code that you're literally deleting the commit after you added it. Why bother? I'm unconvinced that the history of "do it", "oops fix it" is more useful when doing archaeology than "do it right the first time". My suspicion is that people are using rebasing to clean up their prior commits as they go instead of just getting everything working and then breaking the work up into commits, if needed. And this is also how they work themselves into horrible knots trying to figure out what they did to hose their branch.