What you are looking for is likely an accumulation branch.
If you have just two branches - the development branch and mainline, and main line has changed since the development branch was made and merges from mainline to the development branch wasn't done during the process:
+------.----.------dev-------------------------...
/ / /
/ / /
+------------------mainline--------------------+
Then its just a 'simple' matter of doing another merge from the mainline to dev, fixing up the merge in dev, and then merging back to mainline (which should have had minimal changes between the two merges) and closing the branch.
+------.-----.-----dev---.-----.+
/ / / / \
/ / / / \
+------------------mainline--------------------+
The key here is that you really should avoid having a broken build from mainline. Mainline is in most places a 'this is good' and what people branch from. If you instead did just a 'merge to mainline and fix':
+-----.-----.------dev----+
/ / / \ finally fixed
/ / / \ v
+------------------mainline--.---.---.---------+
It is possible that the someone could have branched from the broken state in mainline during before those were ready and stable. This is often seen as a bad thing.
One of the bits with this that can cause some issue is that after development is done on the dev branch, its role/policy changes. Development happens in a dev branch... but after development is done, you're doing something else in the dev branch. This goes against some patterns of branching. You may not use this pattern, but its something to be aware of and consider.
The above case was the simple one - one dev branch. But what if you have two dev branches that need to be reconciled?
I point to Advanced SCM Branching Strategies by Stephen Vance (a really good read when it comes to branching and central version control style systems (rather than distributed - though if you read it you can certainly find parallels between this document and things like git flow).
Vance identifies specific roles that a branch can be. You've got mainline, development, maintenance, accumulation, and packaging. In this case, we're dealing with mainline, dev, and ultimately accumulation.
The problem with working with two branches and trying to do the merge into the mainline is that it can make it even more of a mess for a longer period of time.
The solution is to introduce an accumulation branch.
In the previous example, accumulation role was also part of the mainline branch (which has the mainline role too). It looked like this:

But, when things get hairy with merges, having the mainline and accumulation roles both on the mainline branch can lead to issues. So instead, create an accumulation branch to which you merge the development branches which can then be reconciled there and merged back into the mainline. This particular image also shows a packaging branch, but thats not at issue here.

One important bit to note here is that everything branches from mainline (not some other branch), has a life cycle, merges back into mainline, and then is closed. There are no long running branches (other than mainline). Each branch has a specific role to fulfill and when that is complete the branch is removed.