I like the format of git diff
and the diffstat, but sometimes I would like to use it outside of any git repository, on two arbitrary directories. Doing this introduces some undesired extra directory prefixes into the output, though, which I am having trouble getting rid of.
old
(not in any repo).new
and make some changes.git diff -p --stat old/ new/
This almost works, but unfortunately the diffstat includes {old => new}/
as a path prefix and the diff headers show a/old/...
and b/new/...
, for example:
{old => new}/src/config.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/old/src/config.h b/new/src/config.h
index 8158fcc..7ec16df 100644
--- a/old/src/config.h
+++ b/new/src/config.h
@@ -66,7 +66,7 @@
...
I want the diff to be entirely relative to the directories specified on the command line, thus not naming them in the resulting output at all (i.e. {old => new}/
should not appear and the diff headers should only be a/...
and b/...
). I do want it to include the relative path within each directory (e.g. src/
). i.e. the "correct" output would be:
src/config.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/config.h b/src/config.h
index 8158fcc..7ec16df 100644
--- a/src/config.h
+++ b/src/config.h
@@ -66,7 +66,7 @@
...
I would also like this to work even if old
and new
are not sibling directories -- e.g. I might be comparing old/
and ../foo/bar/new/
, and the output should be exactly identical to the above if they have the same contents.
If, instead of old
and new
, I name the directories a
and b
(and ensure they're siblings), then I can get the patch part to appear correctly by adding --no-prefix
, but this still outputs the wrong diffstat. (This also works if I instead run diff -ur a/ b/
, but then there's no diffstat, and it doesn't work with different directory names.)
Is there any trick I'm missing to accomplish this? Note that I'm on a Windows system, so I only have the limited set of posix tools that come with Git for Windows.
The only working solution to this problem that I have found is to follow the suggestion to use sed by @LeGEC :
diff -u $OLD $NEW | sed -e "s@$OLD/@a/@;s@$NEW/@b/@"
Or with git diff
:
git diff --no-index $OLD $NEW | sed -e "s@$OLD/@@;s@$NEW/@@"
This is still somewhat fragile as it relies on picking a delimiter that's unlikely to appear in either $OLD or $NEW, and these directory names must not appear anywhere in the actual patch content (other than the headers) or it will be corrupted. The latter point means that it's probably a bad idea to actually use "old" and "new" as given in the question; you should use some more unique name. (Though it does at least require a trailing slash, to reduce spurious matches somewhat.)
It would be possible to design a more complex regex that ensures replacement only in the header, bearing in mind that each appears in two contexts. That's left as an exercise to the reader, since I just use the unique directory names.