The Diamondbacks broke things open with a four-run seventh inning highlighted by a two-run double from Chris Johnson.
Arizona won for just the fourth time in 13 games.
It was the first victory for Cahill (10-11) since July 30. He eventually went 6 1/3 innings while giving up two runs on two hits with five strikeouts. Cahill had gone 0-2 in his six previous starts.
San Francisco did not have a base runner until Cahill walked Brandon Crawford with one out in the sixth. The Giants' first hit came on Adam Eaton's infield single with one away in the seventh.
Madison Bumgarner (14-10) took the loss, allowing three runs on seven hits in 6 1/3.