The Colombian sprinter remained calm as numerous attacks went off the front on the last climb of the day in the final 10km, but his Quick-Step Floors team did a good job of covering every move.
However they were caught in the flat final three kilometres, with Lotto-Soudal having two riders on the front in the final kilometre in support of Jens Debusschere.
But Gaviria and Sagan were the two big names left in the front group, and it was Gaviria who opened the sprint, holding off a gaining Sagan to take his fourth win of the season.
As for the overall contenders, they all finished safely in the peloton, with no change to the GC lead of Nairo Quintana (Movistar), who retains a firm grip on the blue leader’s jersey heading into the final stage.
How it happened
After a tough day in the saddle yesterday, the peloton put up little resistance as a eight-strong break went up the road almost immediately.
The break consisted of Ben Gastauer (Ag2r La Mondiale), Pavel Kochetkov (Katusha-Alpecin), Davide Ballerini and Raffaello Bonusi (Androni-Giocattoli), Simone Andreetta and Mirco Maestri (Bardiani-CSF), Alan Marangoni (Nippo-Vini Fantini), and Joonas Henttala (Novo Nordisk).
However they were kept on a relatively close leash for most of the day, with the peloton’s chase only interrupted when it had to stop at a level crossing for a number of minutes midway through the stage.
The gap steadily dropped to less than 30 seconds as the race approached the final 15km finishing circuit including a 3km climb, as Movistar controlled the front of the peloton.
Movistar were attempting to protect the overall lead of Quintana, so there was no need to react to an attack from Vincenzo Nibali (Bahrain-Merida), who was more than five minutes down before the stage.
But with so few sprint stages in the race, the sprinters’ team were keen to neutralise the attack, with Fernando Gaviria’s Quick-Step Floors team-mate Bob Jungels locked on Nibali’s wheel, before a counter-attack came from Fabio Felline.
Felline quickly caught the remnants of the break, with Niki Terpstra also bridging across.
The move look threatening, and prompted an attack off the front of the peloton from Peter Sagan, but the world champion was shadowed by a number of Quick-Step Floors riders to neutralise the move.
After a chaotic descent it was Orica-Scott, with only three riders remaining in the race, pulling the move back as the Australian team attempted to set it up for Luka Mezgec.
Under the flamme rouge as Lotto-Soudal had three riders in front of Jens Debusschere, but with Sagan and Gaviria in close attendance Debusschere was always going to be up against it.
And it was Gaviria who hit the front first, edging out Sagan by half a wheel to prevent the Slovakian from taking his third win of the race.
Meanwhile race leader Nairo Quintana finished safely in the main peloton, meaning that he will take a surely unassailable lead of 50 seconds over Thibaut Pinot (FDJ) into Tuesday’s 10km time trial.
Tirreno-Adriatico 2017, stage six: Ascoli Piceno to Civitanova Marche (168km)
1. Fernando Gaviria (Col) Quick-Step Floors 4:09:31
2. Peter Sagan (Svk) Bora-Hansgrohe
3. Jasper Stuyven (Bel) Trek-Segafredo
4. Matteo Trentin (Ita) Quick-Step Floors
5. Jens Debusschere (Bel) Lotto-Soudal
6. Elia Viviani (Ita) Team Sky
7. Scott Thwaites (GBr) Dimension Data
8. Eduard Grosu (Rom) Nippo – Vini Fantini
9. Anthony Roux (Fra) FDJ
10. Jurgen Roelandts (Bel) Lotto-Soudal, all at same time
General classification after stage six
1. Nairo Quintana (Col) Movistar Team, in 1-44-28
2. Thibaut Pinot (Fra) FDJ, at 50secs
3. Rohan Dennis (Aus) BMC Racing Team, at 1-06
4. Primoz Roglic (Slo) Team LottoNl-Jumbo, at 1-15
5. Tom Dumoulin (Ned) Team Sunweb, at 1-19
6. Geraint Thomas (GBr) Team Sky, at 1-23
7. Rigoberto Uran (Col) Cannondale-Drapac, at 1-30
8. Jonathan Castroviejo (Spa) Movistar Team, at 1-32
9. Bauke Mollema (Ned) Trek-Segafredo, at 1-37
10. Simon Spilak (Slo) Katusha-Alpecin, at 1-59