0

I have a node script outputting a space-separated list of files to a plain text file, .git-files-to-diff, and then I'm trying to use that file to create a "proper" git diff in my bash script.

Something like this:

node ./shell-scripts/pre-commit/stage1.mjs;
git diff -- $(cat .pre-commit-cache/.git-files-to-diff)
node ./shell-scripts/pre-commit/stage2.mjs;

The rationale here is to get the beautiful git diff output from delta. I couldn't figure out anyway to execute git diff from a node script, so I'm exiting the node script, running it in bash, then resuming in node (rabbit hole)

My file is something like this - all file specs are quoted and separated by a space:

".does-not-exist1" ".*ignore"

When I run just cat file it works as expected - just prints list of files... but otherwise, doesn't print anything, no error, nothing...

Reproduce:

cd ~/repos;
rm -rf git-diff-issue;
mkdir git-diff-issue;
cd git-diff-issue;
git init;
touch README.md;
touch other.md;
touch .eslintignore;
touch .git-diff-list;
ls -a;
echo "readme" > README.md;
echo "other" > other.md;
echo "node_modules" > .eslintignore;
echo '".*ignore" "README.md"' > .git-diff-list;
echo "cat file:";
cat .git-diff-list;
git add --intent-to-add README.md .eslintignore .git-diff-list;
echo "full diff:";
git diff;
echo "targeted diff:";
git diff -- ".*ignore" "README.md";
echo "targeted diff with cat:";
git diff -- $(cat .git-diff-list);

screenshot of reproduction script

Text version of reproduction script running on my machine:

Initialized empty Git repository in /Users/devinrhode2/repos/git-diff-issue/.git/
.              ..             .eslintignore  .git           .git-diff-list README.md      other.md
cat file:
".*ignore" "README.md"
full diff:
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.git-diff-list b/.git-diff-list
new file mode 100644
index 0000000..524215d
--- /dev/null
+++ b/.git-diff-list
@@ -0,0 +1 @@
+".*ignore" "README.md"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8178c76
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+readme
targeted diff:
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8178c76
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+readme
targeted diff with cat:
git-diff-issue $

Notice there is no output on the final command.

Devin Rhode
  • 23,026
  • 8
  • 58
  • 72
  • 1
    There's a simple diagnostic to use here: replace whatever command isn't working (in this case `git diff --`) with `file` or `wc` for instance. Try that and observe the output. (Pay close attention to the error messages: what file(s) are these commands trying to open, that don't exist? What extra characters do you need to get rid of?) – torek Dec 09 '21 at 03:24
  • So you're implying I should remove the quotes. I removed all the double quotes (including for .*ignore). And it works. That is so weird. I don't get it, I don't like it, but it works, thanks! If you want to put some sort of answer I can give you points :) – Devin Rhode Dec 09 '21 at 03:36
  • The quotes break things because expansion results aren't parsed as syntax. You don't **want** expansion results to be parsed as syntax; if they were it would be impossible to safely handle untrusted data in shell. So because they aren't parsed as syntax the quotes become literal and you only match files where the quotes are part of the actual file name, and no such files exist. – Charles Duffy Dec 09 '21 at 03:48
  • 1
    For a full explanation read [BashFAQ #50](https://mywiki.wooledge.org/BashFAQ/050). This is a very common question; the duplicates may not be talking about git specifically, but they exist and the knowledge base is full of 'em. (When I have a minute to sit down at a computer I'll find one if nobody else has done so previously). – Charles Duffy Dec 09 '21 at 03:51
  • 2
    (Aside: please tag for one or the other of bash or zsh, not both at once; they're not mutually compatible, and an answer written for one is often subtly wrong for the other). – Charles Duffy Dec 09 '21 at 03:55
  • [BashParser](https://mywiki.wooledge.org/BashParser) is a bit oversimplified, but it's a good place to start with respect to understanding how bash operates. Notice how quotes are handled in step 2, **before** expansions happen in step 5. By the time expansions have happened, quote processing is done and gone, and not going to happen again (unless you force it to, which [causes its own problems](https://mywiki.wooledge.org/BashFAQ/048)). – Charles Duffy Dec 09 '21 at 04:10
  • The funny thing is, other git commands will typically exit non-zero if a filespec doesn't match anything. I think git diff here should probably be piping something to stderr... – Devin Rhode Dec 09 '21 at 18:40

0 Answers0