Jose Valverde (3-2) pitched a perfect ninth after Philadelphia rallied from three runs down to lead 4-3 in the eighth.
Pedro Feliz singled for the Phillies to drive in the go-ahead run in a two-run eighth that followed two runs in the seventh. The NL East leaders had scored only three runs in their previous four games and had been shut out twice in that span.
The Phillies, who were without Chase Utley due to his sore right foot, had reached 17 scoreless innings before getting on the scoreboard. They trailed 3-0 before Astros starter Roy Oswalt left injured with one out in the seventh Saturday.
Back-to-back RBI singles by Ben Francisco and Carlos Ruiz after Oswalt left made it 3-2.
Then Jimmy Rollins led off the eighth with a single off LaTroy Hawkins (1-5) and Ryan Howard hit a tying triple before Feliz singled.
Oswalt allowed two runs on four hits before leaving due to tightness in his lower back with one out in the seventh. Before that, he struck out eight with one walk.
Philadelphia starter Joe Blanton allowed three runs on six hits and a walk. He struck out five.
In the second inning, Hunter Pence hit a two-run homer for his 20th of the season, and added an RBI single up the middle in the third.
NOTES: Utley hurt his foot when he fouled a ball off it in his first at bat Friday night. Club officials say he was being held out as a precautionary measure and is day to day. Miguel Cairo started in his place. ... Astros 3B Jeff Keppinger sat out the game with a sore right hip after receiving treatment on it before the game. He is day to day. ... Michael Bourn got his NL-leading 50th stolen base in the first inning. He's the first Astros player to reach 50 stolen bases since Craig Biggio in 1998.