上週幫客戶處理一個年久失修的 PHP 專案,修正程式的過程中,我利用 Git 幫我直接在測試機上做好原始碼版控與備份等工作,待修正工作完成後,想要把最近一次 commit 過的變更檔案匯出,卻突然不知道指令怎麼下,研究了一下發現還蠻簡單的,今天這篇文章我打算解釋使用 TortoiseGit 、 Git for Windows 與在 Linux 底下使用 Git 工具,應該如何順利的匯出特定版本下的變更檔案。
使用 TortoiseGit 匯出變更檔案
我在多年前曾經寫過一篇【如何讓 TortoiseSVN 僅匯出新增或修改過的檔案】文章,在 TortoiseGit 上面的操作與 TortoiseSVN 的操作幾乎完全一樣,所以我就不贅述這段,請參考該篇文章解說。
在 Windows 平台使用 Git for Windows 匯出變更檔案 (透過 Batch 指令)
要列出最近一個版本的檔案異動清單,可以執行以下指令:
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD
其中 --diff-filter=ACMRT 所代表的意思份別是:
- A = Added
- C = Copied
- M = Modified
- R = Renamed
- T = Changed
※ 完整的 git diff-tree 用法說明,建議可輸入 git help diff-tree 命令,以取得完整的文件說明。
這個指令主要列出該版本 ( HEAD ) 所有變更檔案的路徑與檔名而已,所以如果還要複製出這些檔案,並且依照這些變動的檔案,保留原本檔案的資料夾結構的話,則還須搭配更進階的批次檔語法。
請在你的 Git 工作目錄的最上層資料夾,輸入以下指令:
for /f "usebackq tokens=*" %A in (`git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD`) do echo FA|xcopy "%~fA" "G:\git_changed_files\%A"
上述指令,直接複製貼上到命令提示字元就可以順利執行,並且將目前該版本的所有變更檔案,包含資料夾結構,都複製到 G:\git_changed_files 目錄下。 ( 請依照你自己的需求變更目錄名稱 ) 最後你在利用壓縮軟體自行打包這些檔案即可。
另外,我剛也花點時間寫了一支完整的批次檔,可以更加方便的輸出變更檔案:
檔案名稱:git-export-changes.cmd
檔案路徑:C:\Program Files (x86)\Git\cmd
@ECHO OFF
setlocal enabledelayedexpansion
SET zipfile=update.zip
IF "%1"=="" GOTO Help
IF NOT "%2"=="" SET zipfile=%2
set output=
for /f "delims=" %%a in ('git diff --name-only %1^^') do ( set output=!output! "%%a" )
git archive -o %zipfile% HEAD %output%
endlocal
GOTO Exit
:Help
ECHO.
ECHO 用法: git-export-changes ^<ref^> ^<filename.zip^>
ECHO.
ECHO 輸入 ^<ref^> 的時候,可用 HEAD,該程式會自動跟前一個版本做比較
ECHO 若沒輸入 ^<filename.zip^> 的時候,預設為 updates.zip 並輸出在當前目錄
ECHO.
PAUSE
:Exit
使用範例:在 Git 工作目錄下,輸入 git-export-changes.cmd HEAD export-updated-files.zip
在 Linux 底下使用 Git 工具匯出變更檔案 (搭配 Shell 指令)
利用 Git 取得變更的檔案清單,其指令是一樣的:
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD
然後可以利用 git archive 這個 Git 內建命令來產生本次變更的所有檔案:
git archive --output=files.tar HEAD $(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD)
如果你想匯出 Zip 壓縮檔格式,可以改用以下指令:
git archive --format=zip --output=files.tar HEAD $(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD)
就這樣,很快地就能打包好這些變更的檔案,方便提供客戶更新與部署新版本。
請注意: 如果沒輸入 $(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD) 的話,執行 git archive 會把該版本所有的檔案,全部匯出成 tar 檔,也就如同匯出最新版本的原始碼的意思,因此若要繪出完整原始碼,比較簡短的寫法如下:(以下指令同時適用於 Windows / Linux / Mac 作業平台)
git archive HEAD > export.tar
或是 Zip 壓縮檔格式:
git archive --format=zip HEAD > export.zip
相關連結