The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何讓 Git 僅匯出在特定版本中新增或修改過的檔案

上週幫客戶處理一個年久失修的 PHP 專案,修正程式的過程中,我利用 Git 幫我直接在測試機上做好原始碼版控與備份等工作,待修正工作完成後,想要把最近一次 commit 過的變更檔案匯出,卻突然不知道指令怎麼下,研究了一下發現還蠻簡單的,今天這篇文章我打算解釋使用 TortoiseGitGit 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

相關連結