Thomas completed the stage in 5:18:37, beating Team Sunweb’s Tom Dumoulin of the Netherlands and AG2R La Mondiale’s Romain Bardet of France in the final stretch, with teammate Chris Froome finishing fourth.
The Welshman reinforced his race lead with a general classification time of 49:24:43, one minute and 40 seconds clear of Froome in second.
It was Thomas’s second consecutive stage win after coming out on top in stage 11 yesterday.
In the first 50km of the 175km race, a 30-man breakaway group surged away from the peloton. Thomas remained in the peloton one-and-a-half minutes back.
The breakaway group’s lead grew to two minutes with about 120km remaining. As the race progressed, their lead rose to almost three minutes.
With about 100km remaining, Dutchman Steven Kruijswijk, who was sixth in the general classification standings before the stage, became the virtual race leader as the breakaway extended their lead to three-and-a-half minutes.
Kruijswijk was two minutes and 40 seconds down from Thomas after stage 11.
With 94km left, the breakaway split up as the gap from the peloton shot up to almost four minutes.
Kruijswijk attacked from within the breakaway group and led the race with 72km remaining, as the peloton fell another 15 seconds behind.
Andre Greipel, Rik Zabel and Tony Gallopin retired from the stage several kilometres later.
Kruijswijk extended his lead over the peloton to five minutes and 40 seconds with 65km left, as he prepared for the flatter plateau of the climb. He was 40 seconds ahead of the chasing group at the time.
Team Sky, including Froome and Thomas, dominated at the front of the peloton, setting the pace.
Kruijswijk was first to hit the Col de la Croix de Fer with 55km remaining, as his lead hovered at around six minutes over the peloton.
The chasing group split up as Warren Barguil, Mikel Nieve and Rafał Majka went ahead. Kruijswijk held a two-minute and 40-second lead over the trio and retained his six-minute lead over the peloton.
The chasing trio fell behind by 30 seconds with 40km remaining. Thomas, in the peloton, stayed six minutes behind Kruijswijk and looked likely to lose his race lead.
Over the next 20km the peloton merged with the chasers, as Kruijswijk stayed in solo lead, five minutes clear with 21km left.
Kruijswijk’s lead was gradually reduced and dropped to three minutes and 40 seconds with 11km remaining, as Thomas and the others began to hunt him down.
With 8km left, Kruijswijk’s lead was down to two-and-a-half minutes and he lost his virtual race lead.
A series of attacks were launched from within the peloton. Romain Bardet attacked and went ahead from the chase, as Kruijswijk’s lead dropped to under two minutes.
Bardet was strong in pursuit of Kruijswijk and narrowed the gap to just more than a minute with 5km left.
Bardet then fell back, as Froome attacked and surged ahead of the chase. He passed Kruijswijk with 3.5km remaining and took the lead.
Tom Dumoulin dragged Thomas and Bardet back up to Froome one kilometre later.
The four riders stayed together for the next two kilometres, even after a string of attacks from Bardet and Dumoulin. Mikel Landa joined the group with one kilometre left.
Landa attacked and briefly took the lead with 500m left, but he too was soon reeled back in.
In a near copy-and-paste repeat of the previous stage, Thomas then attacked with 200m to go and surged over the line to take the win.
“This is just unbelievable, can we just go to Paris now?” A delighted Thomas said afterwards.
“I said yesterday this race was made for me. Today I can be happy and sure of that now.
“Maybe the next few days I can keep the jersey but this race is so hard. You never know how your body reacts,” he added, implying that Froome is still their race leader.”