In honor of my new license plate, I decided I wanted to do a quick, little post on rebase vs merge, how each one works, and how I choose to use eac...
For further actions, you may consider blocking this person and/or reporting abuse
Ah, the venomous arguments about trivial things...
On this particular topic, my preference is not to rewrite public history. Rebasing a feature branch that's already on the remote seems wrong to me, so at that point I will always merge master into it. However locally I will rebase most of the time, for all the reasons you outlined here.
Which leads into my example - to squash or not to squash. I've worked with people that think every merge should have a single commit. And others that are just as adamant that you should never rewrite history and every commit should be left the way it was created.
Similar to my merge/rebase preference, I will cleanup my messy local commits by squashing them before pushing. Often I won't squash though because I think the commits are separate things and if I need to revert later on I can be more selective. But what I won't do is squash corrective commits with original commits. If I get feedback on a PR and then I incorporate it I want that history to be preserved. Bizarrely to me, there are some of the 'there shall only be one' committers' who would re-write their branch commits so that changes made after feedback would be incorporated into the same commit as their original changes. They say it's cleaner - to me it's like lying about your work.
The real question is what do you want to get out of your history?
To me history is the why. I like to use the example of undo trees, seen in emacs and vim, these could be view as in memory commits. They have branching and timestamps, but limited in scope to a single file.
The reality is, this isn't the history people keep. They work and craft out a spot they believe is complete. Or they adhere to someone commit twice a day rule. Either way the history is not real.
There are specific tools which make use of history.
bisect
which searches for a commit.blame
which describes a file based on its makeup of commits.revert
which is the 'undo' of git,cherry-pick
the copy/paste of git. I want to build out a history which maximize the usefulness of these tools.Git also provides the tools to help with that, staging area, commit --fixup, rebase -i, and more. Fixup is great for code reviews while allowing for quick cleanup before merging.
Yes it doesn't matter, unless your goals line up with mine.
Regarding squashed changes for me the answer is simple: on larger projects squash, on smaller projects don't. Reason being is on smaller projects having the complete history right there is useful. On larger ones you'll be forced to scroll through dozens, hundreds or even thousands of commits to find even a relatively recent change. No-one wants to do that.
Regarding venomous arguments over trivia seems to me there are a few reasons for this.
The first is that sometimes seeming trivia really does matter.
The second is that some devs lack empathy and can't understand other's preferences.
Following on from these, to non-techies the one can look very much like the other.
Bad devs will often argue personal points on genuine trivia because it makes things nicer for them personally, and since there are likely few real world consequences they don't have to worry about being wrong. Or they just can't tell the difference...
Good and great devs will often still argue trivia for the reason outlined: non-techies and bad devs often can't tell the difference and being seen to be knowledgeable in general can establish them in a position where they can improve the project as a whole, rather than deferring to bad or mediocre devs who would create an inferior product.
Good call on squash or not to squash argument! That always gets our devs going at Kenna lol
The real argument is about what history is and how to preserve it. It's NOT the minutiae; It's the narrative of what the commit does when applied. So
rebase -i
to craft that narrative! Orgit commit --amend
s. Remember that git is collaboration tool too.Keeping a history littered with 'add new comment'-like goo should be squashed and never be in Master. Also, It's almost pointless to merge a single squashed commit to master.
So, If you're pro Master branch merge commits, it best to have a crystal clear rational/strategy as to why you need to keep and share that commit history as the product dev proceeds. Otherwise it's goo.
I'm for a linear history with rare merge commits.
The app I'm working on has rebasing ENFORCED!
This is achieved by blocking pushes on a subtask branch if it is behind it's feature branch. (Development is done on subbranches, testing is done on feature branches, and code review happens in the PR between the two.) Git remote actually responds with the exact commands you need to run in order to get up to speed.
This works pretty well because everyone does it, and our history is just so pretty 🙄.
My biggest beef with this is that it messes with my code review process: The way I work is I review all the code, and if I find issues I comment on them, and decline the PR. The developer then makes the necessary changes, pushes new commits and reopens the PR. At this point I don't want to review all the code. I want to review the new commits only. But since it was rebased, it's hard to find the new changes (and don't get me started on squashed commits).
The integrity of the hashes are also important in this case. It prevents people from perhaps using shortcuts that would of otherwise not been approved in the standard process.
Another issue is that when conflicts are resolved by a different developer, the commit still has the original developers name on it, Which just confuses them.
So as long as no one else involved in a branch, rebase and squash away (YOLO), but please don't enforce it.
In my initial years doing web development, something weird that used to happen to the team was that sometimes when doing
git merge
changes would go missing.This caused the affected pals to be wary of git even to the point of thinking not to use it.
It wasn't until last year(Q4) that I really understood how rebasing works and why that situation happened.
So, I really agree with you that *neither rebase or merge are the right way but rebasing is the way to prevent merges that "remove" code.
How come?
Well, if two devs modify same file, same lines and Dev A pushes to master and then Dev B pulls, if it doesn't do a merge conflict git will remove Dev B changes and place Dev A ones.
This is when rebasing comes in hand because it kind of respects the commit history and moves rebased commits to the beginning/tip.
Currently, I mostly use
git merge
but when I feel that situation could happen, I go withgit rebase
.👍🏾👍🏾
No way git loses commits(!) by simply merging. That only happens if Dev B hasn't commited.
Hi Molly,
I feel excited after reading. For your opinion that rebase should be used when "feature branch needs to be updated to master" which we can make the history clean. Then there is a pathetic pain that it's really difficult for code reviewing on pull request times -- the request shall contains redundant commits from master!
Let's assume the feature branch has 3 devs working on it. My way is to assign one to hold the role for keeping that branch up to date which means he/she will fetch new commits + rebase onto master (resolving conflicts if there is) and then notify other 2 devs to stop pushing new commits in case of lost commits. Means everyone have to wait for the "forced push". In the end, the feature branch has code as expected and everyone can push, pull, fetch normally. The problem is it's painful to postpone every members in branch for just an updating. And what if the branch has a lot of participants like over 10 people, how can we solve this without "forced push"?
Great explanation! I was actually confused reading someone else's blog on this but yours explains it perfectly! It also explains how I've never used rebase, and why I've always gotten by with git merge haha. I will take on your suggestion to use rebase when merging master back into a feature branch.
This.
So, what I get from this article, it makes sense to rebase "downstream" and merge "upstream". I like that. I will be like Molly.
And if it doesn't work, my pragmatic nature will overcome this with ease.
Very straight forward article by the way. Thank you for that.
Very well written! Your strategy is same as the mine; also I never rebase a remote on my local branch
Thank you! I know many others have done posts on rebasing vs merging but hopefully sharing my perspective and/or explanation will help someone understand it better!
You can trust me: among all the merge vs rebase post, your is the only comprehensible!
Can't say much about rebase -- Rebase is evil. Ok, maybe not evil, maybe it's necessary given the requirements git needs to support (huge Linux repos). But history should never be forgotten, and that's what rebase does. I've been working with Fossil and prefer it.
No flames, not trying to convert anyone -- here's a comparison of the two:
fossil-scm.org/home/doc/trunk/www/...
And an article from yesterday:
theregister.co.uk/2019/12/03/githu...
Again, not trying to convert, just showing another option.
/s.
Every time I tried rebase, it screwed up my repo
So since then I stayed on merge 😅
I think I finally understood rebase. 😳
To my defense I must add, that I am working with only for a few months now, and never had the usecase for something like rebase.
Thank you so much for this super clear explanation! I’ve seen so many posts attempt to do this and fail. Also awesome custom license plate!
Sweet license plate BTW 😋
A
Thanks for sharing this way of your working ;) grabbed many things.