Git 練習 - 取回某次 Commit 的檔案版本
1 | 3,911 |
今天遇到一個問題,想從 Git 版控找出圖檔何時被改壞。圖檔不像程式碼能用 git blame 直接找出哪一行何時被誰修改,但至少可以知道檔案在何時被誰改過,再從 Commit 調閱當時的版本加以比對。這個需求肯定有方便的 GUI 工具可以做到,但我想練習用指令完成。
假設 Git 版控有四次 Commit,有個 dog.png 圖檔被改過三次:
要找出檔案在哪些 Commit 被異動過,基本指令是 git log -- path/fileName
( -- 用來分隔選項參數與檔名,-- 前方可加上 --oneline --pretty 等選擇性參數,後方為要查詢的檔案對象),再依需求加上 git log 參數,以下是我常用的寫法:
git log -- dog.png
git log --oneline -- dog.png
git log --date=format:"%Y-%m-%d %H:%M:%S" --pretty=format:"%h %ad %s %an" -- dog.png
知道 Commit ID,我們就能透過 git checkout commit_id path/file
將檔案還原回某次 Commit 的版本,或是用 git show commit_id:path/file
查看內容,若不是文字檔,則可加上 > 導向寫成檔案 git show commit_id:path/file > saveFilePath
git checkout 64dfd59 ./dog.png
git show 6f443d0:./dog.png > dog_check.png
基本上,學會以上指令就能查出檔案在哪些 Commit 被異動過,並調閱特定版本出來比對,已滿足日常需求。但我手又癢了,決定寫個 PowerShell 把歷屆版本全部轉出來,檔名註明存入時間,一次對照個夠。
param (
[Parameter(Mandatory = $true)]
[string]$fileName,
[Parameter(Mandatory = $true)]
[string]$saveFolder
)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$gitLog = "git log --date=format:`"%Y-%m-%d %H:%M:%S`" --pretty=format:`"%h %ad %s %an`" -- $fileName"
(& "cmd.exe" '/c' $gitLog | ForEach-Object {
$p = $_.Split(' ')
return [PSCustomObject]@{ CommitId = $p[0]; Date = $p[1]; Time = $p[2]; }
}) | ForEach-Object {
$saveFileName = Join-Path $saveFolder "$($_.Date)T$($_.Time.Replace(':',''))-$fileName"
$gitShow = "git show $($_.CommitId):$fileName > $saveFileName"
& "cmd.exe" '/c' $gitShow
}
成功!
對上述 PowerShell 寫法有興趣,可參考下列文章介紹的技巧:
Tips of how to get specific file version from Git commit.
Comments
# by 小魚
神~