Apologies, it was easy:
git archive -o changed.zip $COMMIT $(git diff --name-only $COMMIT $COMMIT^ | sed ‘s/.*/"&"/’)
name-only diff between branches shows changes, but regular diff for any specific file is empty
Feature request: `gh pr diff <ref> --name-only`
Question: diff --name-only command implementation
git - How to list only the names of files that changed between two commits - Stack Overflow
Edit [Solved]: As per u/ppww's comment, I wasn't in the root directory of the repo, so my paths were invalid.
If I do the following command, I get a really long list of changed files. Most of which I expect, but some shouldn't have changed:
git diff --name-only myBranch1 myBranch2
For example, one of the files mentioned in the diff is src/general/Log.php
But if I use the following command to check the difference in that particular file, it just prints an empty line and exits the diff:
git diff myBranch1 myBranch2 -- src/general/Log.php
Trying to diff a directory instead of a file does the same thing.
I did however confirm that if I do a full diff across the two branches (not name-only) it does actually show the differences, but as there is a lot in there, most of which isn't what I'm looking for, it would be really tedious to view the whole diff.
What am I doing wrong?
git diff --name-only SHA1 SHA2
where you only need to include enough of the SHA hash to identify the commits. The order of the SHAs does not matter. The output (which includes the relative path, not just the file name) follows this format:
dir 1/dir 2/filename.ext
dir 3/dir 4/other filename.ext
You can also do, for example
git diff --name-only HEAD~10 HEAD~5
to see the differences between the tenth latest commit and the fifth latest (or so).
git diff --name-status [SHA1 [SHA2]]
is like --name-only, except you get a simple prefix telling you what happened to the file (modified, deleted, added...)
git log --name-status --oneline [SHA1..SHA2]
is similar, but commits are listed after the commit message, so you can see when a file was changed.
if you're interested in just what happened to certain files/folders you can append
-- <filename> [<filename>...]to thegit logversion.if you want to see what happened for a single commit, call it SHA1, then do
git log --name-status --oneline [SHA1^..SHA1]
File status flags:
| Flag | Name | Meaning |
|---|---|---|
M |
modified | File has been modified |
C |
copy-edit | File has been copied and modified |
R |
rename-edit | File has been renamed and modified |
A |
added | File has been added |
D |
deleted | File has been deleted |
U |
unmerged | File has conflicts after a merge |
Building on torek's answer, I was able to achieve this in one line using the --line-prefix flag:
git diff --name-only --line-prefix=`git rev-parse --show-toplevel`/ HEAD release
Just add the top level yourself:
git rev-parse --show-toplevel
prints the path to the Git repository.
Feed the diff --name-only output through, e.g., sed -e "s,^,$path," (assuming no commas in your path name):
git-diff-with-abs-path() {
local path
path=$(git rev-parse --show-toplevel) &&
git diff --name-only "$@" | sed "s,^,$path/,"
}
Edit #2: for --name-status, the name comes after a literal tab, so:
git-diff-with-abs-path() {
local path tab=$'\t'
path=$(git rev-parse --show-toplevel) &&
git diff --name-status "$@" | sed "s,$tab,$tab$path/,"
}
Fancy this up a bit and you can make it pick --name-only or --name-status out of the $@ part and compute the correct sed expression, rather than hardcoding --name-only or --name-status.
Try the following command, which I have tested:
$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY
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
-zto withgit diff --name-onlymeans to output the list of files separated with NUL bytes instead of newlines, just in case your filenames have unusual characters in them.The
-0toxargssays to interpret standard input as a NUL-separated list of parameters.The
-IREPLACEis needed since by defaultxargswould append the parameters to the end of thersynccommand. Instead, that says to put them where the laterREPLACEis. (That's a nice tip from this Server Fault answer.)The
-aparameter torsyncmeans to preserve permissions, ownership, etc. if possible. The-Rmeans 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.)