La Roja had looked on course to win in normal time after taking the lead early in the second-half, before Germany levelled late on to force an additional 30 minutes.
The first-half passed without any major incidents and just a handful of half-chances at either end.
With both teams operating a high press, there was little time for any creativity, making the opening period a scrappy, somewhat frenetic affair.
Rodrigo dicated much of Spain’s brighter moments, with his influence growing as the game progressed.
Our No.16 was joined in the starting XI by former City team-mate Aymeric Laporte, while Germany included ex-Blues Ilkay Gundogan and Leroy Sane .
The game exploded into life on 51 minutes when Spain took the lead as Dani Olmo struck a well-placed low shot past Manuel Neuer from Lamine Yamal ‘s cross.
Ferran Torres brought the number of former City players up to four when he replaced Yamal on 63 minutes.
Rodrigo, in masterful form, was winning numerous duels, protecting his back four and sparking counter-attacks as the game wore on.
But, backed by a partisan home crowd, Germany almost levelled on 77 minutes when Niclas Fullkrug connected with a low cross and saw his effort strike the foot of the post.
Alvaro Morata’s substitution on 80 minutes saw Rodrigo take over the captain’s armband as Spain edged towards victory.
However, on 89 minutes, Florian Wirtz struck home a dramatic equaliser via the post from Joshua Kimmich’s clever knock-down to send the majority of the Stuttgart Arena wild – and the game into 30 minutes of extra time.
The first 15 of additional time saw no further scoring, with neither team overly expansive with a semi-final berth at stake.
But in the last minute, sub Merino headed home Olmo’s cross to stun Germany and send the Spanish into the semi-finals.