Export only modified and added files with folder structure in Git
Solution 1
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id
git diff-tree -r $commit_id
:Take a diff of the given commit to its parent(s) (including all subdirectories, not just the top directory).
--no-commit-id --name-only
:Do not output the commit SHA1. Output only the names of the affected files instead of a full diff.
--diff-filter=ACMRT
:Only show files added, copied, modified, renamed or that had their type changed (eg. file → symlink) in this commit. This leaves out deleted files.
UPDATE FROM THE COMMENT:
Base on the question context and the comments below, with the following command, you can get the ACMRT
files as a .tar
file with their folder structure.
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
Solution 2
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | xargs tar -rf mytarfile.tar
Just to round this out, here is the command piped to tar. This exports the files into a tar archive.
Solution 3
Here is a one-line command that works on Windows 7. Run it from your repository's top-level folder.
for /f "usebackq tokens=*" %A in (`git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT HEAD~1 HEAD`) do echo FA|xcopy "%~fA" "C:\git_changed_files\%A"
- echo FA answers the inevitable xcopy question about whether you're copying a file or a directory (file), and the possible question about overwriting a file (overwrite All)
- usebackq allows us to use the output from our git command as the input to our do clause
- HEAD~1 HEAD gets all differences between the previous commit and the current HEAD
- %~fA transforms the git output into fully qualified paths (needed to change forward slashes to backslashes)
- C:\git_changed_files\ is where you will find all the files that are different
Solution 4
if your commit hash is for example a9359f9, this command :
git archive -o patch.zip a9359f9 $(git diff --name-only a9359f9^..a9359f9)
will extract the files modified in the commit and place them in patch.zip while keeping the project directory structure intact.
a bit verbose, the commit hash is mentioned three times, but it seems to work for me.
got it here : http://tosbourn.com/2011/05/git/using-git-to-create-an-archive-of-changed-files/
Solution 5
You can export diff using Tortoise Git to MS Windows:
I right click and select TortoiseGit > Show Log and Log Messages will be open.
Select two revisions and compare it. Difference between will be open.
Select the files and Export selection to ... to a folder!
Michael Kuhinica
Commands electronic brains through words and syntax.
Updated on September 20, 2021Comments
-
Michael Kuhinica over 2 years
I would like to get a list of modified and added files in an specific commit so that I can export them and generate a package with the file structure.
The idea is to get the package and extract it on the server. For many reasons I can't create a hook to pull the repo automatically and the easiest way I have to keep the server updated is generating this package.
-
Michael Kuhinica over 13 yearsNow I just have to find ou a way to glue the result of this command with tar! Thank you!
-
Nathan Fig about 10 yearsWhen I saw that mess of symbols I did not expect it to work without extensive tweaking... but it worked on the first try, thanks.
-
evolutionxbox over 9 yearsCan this be done for multiple commits into one tar file?
-
ADTC over 9 yearsI think I can use
function
in PowerShell to reduce the command to just a function name and use$args
to pass in the commit hash just once. In *nix, you can probably use shell-scripting to achieve the same effect. -
Ricardo Martins over 9 yearsWhen trying to add multiple commits to the same tar file, sometimes tar creates filename.ext again with other name (filename1.ext). I realize that if I use zip, I can add and overwrite the file if it exists in the zip... You just need to replace the xargs with xargs zip -r0 myzipfile.zip $1
-
Matthieu Sadouni over 9 years@Taverneiro You can pipe it to the tar command given in this answer, eg. for a tgz file :
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
-
deanpodgornik about 9 yearsMan... I own you a beer :)
-
Ben Sewards almost 9 yearsjust a note that git archive doesn't work for a range of revisions
-
buddybubble over 8 yearsa little heads up for all the guys who are (like me) not very familiar with windows batch files: If you want to use the above command in a batch file, you will need to replace %A with %%A inside the for loop
-
ADTC over 8 years@BenSewards for range of commits between commit1 and commit2 (inclusive of later commit, exclusive of earlier commit; order doesn't matter) just do
git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1 commit2)
. The commit passed to thearchive
command can be any arbitrary commit (most likely either the HEAD or the later commit), and the files are pulled as if they are checked out at that commit stage. The commit1 and commit2 passed todiff
are only used to generate the list of files to pull - they do not affect the version of files pulled. -
ADTC over 8 yearsWhat? LOL. Just use the git archive - git diff combo (Nicolas' answer). Much easier and straightforward. (I honestly don't know what's happening here.)
-
ADTC over 8 yearsAdditional tip: If you want to combine the changed files of multiple ranges of commits into one archive, just repeat the
diff
command with a semicolon:git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1A commit1B; git diff --name-only commit2A commit2B; git diff --name-only commit3A commit3B)
-
Boggin almost 8 yearsDue to spaces in path names I had to use a pipe to xargs handling the NUL
git diff -z --name-only commit1 commit2 | xargs -0 git archive -o patch.zip HEAD
-
Erdal G. almost 8 yearsIs xargs needed here? I know it is for stuff like rm, but I thought tar could handle as many files as you want.
-
Alberto Alexander Rodriguez almost 7 yearsI've just detected a WEIRD issue: if I try the code above it works like a charm. But I change the tar -rf test.tar for tar -zcf test.tar.gz, then the resulting file is missing several files. What can be causing this difference in result?
-
morteza khadem over 6 yearsthis code is great, but i want export files and directories with submodules your code only worked with main repository and if submodules changed your code say submodule folder deleted!
-
mems about 6 yearsBe carefull with this answer, this take diff files but as the current version of the current branch
-
Navin prasad over 5 yearsWhile executing this command in the windows slave machine, I'm getting the following error "'xargs' is not recognized as an internal or external command, operable program or batch file."
-
Navin prasad over 5 yearsWhile executing this command in the windows slave machine, I'm getting the following error "'xargs' is not recognized as an internal or external command, operable program or batch file."
-
Simon East about 5 yearsWarning: this will copy files from your working copy, which may not actually match what's in HEAD (or whatever commit hash you replace it with)
-
user1169587 almost 5 years@mems assume the diff is fileA, then how to get the $commit_id version of fileA instead of the current version of fileA?
-
user1169587 almost 5 years@ADTC cannot use git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1A..commit3B)? but need to repat the diff command with a semicolon?
-
dythim almost 5 yearsDefinitely. So many answers to this had linux-only commands, and a lot did not capture working changes, only changes which had been committed. Glad this was posted!
-
ADTC over 4 years@user1169587 your version is for a single range of commits (ALL commits from 1A to 3B). I was talking about combining multiple ranges of commits (1st range 1A to 1B; 2nd range 2A to 2B; 3rd range 3A to 3B; etc) so the commits outside these ranges would be ignored.
-
Rodion Bykov almost 4 yearsGreat stuff, but works with only CMD not Powershell, -v°v-
-
Michael Li over 2 yearsperfect. it solve my question.
-
Nathan Rona about 2 yearsYou can create a zip-file through git archive by: git archive -o upadate.zip HEAD $(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT <comit_id>)