Git diff --name-only and copy that list
GitGit Problem Overview
I just want to get a list of changed files between two revisions, which is simple:
git diff -–name-only commit1 commit2 > /path/to/my/file
But, what should I write, if I want copy all that listed files to another place? And I need completely identical directory structure for copied files.
For example, I have modified and added files:
/protected/texts/file1.txt
/protected/scripts/index.php
/public/pics/pic1.png
I want to have in /home/changes/
all those changed and added files:
/home/changes/protected/texts/file1.txt
/home/changes/protected/scripts/index.php
/home/changes/public/pics/pic1.png
Git Solutions
Solution 1 - Git
Try the following command, which I have tested:
$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY
Solution 2 - Git
The following should work fine:
git diff -z --name-only commit1 commit2 | xargs -0 -IREPLACE rsync -aR REPLACE /home/changes/protected/
To explain further:
-
The
-z
to withgit diff --name-only
means to output the list of files separated with NUL bytes instead of newlines, just in case your filenames have unusual characters in them. -
The
-0
toxargs
says to interpret standard input as a NUL-separated list of parameters. -
The
-IREPLACE
is needed since by defaultxargs
would append the parameters to the end of thersync
command. Instead, that says to put them where the laterREPLACE
is. (That's a nice tip from this Server Fault answer.) -
The
-a
parameter torsync
means to preserve permissions, ownership, etc. if possible. The-R
means to use the full relative path when creating the files in the destination.
Update: if you have an old version of xargs
, you'll need to use the -i
option instead of -I
. (The former is deprecated in later versions of findutils
.)
Solution 3 - Git
Here's a one-liner:
List changed files & pack them as *.zip:
git diff --name-only | zip patched.zip -@
List last committed changed files & pack them as *.zip:
git diff --name-only HEAD~ HEAD | zip patched.zip -@
Solution 4 - Git
zip update.zip $(git diff --name-only commit commit)
Solution 5 - Git
#!/bin/bash
# Target directory
TARGET=/target/directory/here
for i in $(git diff --name-only)
do
# First create the target directory, if it doesn't exist.
mkdir -p "$TARGET/$(dirname $i)"
# Then copy over the file.
cp -rf "$i" "$TARGET/$i"
done
https://stackoverflow.com/users/79061/sebastian-paaske-t%c3%b8rholm
Solution 6 - Git
It works perfectly.
git diff 1526043 82a4f7d --name-only | xargs zip update.zip
git diff 1526043 82a4f7d --name-only | xargs -n 10 zip update.zip
Solution 7 - Git
No one has mentioned cpio
which is easy to type, creates hard links, and handles spaces in filenames:
git diff --name-only $from..$to | cpio -pld outdir