12
jiraTicket
283d

Merge VS Rebase:
- Did you pick a side?
- Practical tips? Like dealing with merge conflicts
- Have you ever regretted using either?

My answer
* My team squash-merges all branches to master so we don't really care what the branch history looks like. Master history should be pretty - but a branch history can be ugly and filled with a dozen commits.
* Practical tip 1: use `git config rerere.enabled true`. rerere stands for "reuse recorded resolution" and this means if you rebase often you don't have to resolve the same merge conflict twice.
* Practical tip 2: use `git commit --fixup oldcommithash` and then rebase with `--autosquash`
* I like using Rebase. But I have regretted the amount of time I've spent on trying to rebase old branches with many commits only to give up and to `git rebase --abort` since I realised I couldn't handle trying to reapply all the commits chronogically as the changes in the 1st commit were no longer relevant.

Comments
  • 6
    I just merge.

    The amount of time engineers spend dicking about with rebase strategies to keep commit history clean only makes sense if you're looking at the git log often. And quite frankly, I don't think 99% of us do.

    I'm optimizing for write performance over read performance on this one.
  • 2
    @lungdart I thought I was the only one with that attitude lol. I too rarely look all that deeply at the history or logs, I think if you really have to, somethings wrong. I just merge and move on. At that point my brain is too tired to think about how to push my changes
  • 3
    @lungdart Yeah, I agree, 99% should care less about git history. The most common arguments I see about Merge vs Rebase are from devs in scenarios which are relatively niche: like working in a huge complex codebase with huge amounts of contributors where old bugs are often found months later - so they optimize for being able to use `git bisect` to track down the exact commit that caused a bug. (which is sometimes and argument for "never rewrite history!")

    I've never really had that problem working in smaller teams of <10 devs.
  • 4
    History should not be pretty, it should be the truth. Rebase is for people who can't handle the dirty reality.
  • 0
    I could certainly Google or GPT this but I’ll ask here since we’re discussing it. If you want to know how many commits a contributor has made over a period of time, doesn’t squashing kind of "erase" part of the history? Maybe the guy spent a week working on a branch and made 10 commits. Once squash-merged to master (or main, or whatever you call it), won’t there just be one commit shown in history for all the dude's work on the feature branch?
    In my company they kind of like "monitoring" people’s activity by looking at the amount of commits they make. So squashing may not work for this
  • 1
    I like rebase and commit --amend.
    Sometimes a task includes independent commit steps, like updates or fixes in some other parts of the codebase, that should have their own commits in the master branch.
  • 3
    When I look for logs, I go to the pull request that introduced the change, because that's where the discussion took place.
  • 1
    Rebase should always be first.

    I’ll try not to get mad, but what is the purpose of using git when you don’t give a fuck about the history? Why even track changes to files if you don’t ever plan to look at the changes themselves? Have u ever thought more about actually using git as a tool rather than something you “have to use”. Argggg
  • 3
    Yep, history should be clean when it comes to main/master. Squash merge is good when your maintaining the release notes so that the exact change can be back track using the closed PRs
  • 4
    I prefere rebase before merge since in the case of merge conflict its easier to solve and if you change logic, getting changes intermixed can make it harder to follow.

    Most times it does not matter no, but on the occasions it does having all commits fresh at the end helps.

    If you merge often the problem is very much reduced, and in a small team the same. But with 10 devs that could end up poking around in the same file it can be a mess (we are refactoring your reduce the risk of multiple changes to the same file but in the process the risk is higher until we are done )
  • 1
    @Voxera plus too if u have a merge rat king nest of PRs into one branch from a bunch of goofballs on the team, and you have to revert a feature, chances are it’s going to be a nightmare compared to if the team tended to favor rebasing work in an easy to rewind linear chain of commits.
  • 7
    @black-kite monitoring the amount of commits a developer makes is roughly the same as counting code lines as a performance metric.
    It's stupid and in no way an indication of what the developer truly did, his thought process, etc.
    Like the age old joke:
    An engineer comes to fix a machine, replaces a screw and bills high. The manager asks for a breakdown and gets the following:
    Replacing the screw:5$
    Knowing which screw to replace: 1000$
  • 6
    if you "pick a side", you're doing it wrong.

    they're both different tools for different purposes. like a knife and a saw.
  • 1
    @tosensei yeah exactly. Both tools coexist for a reason, bc either would be great for certain situations and cause problems/be a pain in the ass in others
  • 2
    @aviophille if you need to revert, deploy an old artifact.

    If you need to hot fix, merge a hot fix in.
  • 3
    @shovethisrant I've been developing for 25 years. I've used emailing files, ftp, cvs, svn, and git.

    I've only needed to revert commits while using version control half a dozen times.

    Git is the best, but it's a bit more complicated than the majority devs truly need IMO. I'm sure some big open source projects make use of its more esoteric features, but the majority of small corporate teams (<15 devs) working on multiple projects just don't need them.
  • 0
    @m144 100% agree with you, but that doesn’t answer my question.
  • 0
    @black-kite to answer your question, it depends. Squashing also contains all hashes and commit messages that were squashed, if done right. So to comply with this idiotic check, you would just ask the company to check the number of hashes in this squashed commit.
  • 1
    @koes "History should not be pretty, it should be the truth"

    Agree in some ways. If I'm working on a feature-branch I don't feel the need to prettify history. But merging it to master is a different thing for me.

    An example: let's say I have a branch called "Implement Video player". The plan was to have a Play-button and a Volume-button. But then we decided to remove the Volume button. The history might look like this

    * feb 4 - Remove Volume-button

    * feb 4 - Fix lint errors

    * feb 3 - Change Volume-button icon

    * feb 3 - Style Video border

    * feb 2 - Change Play-button icon

    * feb 2 - Add Volume-button

    * feb 1 - Video component - initial commit

    When merging this branch to master I'd do "Squash and merge" cause it's beneficial not to have commits in master referencing a Volume button that ended up never being used.

    Allthough I wouldn't waste time manually squash commits within the feature-branch
  • 0
    @tosensei Yeah, I'll admit I wrote it like that to fire up the debate - and see if there were any fanatics saying "always do X, never do Y"

    And I realise I was unclear.

    But I was mainly thinking about working in feature-branches and asking if people prefer rebasing on master, or merging master into their feature-branch
  • 0
    @aviophille I don't think he means he never looks at git logs, just that the prettyness of git commit messages etc might not be as critical as we imagine. Some will just 'git bisect' their way to find the issue and don't necessarily even read commit messages

    (Personally I don't, just sayin)
  • 1
    About Reverting and tracking bugs: for me I find that most of the time bugs are introduced as part of a feature-branch, and even if the author of the branch wrote isolated commits it's often hard to just remove the buggy commit and and keep the rest. If there's an urgent problem you often have to revert the entire feature and then look into how to fix it.

    One reason I prefer that feature-branches are squashed into master as 1 commit is that it makes it dead simple to revert them.

    One reason I prefer that feature-branches keep their history (and not manually prettify it before merging the entire feature to master) is that it's easy to browse their commit history and see where a mistake was made
  • 2
    If you squash all merges to master you loose code archeology data such as indications of the code author's intent when writing the shitty code.

    When I'm working in legacy I wanna get as many hints as I can
  • 1
    @MammaNeedHummus I rarely squash commits, I do rebase so all commits are in order.

    Squash is mainly used to remove nonsensical commits, like fixes that are fund before merging that serve no purpose in the main log or when you need to pause a branch for some reason and then resume.
  • 2
    @Voxera meh even then who actually reads the commit history like a timeline - the only places you do look at commits is during release fuck ups (which is only last few commits) and during code archeology (which is usually only interested in select a few commits).

    It feels like we're trying to solve a problem here that's not a problem.

    The bigger issues that are really getting Devs and development speed down are where I want to spend my time and my team's time fixing - not catering to aesthetic sugar.

    (Note: I am a fan of atomic commits and purposeful commit messages to aid with PR reviews, easy to drop changes, and future dev's archeology)
  • 2
    @MammaNeedHummus yeah, I rarely look at history unless something REALLY bad happens where we REALLY have to revert a change. And you REALLY shouldn’t have to be doing this often if things are tested adequately and if the requirements aren’t changing a shit ton.
  • 1
    If reverting is a normal thing, somethings WRONG. Shit planning and testing leads to that
  • 1
    @MammaNeedHummus Most mergers are single comits and if no one else messed with the same file a plain merge is enough.

    But whenever a merge has more than one comit I think a quick rebase not only makes sure any merge conflicts are handled locally in the branch and not during the actual merger reducing the risk of an error leaking into some other branch.

    It also makes sure that if we fo need to pull the merge we do not have all comits in one place.

    Its rare yes, but rebasing is also usually very fast.

    The only time it takes more time is if there are merge conflicts and thats also where its most useful, so its an easy guard I at least feel is worth the time.

    Squashing is not enforced but rather up to the dev but if they do I always ask them to keep any commits with relevant messages.

    That also helps in case someone else get a merge conflict.

    Especially as the blame feature makes it very clear why a certain line was changed and when.

    But as long as the team find a solution they feel works I think that is fine.
  • 1
    @TeachMeCode I disagree you can't plan everything up front, sometimes you want to refactor something and then change your mind etc without affecting your other changes

    Our branches have a very short time to live where I work so we don't usually revert often but it's useful sometimes depending on business change
  • 1
    @MammaNeedHummus no, of course you can’t plan it all up front. That’s impossible. But if you’re reverting over and over so often something isn’t thought through enough
  • 1
    I want to argue more in this thread but I’m honestly too angry, jaded, and don’t give a fuck anymore to start that whole process in my mind.
  • 1
    Merge vs rebase is the new vim vs emacs
  • 1
    @lungdart space vs tabs….OOP vs FP….Sega Genesis vs Super Nintendo….
  • 2
    @TeachMeCode

    * tabs all the way, spaces are for losers

    * OOP and functional programming are not mutually exclusive and actually work quite well together

    * emulate both

    @lungdart both are equally inferior when compared to our lord and savior nano
  • 1
    @tosensei I know right…if it’s practical to use both oop and fp…then don’t let dogma keep you down.

    I know emulate both…but back in the day this was a hot topic when I was a kid lol
  • 1
    @TeachMeCode we only ever had some extremely old gdr-made black-and-white analog video game that was basically just 5 variations of pong.

    on the other hand, we always had access to computers, and those had the better games mostly, anyway.
  • 1
    @TeachMeCode Linux vs Windows
  • 0
    @lungdart ack I missed a spot…lol
  • 0
    @MammaNeedHummus ”When working in legacy I wanna get as many hints as I can”

    Sounds good in theory but don’t you often find projects with lots of changes and many small commits end up having a barrage of tiny insignificant commits plus some back-and-forth changes that make it really hard to get an overview?

    Like imagine your looking at git history for a file and see

    * feb6 - fix line height
    * feb 5 - undo refactoring user
    * feb 4 -lint fix
    * feb 4 - update comment
    * feb 4 - move fetch
    * feb 4 - finish refactor
    * feb 3 - adjust line height
    * feb 3 - lint fix
    * feb 2 - start refactoring user

    It’s just too muc detail especially if this was all part of a single branch

    And there are 20 more branches like this that have changed the file previously

    The further back you go the less significant each commit becomes, and the more I just widh there were 20 squashed commits rather than 200 unsquashed ones
  • 0
    Now I know some of you will argue these are horrid commit messages … like ”adjust line height of what?” but come on

    In a PR named something like ”render user name” with 10 commits you would write commit messages under the assumption that they refer to the user name, you’re not gonna prefix each commit with ”user name” because it has to work if taken out of context…are you?

    Viewing a history like this in a git tree might make sense but as a flat history on github it’s hard to read.. if we imagine there’s hundreds more like this
  • 0
    And regarding that ”start refactor” and ”undo refactor” - that shit happens when working with PR feedback

    (Each could still be an atomic commit in the sense the code still works with each commit)

    So if you don’t wanna see that backandforth as part of master history you gotta squash at some point
  • 0
    @koes you can use rebase to rewrite history and then I fully agree with you. If you do it to get rid of all the merge commits it's not really doing that. I have a perform with force pushes to the long moves branches because then you can't handle the truth.

    I've worked with both styles and especially github was annoying with always creating a merge commit even when it was a fast forward.
    We do use the history quite often so I like the fast forward only approach of merging. A lot of MR/PR are a single commit. To have that exploded with merge commits it's annoying.
  • 0
    @hjk101 why are you using history so often?

    What's the workflow? I've RARELY needed it.
  • 1
    I try to only rebase my own uncommitted work at the end of the day. I don't like squashes, people have done atomic commits and commit messages for a reason (or at least I hope they did).

    But no matter merge or rebase, there will be "conflicts" sooner or later, and when people are allowed to rebase and force-push, they can destroy valuable work without even leaving their name tag.
  • 0
    @ingosteinke I also like rebasing uncommitted work end of day

    But regarding atomic commits:
    Don’t you find that even if commits are atomic, we normally write commit messages which are understood in relation to their branch - and become harder to understand if they are merged as separate commits to master?

    Example: if I work in a branch with a PR named ”Update youtube player” I could make some atomic commits like: 1. ”Change volume icon” 2. ”Change duration time format”

    If this PR is merged to master without squashing and someone views the history on github it is unclear what the commit ”Change volume icon” means. Which volume icon? You might have multiple video players with volume icons

    Using a tool like git-tree it would become clear that it was part of the PR named ”Update Youtube player” but in github it’s not that clear.

    That’s one reason I like squash-merging PR:s
  • 0
    It can be argued that this is mainly a result of how github’s presentation works (IF github had shown each commit’s parent branch or PR I would be fine with not squashing a PR)

    But as things are currently in my team where no one uses git-tree or similar, I find it is unclear when a PR is merged without squashing

    Except in a few special cases where someone makes a PR that does many big things at once and makes effort to really prefix each commit message
Add Comment