The Reds took the lead through Ben Osborn but Jonathan Kodjia restored parity shortly before half-time.
And, despite Forest's dominant start to the second period, the visitors' influence grew and defender Aden Flint headed home the winner from a corner.
Chris Cohen was handed his first league start since September 2014, replacing the bench-bound Gary Gardner. Forest were otherwise unchanged from the side that narrowly lost at Burnley on Tuesday night.
It was a busy start to the match, the first chance falling to Forest on two minutes. Nelson Oliveira showed excellent control before executing a lovely pass with the outside of his right boot to send Jamie Ward into the area. Ward had to take his shot first time and could only guide the bouncing ball over the bar.
Bristol City's response came a minute later when Matt Mills had to stand firm to nudge Lee Tomlin's effort out for a corner after the wide man showed excellent feet following a quick counter-attack.
Ward and Oliveira almost linked up again on seven minutes, the former receiving a pass from Bojan Jokic, bursting to the byline and drilling it across goal. Oliveira was unable to set himself in time to convert from his unmarked position at the back post.
Forest kept up their intensity and, after receiving a neat first-time lay-off from Cohen, Eric Lichaj burst forward from right back. The American cut inside on his left foot and struck the ball goalwards, but Richard O'Donnell was well placed to make a comfortable save.
Moments later, the visitors conjured up a chance of their own when Kodjia intercepted a loose pass and did well to work himself space for a shot in Forest's area. Matt Mills came in at the last minute to make an important block.
Ward had another brief glimpse at goal on 12 minutes after Vaughan robbed Tomlin and laid the ball off to Oliveira. He supplied Ward, who got the ball caught under his feet in the area and was unable to evade the Bristol City defence.
That proved to be Ward's final major involvement as he sustained an injury while trying to control a diagonal pass. He hobbled off and was replaced by Tyler Walker on 18 minutes.
The pace of the game slowed after that, with only half-chances for either side coming before Forest broke the deadlock on 30 minutes.
Tomlin fouled Lichaj close to the right touchline and Cohen took charge of the free-kick, swinging the ball low into the box. It snuck under a defender's foot and Osborn was able to bring it under control, swivel and fire it low past O'Donnell to put The Reds 1-0 up.
Forest were playing with plenty of confidence, as evidenced by Oliveria's extravagant attempt to double his side's advantage 11 minutes before the break. Jokic did well to dig out a cross from the left, finding the Portugal international on the edge of the box. He flicked the ball up for himself, spun his body goalwards and volleyed the ball sweetly, only for a City defender to block well.
The visitors were refusing to lie down, however, with Tomlin a continuing menace. His brilliant run was halted at the last by Mancienne, moments before Joe Bryan curled a shot wide from the corner of the box.
And Lee Johnson's side had their equaliser four minutes before the break. Bryan was again the instigator, rattling the base of the post with a shot from range. Kodjia was the first man on the scene to guide the ball past Dorus de Vries from eight yards.
There were no changes for either side at the break but first-half substitute Walker had an opening within four minutes of the restart. He raced away down the right to go through one-on-one with O'Donnell but a City defender recovered well to hold the youngster up. Forest worked the ball to Cohen, who pushed it beyond two defenders and went to ground just outside the area. Referee David Webb booked the midfielder for simulation.
Forest were making all the early second-half running, Oliveira having a shot blocked in the area, Lichaj seeing his cross-cum-shot flash a yard wide of the post and Walker arriving half-a-second too late to convert Cohen's drilled delivery.
But it should have been 2-1 to the visitors on the hour. Tomlin was once again the thorn in Forest's side, firing in a low cross from the left which de Vries could only parry towards the penalty spot. Luke Freeman was first to the ball and looked certain to score, but he lashed at it wildly and somehow sent it wide.
Freeman nearly made amends four minutes later when he found Kodjia with a cross from the right, but the striker got underneath the ball and could only glance it into de Vries' grasp.
Now it was all City and, after Michael Mancienne was panicked into conceding a corner by Freeman, Nathan Baker hit the outside of the post after meeting the cross.
Dougie Freedman saw fit to make his second changed shortly afterwards, replacing Vaughan with Gardner on 68 minutes.
But there was nothing the substitute could do to prevent Forest going behind two minutes later as the visitors made their latest corner pay. Flint rose highest to meet Freeman's delivery and, despite getting a hand to the defender's header, de Vries couldn't keep the ball out of his net.
Freedman's final change saw Ryan Mendes, back from a minor injury, replace Robert Tesche.
But Forest were struggling to impose themselves on the Robins and, despite four added minutes, they were unable to find an equaliser.
Forest: De Vries, Lichaj, Mills (c), Mancienne, Jokic, Cohen, Vaughan (Gardner 68'), Tesche (Mendes 74'), Osborn, Ward (Walker 19'), Oliveira
Subs not used: Evtimov, Blackstock, Hobbs, Grant
Goal: Osborn 30'
Booking: Cohen 49'
: Bristol City
O'Donnell, Little, Flint, Baker, Golbourne, Pack (c), Reid (Agard 90'), Tomlin (Wagstaff 74'), Bryan, Freeman, Kodjia (Wilbraham 82')
Subs not used: Fielding, Vyner, Pearce, Williams
Goals: Kodjia 41', Flint 70'
Referee: David Webb
Attendance: 20,551 (1,032 away)