Export Changed Files Between Two Commits
More often than not some deployment strategies involve file overwriting, such as in the case of Sitefinity projects. This manual deployment process typically takes the following steps:
1. Identify files that are modified or created
2. Obtain the files and put them in a new folder
3. Organise the files to follow the original structure
4. Zip the folder
5. Upload to production server
The above mentioned process is tedious and is prone to human mistake as the number of files involved scale up. Fortunately the process can be automated with a single Git command:
git archive --output=package.zip update_commit $(git diff --name-only original_commit..update_commit --diff-filter=d)
The Git command is made of two parts:
1. Generate a list of files that are created and modified between two commits
2. Archive the list of files in a zip folder
We shall use an example to illustrate what happens under the hood.
Assuming we have a directory called “DIFF” that has the following structure:
| — folder1
| | — file1.txt
| — file2.txt
It has a folder called “folder1” in which a file “file1.txt” resides. There is also a file called “file2.txt” in the root folder.
Suppose we have the first commit to create all the files. In the commit we create the following content in file1.txt and file2.txt:
## file1.txt has the following content:
this is file 1
## file2.txt has the following content:
this is file 2
Then we have the second commit that appends a new line to file1.txt:
## this is what file1.txt looks like after the second commit
this is file 1
And the third commit to appends a new line to file2.txt:
## this is what file2.txt looks like after the third commit
this is file 2
The commit history is
c2505fe (HEAD -> master) update file2
c780650 update file1
f3f57c9 initial commit
Our goal is to generate a zip file called “deployment-v1” that includes the changes from first to third commit.
Generate the list of new and modified files
The first half of the command obtains a list of all new or modified files between two commits. Since we know the starting point is the commit with ID
f3f57c9 and the ending point is
HEAD, we can have our first half:
git diff --name-only f3f57c9..HEAD --diff-filter=d
The option “name-only” tells the command to only generate the name of the files. The second option “diff-filter=d” instructs the command to exclude deleted files.
We have the following output immedidately:
Archive the generated files
We have the list of files to be archived now. We will then use the list of files for the second half of the command to create the zip file.
git archive --output=deployment-v1.zip HEAD $(git diff --name-only f3f57c9..HEAD --diff-filter=d)
We provide the file name “deployment-v1” in the “output” option. At this point the command is aware of the files to be archived, but how does it know up to which commit should the content of the files be updated to? This is where we provide the parameter “HEAD” as the reference point. That also means if we provide any other commit ID as the parameter, the content of the archived files to be different.
Finally we have a zip file called “deployment-v1.zip” with the created and modified files.