Rebase workflows are awful and unintuitive. Leave the rebasing to the git wizards who actually know what they're doing, in no circumstances should this be part of your day-to-day work.
Rebase workflows are awful and unintuitive. Leave the rebasing to the git wizards who actually know what they're doing, in no circumstances should this be part of your day-to-day work.
This sounds like the refrain of someone who doesn't want to actually learn how one of the most fundamental tools of their profession works. I realize that git wasn't the optimal choice for the industry to settle on, but it's what we picked, and simply avoiding a feature that a majority (65%) of your peers use to at least some degree [0] will hamper your professional development.
Learn git. It's not pretty, but it's what we've got, and it's not going anywhere anytime soon.
The reality is that most people work on their private branches, alone. In that case it makes almost no difference if you rebase or merge. In almost any other scenario, merging still works as expected, while rebasing without understanding git will almost definitely lead to losing work and spending an absurd amount of time resolving conflicts. Why would you want to inflict that on yourself? Just use the approach that always works instead.
Learning Git really isn't high on the priority list for most developers, as they know what they need to use to get stuff done. The complexity gets really high really fast, so it's quite understandable why most people treat Git like DNS or other infrastructure - it's there, I know the basics to get stuff done and if anything goes wrong I ask an expert to take a look. And guess what? There is NOTHING wrong with that.
I'm well aware about the differing meaning of HEAD in merge and rebase, and if I had to think about it, would probably realize that it makes sense to always display HEAD first. And that as a consequence, the order would be swapped.
But I would definitely have answered "no" to the question as written.
I absolutely do. Every lead I've ever worked with absolutely does. If you merge an unnecessarily big commit to master, you are potentially making life very difficult in the future.
If you make a meandering series of commits during development, squash them for the PR. But please, please do not squash the entire feature upon merge.
Also, I'm not sure how rebase could be confusing except in the case where there are multiple commits with big conflicts, but that's rare, and you can make exceptions if the developer is really that unsure with git in those rare cases (or ask for help).
> If you make a meandering series of commits during development, squash them for the PR. But please, please do not squash the entire feature upon merge.
I typically turn my PRs into a series of buildable and testable commits. I also put a lot of work into making those commits tell a useful story to the reviewer and to anyone doing git blame later, and squashing them all into one commit undoes that work.
Does your CI test each individual commit? Afaik most of them only test the top commit. How do you know/enforce that all the inbetween commits also build/pass tests?
How do you know how many commits to revert, if you need to revert the feature? Instead of reverting 1, now you have to revert N where N is not recorded anywhere.
Because they can explain their individual rationales, while still making the most sense to merge all together.
> What can you possibly learn from that that you can't get from looking at the entire diff the PR is introducing?
Ease of review (both before merge, and in the future when wondering why something was done a certain way). Saves me as a reviewer from having to guess which parts of the commit are meant to do what.
This, of course, means that every commit needs to be a reasonable change in itself -- fixup commits done while developing should be squashed into the original change with a local rebase (these are the "meandering" commits your parent post mentioned).
> How do you know/enforce that all the inbetween commits also build/pass tests?
I'm no CI expert, but I would hope that most systems allow this as an option.
> How do you know how many commits to revert, if you need to revert the feature? Instead of reverting 1, now you have to revert N where N is not recorded anywhere.
It's recorded in the merge, assuming you always make a merge commit.
Otherwise, since each commit is actually its own logical change, you figure it out the same way as you would figure it out in the "squash PR" model -- bisect to find it, then see if reverting it helps.
If the extra “noise” bothers you you can use —-first parent with git log.
Hard disagree. I hardly consider myself a "rebase wizard," but I've been a near-exclusive practitioner of rebase workflows since I can remember. I find rebasing much more intuitive than workflows with merge commits. Squash merges are fine, but with proper intuition, they appear like a special case of rebase.
In my experience, the resistance to rebasing comes down to fears about "rewriting history" and false intuitions about how git works. I usually allay the former by pointing out that squash merges - which almost everyone approves of - also rewrite history. The latter issue seems to arise from arrows in popular git visualizations pointing in the wrong direction, e.g. in Gitflow.[0] In git, the child commit points to its parent, because each node is immutable. The git data structures are extremely simple (hence why git is so named), consisting of blobs, trees, commits, tags and references. Once you understand how these work in practice, rebase becomes intuitive.[1][2]
IMO, the only thing unintuitive about git is the CLI. Translating the graph operation I want into the commands is sometimes a challenge. Maybe that makes me a (frustrated) wizard after all?
[0] https://nvie.com/img/git-model@2x.png
[1] https://speakerdeck.com/pbhogan/power-your-workflow-with-git...
[2] https://eagain.net/articles/git-for-computer-scientists/
There is 'git bisect' which only gives you detailed answers if your commit history is as fine-grained as possible while still being compileable and testable. Also, changing commit IDs on branches that are visible to others are a problem.
Which is why my approach is as follows: Work on private branches, one per feature/fix/..., then do interactive rebase to create a compilable and testable patch series out of those onto a for-review branch. While developing, rebasing onto whatever public branch you want to merge with next is of course OK and necessary. When you think the feature in the for-review branch is ready, do a merge-request into the public target (mostly devel) branch as usual, and either merge or rebase, whatever you like best.
But: Whatever branches are public are only ever merged. Never squash-merged, never rebased, never force-pushed, never filter-branched (except maybe after a court order). Because all commits on those branches are necessary to trace what people were doing with the code. All those commits and their relations are necessary for git-blame, bisect, sloccount and other things. Any commit ID there could wind up in some test binary, release ID or stuff, and you absolutely truly need those later on. And while a simple rebase might keep some of the necessary details intact (the other branch will still be there after all), only a plain merge will also preserve all the relations between the branches properly.
(Ironically, I've found that this style of development makes it less likely for bugs to be introduced in the first place.)