I would like to comment on this:
> I have been asked countless times if it's better to merge or to rebase and while I never want to stir up a hornet's nest, I have always advocated merging over rebasing.
I've been involved in this discussion many times as well, and the correct answer is that one isn't inherently "better", and you shouldn't _always_ prefer one over the other. There are situations when a merge is preferable (e.g. to keep a branch in history), and others when a rebase is (e.g. to, well, _base_ some work on a specific commit). The choice of when to use either will depend on the author's or team's preference in each case, which is why it's given as an option in most web-based PR/MR workflows. Squashing is another task you don't want to always do either.
I partly blame this confusion on Git's UI, and on the baseless fears spread about rebasing for years, which many developers mistakenly absorbed. The amount of times I've heard that force-pushing after a rebase is "dangerous" is too high. No wonder people find it scary...
They're really not.
First of all, no data is really lost with Git. Commits can be recovered from the reflog if they haven't been garbage collected, and there are ways of recovering anything on GitHub as well[1], even if it technically shouldn't be the case.
But this aside, data loss is circumstantial, like you say. I've heard the idea that force-pushing in general is harmful, when it's really not if you're working solo or on an isolated branch. Rebasing and force-pushing are just different tools in the toolbox.
In general, my objection is to the practice of describing any software as "dangerous". It creates an air of intimidation that prevents people from using the tools to their full extent, which when spread can popularize wrong practices among new users as well. This is why you see the person in the article claiming that they've always been a "merger", having a false dilemma between merging and rebasing, and describing their solution as "fearless". This line of thinking is also commonly associated with the command line and Linux itself, and is just harmful.
Instead, users should be educated on what the software does, which does require having comprehensive UIs and documentation, and designing the software with sane defaults, fail-safes, and ways to undo any action. Git doesn't do a great job at all of these, but overall it's not so bad either. What really hurts users is spreading the wrong kind of ideas, though.
(And then I don’t think there are any more “force” flags left to worry about…!)
https://stackoverflow.com/questions/65837109/when-should-i-u...
That depends entirely on your organization's (or project's) preferred branching strategy and what is accepted as a unit of change: Some accept entire features as a single commit (via squash merging dev/feature branches - very useful when you have to maintain multiple release branches and can easily cherry-pick features & big fixes): here, merges faster advantage. Other places care a lot about the individual commits and preserving commit history from dev/feature branches - here merges can hide some of that granularity, and rebases are a better fit. The latter is common for projects with one evergreen release branch without any concern about back-porting features or fixes to other, currently supported release branches; supporting versions N, N-1, and N-2 is common in enterprise software, with each having its own release branch or tag.
To me it's virtually zero in seven years but it might be due to the teams and projects I've been involved with.
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.
That sounds like a problem with the people you work with, not with squashing in general.
>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.
This is a wild generalization. Thoughtful people squash when they think they have a set of changes that go together. If someone is jamming together stuff that does not go together then that is indeed a problem, but not a problem with squash. Nobody really wants to see the 50 edits someone made to come up with one final change.
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.
The linear commit history created by rebasing made it trivial to bisect and determine what introduced the problem.
Huge difference to my productivity.
In your situation I'd prefer merges because: if commit X used to have parent A, and you move it over to parent B, it gets a new commit hash and a version of the code that has never been tested. If that commit is broken: was it broken when the author wrote it, or did it only break when you rebased? You threw away your only means of finding out when you rewrote history.
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.
You can do that with merge just as easily though - just merge master into your branch.
> 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)
I also don't know of any pain to it, though. It's just simple and easy and clean.
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.
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.
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.)
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)
[rerere]
enabled = true
autoupdate = trueIf you want to have it forget a recorded resolution, for example because you messed something up, there are commands for that, but I use them very seldomly.
I’ve never run into any particular pitfalls to speak of. I mostly just turn it on and forget it’s there. You can still always go back in time with the reflog if needed.
Either way, even simpler, imho, than any log that one has to comb through after the fact is to create a named backup
branch=$(git branch --show-current) && git switch -c backup-${branch} && git switch -
Carry on as planned and if you bork it all, switch to the backup branch which retains the original commits and all, delete the borked one and have another go git switch backup-somebranch && git branch -D somebranch && git branch -m somebranchNote: First I thought that `ORIG_HEAD` was the thing. But that won’t work if you did `git reset` during the rebase.
(`ORIG_HEAD` is probably “original head”, not “origin head” (like the remote) that I first thought…)
[1] You just have to comb through documentation!
Dropbox doesn't have a notion of uncommitted data. Why should source control?
Pick your most important repo. Make sure everything is committed. Doing something stupid like `git reset --hard HEAD~100`. Look how fucked your work is. Do `git reset --hard HEAD@{1}`. Look at how nothing was lost.
Among its other virtues, reflog makes safe the highly empowering 'git-commit --amend'.
git rebase —ontoI don't think they are the first ones to open-source their code on a timer, but they are trying to popularize the idea.
But... have you seen who wrote this article?
Scott Chacon. If there's anyone in this world whose article would make me try a new git tool, it's him. He wrote the Pro Git book, Git Internals. Oh and cofounded GitHub. This is not argument from authority fallacy. This is "hey! this guy knows git like very very few others, it's worth listening to what he has to say".
> For better or worse, my experience as a GitHub cofounder and author of several Git books (Pro Git, etc) is that the Git commit message is a unique vector for code documentation that is highly sub-optimal.
> ...
> I don't know exactly what the answer is, but the sad truth of Git is that writing amazing documentation via commit message, for most communities, is almost entirely a waste of time. It's just too difficult to find them.