如何在Azure DevOps中通过FTP Upload任务仅上传Git提交的变更文件?
Solution: Upload Only Git-Changed Files via Azure DevOps FTP Task
The FtpUpload@2 task doesn’t have built-in logic to filter files by Git changes, but we can work around this by first capturing modified files, copying them to a dedicated temp directory, then uploading only that directory. Here’s the adjusted pipeline and breakdown:
Updated Pipeline YAML
trigger: - main pool: vmImage: 'ubuntu-latest' variables: - name: StagingRepo value: $(System.DefaultWorkingDirectory) - name: TempDir value: $(System.DefaultWorkingDirectory)/temp-changes steps: # Step 1: Capture list of changed files from Git - script: | # Get files changed between current commit and previous one git diff --name-only HEAD^ HEAD > changed-files.txt # Fallback: If this is the first commit (no HEAD^), get all files if [ $? -ne 0 ]; then git ls-files > changed-files.txt fi displayName: 'Fetch Git Changed Files' # Step 2: Create temp directory and copy only changed files (preserving directory structure) - script: | # Clean up temp directory from previous runs (if any) rm -rf $(TempDir) mkdir -p $(TempDir) # Copy each changed file to temp dir, maintaining relative paths while IFS= read -r file; do if [ -f "$file" ]; then # Create matching subdirectory in temp dir mkdir -p "$(TempDir)/$(dirname "$file")" # Copy the file cp "$file" "$(TempDir)/$(dirname "$file")" fi done < changed-files.txt displayName: 'Stage Changed Files to Temp Directory' # Step 3: Upload only the staged temp directory to FTP - task: FtpUpload@2 displayName: 'FTP Upload Changed Files' inputs: credentialsOption: inputs serverUrl: 'ftps://00.00.00.00:22' username: ftp-username password: ftp-password rootDirectory: '$(TempDir)' remoteDirectory: '/home/public_html' clean: false cleanContents: false preservePaths: true # Critical: Keeps relative file structure intact trustSSL: true
Key Details Explained
Capturing Changed Files:
git diff --name-only HEAD^ HEADgrabs all files modified between the current commit and the one before it.- The fallback
git ls-fileshandles the first commit scenario where there’s no prior commit to compare against.
Staging Files to Temp Directory:
- We first clean up any existing temp directory to avoid leftover files from previous runs.
- For each changed file, we create the matching subdirectory in the temp folder (using
mkdir -p) to preserve the original file structure, then copy the file over.
FTP Upload Adjustments:
- Set
rootDirectoryto the temp folder so only changed files are scanned. - Enable
preservePaths: trueto ensure files are uploaded to the correct subdirectories on the FTP server (instead of dumping everything into/home/public_htmlroot).
- Set
Optional: Handle Deleted Files
If you need to sync file deletions to the FTP server, add this additional step after capturing changed files:
# Step 1b: Delete corresponding files from FTP - script: | # Get list of deleted files git diff --name-only --diff-filter=D HEAD^ HEAD > deleted-files.txt # Use lftp to delete files from FTP (install lftp first if needed) if [ -s deleted-files.txt ]; then sudo apt-get update && sudo apt-get install -y lftp while IFS= read -r file; do lftp -u ftp-username,ftp-password ftps://00.00.00.00:22 -e "rm /home/public_html/$file; quit" done < deleted-files.txt fi displayName: 'Delete Files from FTP'
Notes for Different Trigger Scenarios
- If your pipeline triggers on pull requests, adjust the
git diffcommand to compare against the target branch (e.g.,git diff --name-only origin/main HEAD). - For multi-commit builds, modify the diff range to include all commits in the build (e.g.,
git diff --name-only $(Build.SourceVersionPrevious) $(Build.SourceVersion)).
内容的提问来源于stack exchange,提问作者Slimshadddyyy
相关产品推荐
相关产品推荐

