git diff --no-index but with multiple files

6,729

Solution 1

Since git diff --no-index accepts also two directories and compare these, you could always write a wrapper script around that, copying your files into two temporary directories.

Other than that, I don't know of a diff tool that accepts multiple pairs of files to compare. Even diff only accepts a single pair of files, or a directory and a list of files.

Solution 2

This is basically two context-dependent versions of Jaap's answer, each with a bonus:

Before running git diff --no-index, you may want to set diff.colorMoved in the Git config. Alternatively, you can include a --color-moved option instead of setting it globally.

diff.colorMoved settings use a different line color when lines removed from one place show up elsewhere in the diff... whether they moved within the file or moved to another file, like in a refactor.

Complete or almost complete sets

You have some files in a directory, current-version, that you want to compare to some other files. If the set of files you want to compare them to in new-version is nearly identical in content, just use Jaap's suggestion:

git diff --no-index current-version/ new-version/

Specific files to compare

If there are only a handful of files in one version and lots of files in the other, like so,

┌ current-project
| ├ (various folders)
| └ src
|   ├ (various files)
|   ├ foo.c
|   └ bar.c
└ proposed-replacements
  ├ new-foo.c
  └ new-bar.c

...you can try to let Git's rename detection do the work. I don't know what version of Git adds the degree of rename tracking that is necessary to do this (I'm using v2.18). Also, the testing I did was on a pretty trivial set of files.

You don't really want to see that the majority of the files are "missing" in proposed-replacements. Also, you don't want to bother giving proposed-replacements' files the same name/path as they appear in current-project, so you leave them where they were and put in a filter that includes only renamed and modified files.

git diff --no-index --diff-filter=RM current-project/ proposed-replacements/
diff --git a/current-project/src/foo.c b/proposed-replacements/new-foo.c
similarity index 65%
rename from current-project/src/foo.c
rename to proposed-replacements/new-foo.c
index dd51990..64445b1 100644
--- a/current-project/src/foo.c
+++ b/proposed-replacements/new-foo.c
@@ -1,4 +1,4 @@
 octopus
 cow
-dog
 tiger
+flamingo

diff --git a/current-project/src/bar.c b/proposed-replacements/new-bar.c
similarity index 87%
rename from current-project/src/bar.c
rename to proposed-replacements/new-bar.c
...
Share:
6,729

Related videos on Youtube

alecbz
Author by

alecbz

alecb.dev

Updated on September 18, 2022

Comments

  • alecbz
    alecbz over 1 year

    I really like git diff's output format, and I use it a lot as git diff --no-index to compare arbitrary non-git-related files. But as far as I can tell when using --no-index you can provide only a single pair of files. I'd really like to be able to pass it multiple pairs, like:

    git diff --no-index a.new a.old b.new b.old
    

    And get the kind of output you'd get by running git diff in a repo:

    diff --git a/a b/a
    index e965047..ce01362 100644
    --- a/a
    +++ b/a
    @@ -1 +1 @@
    -Hello
    +hello
    diff --git a/b b/b
    index 2b60207..dd7e1c6 100644
    --- a/b
    +++ b/b
    @@ -1 +1 @@
    -Goodbye
    +goodbye
    

    Is there any way to do this with git diff, or a similar tool?

  • alecbz
    alecbz over 8 years
    Ooh, I didn't know it accepted directories. That's probably good enough for me. I would prefer a solution where the file names didn't necessarily have to match (ie, in the two directories), but I can probably live with that.
  • Michael
    Michael almost 6 years
    @Alec With the advent (years later in v2.15) of diff.colorMoved in the config options, the filenames matching should matter less. There will still be + and - lines, but they'll be colored to show that they came from somewhere else in the same diff.
  • Aktau
    Aktau almost 6 years
    @Michael I've tried to find it but I couldn't find how to do what OP wants with regular GNU diff(1) either. I have version v3.6 (far newer than the v2.15 you mention). I can only seem to pass it FILE1 FILE2, not FILE1 FILE2 FILE3 ... (in pairs).
  • Michael
    Michael almost 6 years
    @Aktau The version I mentioned was for Git (and its associated git diff). See my answer for an extended explanation.
  • Aktau
    Aktau almost 6 years
    Thanks for the answer @Michael. My problem (and the OPs problem, I guess) is that our files aren't tracked in Git. We just like using git-diff(1) for its output.