Getting from Bootstrap 2 to Bootstrap 3 Doesn't Have to Ruin Your Week
I migrated a production dashboard from BS2 to BS3 back in 2014 and honestly it was one of those tasks that looks simple on paper and then bites you in six different places once you actually try it. The migration isn't hard if you understand what changed. It's miserable if you just copy-paste the old HTML and hope for the best. Bootstrap 3 introduced a complete grid overhaul, moved from fixed to fluid by default, renamed a bunch of classes, and dropped some of the less-used components entirely. Your existing markup will mostly still render, but things like form layouts, button styles, and the navbar are going to look wrong without some adjustments. That's where a structured approach helps instead of randomly chasing CSS issues one at a time.
Boot 2 To 3 Migration Guide
Start by upgrading the files. Pull the latest Bootstrap 3 release, replace your existing bootstrap.min.css and bootstrap-theme.css, and remove any references to the old glyphicons sprite since they were replaced with font files. If you're using custom LESS variables, stop and read through the new variable names first because half of them changed. The old @gridColumnWidth stayed the same but @gridGutterWidth became something you need to recalculate anyway. Here is the part most people skip and then waste hours debugging. Run your templates through a validation pass before you do anything else. Check which components you're actually using. If you built anything on .span4 or .span6 you need to convert those to .col-md-4 or .col-md-6 immediately. The old span classes still exist in BS3 but they're deprecated and they behave differently with responsive breakpoints, which means your layout might look fine on desktop and completely broken on tablet. I ran into a very specific problem with nested columns during a migration for a client who had deeply nested row structures. The old BS2 nesting worked fine because columns were floats inside floats. BS3 uses flexbox-style calculations and the inner rows needed explicit .row wrappers around every nested level, otherwise the negative margins on the outer rows conflicted with the padding on the inner ones and your content would shift by about 15 pixels to the right on smaller screens. The fix was wrapping each nested group in its own .row and making sure the gutter values matched up between the parent and child levels. Took me about forty minutes to find and fix once I understood what was happening.
Forms changed significantly. .control-group is gone. .help-block replaced .inlineHelpText. Input sizing classes moved from .input-mini through .input-large to the more flexible .col-sm-* and .col-md-* system integrated directly into the grid. If your forms relied heavily on the old input sizing classes you will need to refactor those. Buttons lost .btn-mini and .btn-large. They kept .btn-xs and .btn-lg but the sizing logic is different now because font-size and padding scales differently. Your existing button markup will compile but may not match your design expectations pixel-perfectly. The navbar underwent a complete rewrite. .navbar-inner is gone. You now wrap everything in .navbar and .container or .container-fluid depending on your layout needs. If you have a custom themed navbar the new Sass/LESS mixins are structured differently and your color overrides will likely break unless you audit them. I've seen people spend two days chasing navbar color issues that came down to a single misplaced class attribute.
Get the Full Details

Dropdown menus changed their data attribute handling. The old data-toggle="dropdown" still works but the JavaScript plugin was rewritten and you need jQuery 1.9.1 or higher. If you're still running jQuery 1.6.x or 1.8.x you will hit compatibility issues and the dropdowns won't open. Upgrading jQuery first before touching Bootstrap saves a lot of frustration. For a smoother transition you can use the Bootstrap Migrator tool if you have a large codebase. It automates the class renames and structural updates across your HTML files. It won't fix everything, especially custom components you built on top of BS2, but it handles the bulk rename work that would otherwise take days manually. The tool is available on GitHub under twbs/bootstrap-migrator and it still works for basic migrations. Be aware that BS3 dropped support for Internet Explorer 7 entirely. If your product has any IE7 traffic this migration is going to cause real problems for those users. Also the drop of .hero-unit means you lose that large callout component, and .thumbnail was renamed to .img-thumbnail for images while the card-like .thumbnail remains but with different styling. Both exist now and it is easy to mix them up.
The downsides are real. BS3 is a breaking change, not an additive upgrade. You cannot do a zero-touch migration and expect a polished result. Budget roughly 8 to 12 hours per major page template depending on complexity. Simple landing pages might take two hours. Complex dashboards with custom components could easily take a day or more per template. If you have custom JS plugins that hook into BS2 events like .on("show" etc on modals you need to verify they still work because the event names changed slightly. If your project is still heavily tied to IE7 or you have a massive amount of custom BS2 code you might consider staying on BS2 for another revision or looking at migrating directly to Bootstrap 5 if the budget allows. BS4 and BS5 are further removed from BS2 in different ways, but they come with better documentation and more recent community support. The choice depends entirely on your timeline and how much technical debt you're willing to absorb in one pass versus spreading it across multiple upgrades.