Thomas finished just 14 seconds behind second place Tom Dumoulin (Sunweb), who went fast enough to confirm his second place and take victory on the stage, just one second ahead of Chris Froome (Team Sky).
Primož Roglič (LottoNL-Jumbo) lost his place on the podium in third as fourth placed Chris Froome did enough to gain the 13 seconds needed over the 31km course in the Basque Country. Froome took 1-12 out of yesterday's stage winner, who now drops down to fourth with his team-mate Steven Kruijswijk in fifth.
World champion Dumoulin had looked like he wouldn't be contention for the stage and could even lose time on Thomas as he went slower than the race leader and Froome through the intermediate splits, but paced his time trial perfectly to cross the line to take victory ahead of the defending champion by a single second.
The Dutchman moved from 2-05 to 1-51 behind Thomas, but it never looked like the yellow jersey was ever under threat throughout the time trial.
Other moves in general classification include Romain Bardet (Ag2r La Mondiale) moving up to sixth ahead of Mikel Landa (Movistar), while Ilnur Zakarin (Katusha-Alpecin) moved up to ninth ahead of Nairo Quintana (Movistar) in 10th.
How it happened
With one last decisive stage to come at the 2018 Tour de France, the 145 remaining riders faced a hill 31km time trial from Saint-Pée-sur-Nivelle to Esplette in the very south west of France.
As usual, riders set off in order of the general classification with many riders in the lower rankings just looking to get through in sufficient time.
But Australia’s Michael Hepburn (Mitchelton-Scott) set his stall out early with a shout at the stage win, setting a long-standing time of 42-15.
He was able to enjoy his time in the hot seat until Marc Soler (Movistar) arrived in at the finish at just 0.05 seconds ahead of him to take the lead.
With the stronger riders now heading out on the course, the Spaniard’s time didn’t last very long, with Søren Kragh Andersen (Sunweb) coming in 31 seconds ahead.
That also didn’t last long as Michal Kwiatkowski looked to make the day even better for Team Sky as he went one second faster. And that time would stand until the general classification riders began to get out on the road.
Chris Froome set off on his run at a blistering pace, going through quickest on the intermediate time checks as he eyed a stage win and a return to the podium.
When the man ahead of him in GC, Primož Roglič, began his time trial, it immediately looked like Froome would be easily moving into third as Roglič struggled to match his pace.
Likewise, it looked like Tom Dumoulin could see his second place under threat from Froome as he went slower through the intermediate checks, but the world champion began to up his pace in the closing half of the course.
Behind him, Geraint Thomas had set off on his run and also began at a furious pace and also went quickest through the time checks, and aside from a slight wobble on a corner, it was clear he would win the Tour de France with a strong time trial.
As Froome came in to the finish he took the lead from his team-mate Kwiatkowski by a huge 49 seconds, but he would only have to wait a couple of minutes to see if Dumoulin would deny him a late stage win.
In the meantime, Roglič arrived at the finish with a hugely disappointing time of 1-11 down on Froome, seeing his podium place slip from his grasp after impressing on the final mountain stage on Friday.
Dumoulin was the next to arrive, just making it across the line with a single second in hand over Froome to take the stage victory.
Thomas was of course the last man on the road, crossing the line 14 seconds down on Dumoulin’s time but screaming with delight, safe in the knowleged that he had done enough to win the 2018 Tour de France.
The Tour concludes on Sunday, with a 116km stage from Houilles to Champs-Élysées, Paris; a largely processional stage that should end in a sprint finish.
Tour de France 2018, stage 20: Saint-Pée-sur-Nivelle to Esplette (31km ITT)
1 Tom Dumoulin (Ned) Team Sunweb, in 40-52
2 Chris Froome (GBr) Team Sky, at 1s
3 Geraint Thomas (GBr) Team Sky, at 14s
4 Michal Kwiatkowski (Pol) Team Sky, at 59s
5 Søren Kragh Andersen (Den) Team Sunweb, at 51s
6 Bob Jungels (Lux) Quick-Step Floors, at 52s
7 Ilnur Zakarin (Rus) Katusha-Alpecin, at 1-02
8 Primoz Roglic (Slo) LottoNL-Jumbo, at 1-12
9 Marc Soler (Esp) Movistar Team, at same time
10 Michael Hepburn (Aus) Mitchelton-Scott, at 1-23
General classification after stage 20
1 Geraint Thomas (GBr) Team Sky, in 80-30-37
2 Tom Dumoulin (Ned) Team Sunweb, at 1-51
3 Chris Froome (GBr) Team Sky, at 2-54
4 Primoz Roglic (Slo) LottoNL-Jumbo, at 3-22
5 Steven Kruijswijk (Ned) LottoNL-Jumbo, at 6-08
6 Romain Bardet (Fra) AG2R La Mondiale, at 6-57
7 Mikel Landa (Esp) Movistar Team, at 7-37
8 Daniel Martin (Irl) UAE Team Emirates, at 9-05
9 Ilnur Zakarin (Rus) Katusha-Alpecin, at 12-37
10 Nairo Quintana (Col) Movistar Team, at 14-18
Thank you for reading 20 articles this month* Join now for unlimited access
Enjoy your first month for just £1 / $1 / €1
*Read 5 free articles per month without a subscription
Join now for unlimited access
Try first month for just £1 / $1 / €1