5 ms·
> The number of times I got stuck fixing (mine and other people's) git issues is way more than seems necessary. I almost never have any issues with git, I wond
by jkubicek 3y ago
> The number of times I got stuck fixing (mine and other people's) git issues is way more than seems necessary.
I almost never have any issues with git, I wonder if you're working differently than I do?
> I have not used a merge at a workplace for so long that I forget how it works, because rebases make so much more sense.
Oh, that's the reason.
I've been using git almost as long as github.com has been a thing and I'm convinced that if you find yourself rebasing, _especially_ if rebasing is a normal part of your workflow, you're using git wrong.
Here's how I work:
1. All development is on a features branch
2. Feature branches are tight and focused
3. Frequent merges from `main` to stay up-to-date
4. Squash your branch into a single commit before merging
This gets you everything you want from source control (linear history of well-structured atomic changes) without any of the gymnastic skills necessary to be a competent rebaser.
Oh, and I never get stuck fixing weird issues, because it's impossible for me to generate weird issues. The worst thing I encounter is a merge conflict, and merge conflicts are the easiest possible conflicts to resolve.
- happytoexplain 3y agoI have to disagree with #4. If your branch's commit history is unnecessarily fragmented because it evolved as you worked, then yes, squash those commits - but "one commit per feature" as a rule doesn't work for many kinds of features which by their nature can be made only so "tight and focused". Sometimes it's an undue burden to have to view a feature's patch as a single diff, even if the feature is functionally as atomic as it can get.
- jkubicek 3y agoFirst, my feature branch commit history is always fragmented and unusable. I commit extremely liberally, every few minutes if I'm actively making changes. Why not? If I always squash before I merge, nobody seems my junk, and being able to back up a few steps after coding down the wrong path is super useful. Second, if I do create a feature that should be multiple commits for clarity, I find it a lot easier to do all my work in a scratch feature branch, get everything working correctly, tests passing, etc., then do a `git merge --no-commit` onto my final feature branch for the PR. At that point I can break my work up into a few different commits, as necessary.
- yencabulator 3y agoMaybe consider you're just a messy person, and don't extrapolate from that to "if rebasing is a normal part of your workflow, you're using git wrong". For me, rebasing is the means by which I keep my development branch neat and tidy. Each commit changes one thing. It's easy to see what's "prep work" and what's the ultimate change of functionality. Git bisect can find the commit that caused a bug. And so on. I view squash merges largely used as a crutch to hide bad habits. I find the resulting history from lots of squash merges is not useful in figuring out why a change was made; by that time the specific change is part of a big ball of mud with a very vague high-level goal.
- jkubicek 3y ago> Maybe consider you're just a messy person, and don't extrapolate from that to "if rebasing is a normal part of your workflow, you're using git wrong". Possibly? But I also find it hard to believe that there's this many developers out there typing out perfect code on the first try with no mistakes or false starts. > I find the resulting history from lots of squash merges is not useful in figuring out why a change was made; by that time the specific change is part of a big ball of mud with a very vague high-level goal. That's the developer's fault though. If someone is lazy enough to squash-merge a big ball of mud onto the main branch, they would also be lazy enough to generate a commit history filled with barely working and unclear commits, or incompetent enough to completely hose themselves with a rebase. At the end of the day, I'm generating the same set of small, atomic commits as you. The difference is that I don't spend any time worrying about what the commit history looks like while I'm coding. It's only at the last second before sharing a PR that I consider it. 95% of the time I've got a tight one-commit PR containing a little code, a few docs, a few tests. Sometimes I break my changes into separate PRs, very rarely I'll add multiple commits to a single PR, but those aren't my default workflows.
- jimbobimbo 3y ago"Messy" and "tidy" is not something I'd expect to see in the conversation about private branches. Version control in the private branch is a tool which helps me maintain state and go back and forward in time. It looks exactly like I thought about the code or work I needed to do at some point in time. It is not messy or tidy, it's just what it is. I don't have to please anyone's sensibilities when I'm in the private branch. The merge into main is squashed and atomic, of course.
- mbork_pl 3y agoI 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.
- dasil003 3y agoDisagree pretty strongly about rebasing. If you are an experienced and full-time programmer then you should know how to rebase and merge, and understand when the time and place is for each one, and I personally always rebase my local topic branches. I understand this is a bit subjective and may depend on local context, but essentially my view is this: When you merge, conflicts are resolved for a large number of independent commits all at once and crammed into a potentially large blackbox commit that is not directly related to either the work on main or your topic branch. When a developer makes a mistake in that merge (which happens often), it's hard to reason about their mental state and whether they fully grokked the state both both branches. Even worse is when there is a logical conflict, but the lines aren't near each other, so git just happily merges. By contrast, when you rebase, you are essentially going through the exercise of updating your commits for the current state of the world, and each conflict is resolved locally to where it was authored, including completely removing things that no longer make sense. The result is fully bisectable, and this property can be preserved along with the ability to see original author and merge times with existing timestamps and merging to main with the -no-ff flag. Obviously this requires some expertise with git, but it's not very difficult once you get the hang of it, and in fact leads to more disciplined thinking about how your changes will roll out. WRT to squashing, I think the value depends on the scale of the team and codebase you're working for. The larger it is, the more squashed you want things for posterity. However for small teams, as long as you keep CI building, finer grained history can be useful. This also depends on the size of your feature branches and deploy cadence, so YMMV.
- aidos 3y agoIt’s irrational, but I always stand on the sidelines of these conversations being a little bit cross that people slag off rebasing. At some point someone pointed out that rebasing changed the history and if you change the history of a public branch everyone was going to have a bad time. That got turned into “rebasing is bad” and now people keep rolling it out the same old trope. It’s a tool, and a good one for managing your work. If you don’t know how to use it then you’re doing yourself a disservice. In terms of squashing, my rule is that I squint at the PR and if the commits are going to have value in a years time then I’ll merge commit otherwise I’ll squash. In 10 years of running my codebase I’ve never blamed and thought to myself “I wish there were more fine grained commits here” so it’s obviously working fine for me. As you say, do what works for your team but make sure you understand the tools and what they provide for you.
- vvpan 3y agoI pretty much only work in the context of teams. My own git skills matter quiet little - there are many other people of various skill levels who are working on the same codebase. Junior developers get very easily confused by git.