於是周襄王就派人邀請晉文公,要他派兵護送自己回朝。晉文公聽到周天子的號令,立即派兵向東攻打,打退了狄國,殺了太叔帶和支持他的大臣,順利將周襄王扶上天子之位。這件事之後,晉國在諸侯國中樹立了較大的威望,一些小國開始表示臣服或友好。
兩年後,宋國國君宋成公向晉國借兵,楚國糾結陳、蔡、鄭、許及本國兵力攻打宋國。晉文公讓眾大臣討論各自的看法,大家紛紛表示,楚國總是欺負中原各諸侯國,晉國應該幫助有困難的國家,借此也建立起晉國的威信。於是魯僖公二十八年(公元前632年),晉文公擴充三軍,浩浩蕩蕩前去幫宋國解圍,城濮之戰正式拉開帷幕。
當時的“國際”背景是,齊桓公死後,國內大亂,北方霸業衰落,南方的楚國趁機北上,先後控製了鄭、蔡、衛、宋、魯等眾多中小國家,國力空前強盛,楚成王成為新的霸主,楚國有望進一步向北擴展。而晉國,雖然在中原諸侯國中屬於比較強大的國家,但崛起的時間短,無論是國力還是兵力,都稍遜一籌,但一心想建立霸業的晉文公也不甘心任由楚國強大。城濮之戰就是在這種局勢下展開的。
晉國與宋國之間,隔著曹、衛兩國,這兩國都是楚國的附庸國。晉國若繞過這兩個國家直接攻打楚國,容易腹背受敵,加之楚國比較強大,晉國沒有必勝的把握,局勢對晉國很不利。晉文公就在狐偃的建議下,先攻打曹、衛兩國,一方麵可以打擊楚國的勢力,將戰線南移;另一方麵,可以借此引誘楚國北上,拉長楚國的戰線。結果,曹、衛兩國在晉軍麵前不堪一擊,這兩個國家的國君最終被俘虜。
雖然成功俘虜了曹、衛兩國的國君,然而晉文公的目的卻隻達到了一個,楚軍不肯北上,依舊全力圍攻宋國國都商丘。在宋國國君接連發出告急通知的情況下,晉文公既擔心宋國投降,又擔心如果晉軍南下,遠離本土,戰線太長,不利於自己。晉國群臣再次召開軍事會議,仔細分析了當前的局勢,最終做出這樣的決定:建議宋國表麵上疏遠晉國,然後由宋國出麵,給秦國、齊國這兩個中原大國送去一份厚禮,讓這兩個大國出麵懇求楚軍撤兵。為了打消宋國的疑慮,晉國將自己戰勝獲得的曹、衛兩國的一部分土地贈送給宋國。
晉國的這些建議,宋國都一一照做了。結果,楚國看到齊、秦兩國要求楚國撤兵的懇求之後,竟然不同意,因為曹、衛兩國原本是屬於楚國的勢力範圍的,現在已經成為晉國的勢力了,楚國怎能甘心就這樣撤兵呢?因此,楚國沒有接受這兩個大國的建議。齊、秦兩國原本是這場戰爭的中立國,但如今在楚國丟了麵子,所以很自然成為楚國的對立國,並與晉國結盟。這樣一來,雙方的兵力發生了明顯的變化,楚國不得不麵對晉、齊、秦三大強國。
既然形勢已經不利於自己,楚成王也識趣地將楚軍撤退到申地(今河南南陽),放棄對宋國的圍攻。但是,圍困宋軍的令尹子玉很自大,不把晉軍放在眼裏。當楚成王要求他撤兵以免與晉軍發生衝突時,子玉毫不在乎,堅決要求讓自己與晉軍大戰一場。楚成王是個優柔寡斷的君主,既然子玉堅持,他就同意了,但卻沒有給子玉足夠的兵力,隻從國內派了少量兵力前往增援。
子玉原本就驕傲自大,楚成王又派出了救援,因而更加狂妄。在開戰之前,他開出一個苛刻的條件以激怒晉軍主動同自己開戰。他要求:晉軍從曹、衛撤軍,使之複國;然後自己的軍隊撤出宋國。這個條件表麵上看來沒什麼,但卻打消了晉國號令群雄、稱霸中原的機會。
沒想到晉文公采取了更高明的對策:將計就計。他暗地釋放了曹、衛兩國國君,答應幫助他們複國,但要求他們先與楚國斷交。然後,他扣留了楚國的來使。子玉原本是來救曹、衛兩國的,沒想到這兩個國家臨陣倒戈與自己絕交,而且自己的使者還被晉國扣押。這讓驕傲自大的子玉惱羞成怒,氣得直跺腳,然後就率領楚軍及附庸小國軍隊,氣勢洶洶地向晉軍逼近。
晉文公這時候又下令軍隊“退避三舍”,表示自己兌現了流亡時期向楚成王許諾的“後退九十裏”的約定。此舉贏得了“國際”上的讚同,大家都以為晉文公是一位真正的君子,晉軍在輿論上占了主導。其實,晉文公的真正目的是避開楚軍鋒芒,避免更大的傷亡,借此誘敵深入,尋找有利的時機後發製人。
晉軍的突然撤退,使楚軍中的不少人感到蹊蹺,建議停止追擊。但剛愎自用加惱羞成怒的子玉根本聽不進去他人的建議,反認為這是奪回曹、衛的大好時機,堅持前進,於是他帶領軍隊一直追擊到晉軍的駐紮地城濮。此時,齊、秦、宋諸國的軍隊也陸陸續續與晉軍彙合。晉文公借助目前對自己有利的“國際”局勢,檢閱了部隊,振奮了士氣,全軍憋足了勁兒與楚軍一戰。
公元前632年4月,晉、楚兩軍在城濮展開決戰。晉軍率先集中兵力攻擊子玉戰鬥力最差的翼側軍隊,楚右翼迅速被殲滅,然後又利用楚軍不諳虛實的弱點,打擊楚軍的左翼軍。子玉所率領的中軍,雖然是戰鬥力最強的,但由於失去了左、右兩軍,敗局已定,匆忙率領中軍撤出戰場,這才僥幸保全中軍。城濮之戰就此以晉軍獲得決定性勝利而宣告結束,子玉大軍後退至連穀時,子玉覺得沒法向楚成王交代,便被迫自殺了。