git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[BUG] regarding `git add -p` and files containing wildcard characters

From
Uunixway.drive@gmail.com <unixway.drive@gmail.com>
Date
Dec 9, 2016, 01:46 UTC
Message-ID
<c9876671-6252-5dfa-18df-a6719dc6834c@gmail.com>

`git add -p` behaves incorrectly if modified file contains any wildcard character. Consider 'random.diff' (attached). For this, interactive 'add' would first ask to add hunk with two diff headers (or with some "random" header at the end):

     $ git add -p
     diff --git a/Random * b/Random *
     index 01e79c3..01f03ff 100644
     --- a/Random *
     +++ b/Random *
     @@ -1,3 +1,5 @@
      1
     +  a
      2
     +  b
      3
     diff --git a/Random Crap b/Random Crap
     index 01e79c3..b4373d5 100644
     --- a/Random Crap
     +++ b/Random Crap
     Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]? y
Then it will ask for some irrelevant hunk:
     @@ -1,3 +1,5 @@
      1
     +  whoa
      2
     +  dude
      3
     Stage this hunk [y,n,q,a,d,/,K,g,s,e,?]? y

…and, if confirmed, apply it to the wildcard-named file instead of what was confirmed for staging before:

     $ git diff --cached
     diff --git a/Random * b/Random *
     index 01e79c3..283ac91 100644
     --- a/Random *
     +++ b/Random *
     @@ -1,3 +1,5 @@
      1
     +  whoa
      2
     +  dude
      3

Then one can just repeat this over and over again (unless safely named files are resolved first):

     $ git add -p
     diff --git a/Random * b/Random *
     index 283ac91..04c92f1 100644
     --- a/Random *	
     +++ b/Random *	
     @@ -1,5 +1,5 @@
      1
     -  whoa
     +  a
      2
     -  dude
     +  b
      3
     diff --git a/Random Crap b/Random Crap
     index 01e79c3..283ac91 100644
     --- a/Random Crap	
     +++ b/Random Crap	
     Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

The problem is that `git-diff-files` does some globbing on the 'path' arguments on its own and has no option to disable that (and `git-add--interactive`'s `run_cmd_pipe` already handles all other sorts of unsafe characters like spaces and backticks well).

     $ strace -f -e trace=execve git add -p
     …
     [pid  1713] execve("/usr/lib/git-core/git",
         ["git", "diff-files", "-p", "--", "Random *"],
     [/* 36 vars */]) = 0
     …
     $ git diff-files -- 'Random *'
     :100644 100644 … … M	Random *
     :100644 100644 … … M	Random Crap

For all the eager people (although I doubt if anybody else is lazy enough to not bother with file names like these), this could be easily worked around like this:

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index ee3d812..358d877 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -2,3 +2,3 @@

-use 5.008;
+use 5.014;
  use strict;
@@ -761,3 +761,5 @@ sub parse_diff {
         }
-       my @diff = run_cmd_pipe("git", @diff_cmd, "--", $path);
+       my @diff = run_cmd_pipe("git", @diff_cmd, "--", (
+               $path =~ s#[\[*?]#\\$&#gr
+       ));
         my @colored = ();

(Although a `git-diff-files` option is clearly a better solution that 
would cover tools other than `git-add--interactive` as well.)


diff --git a/Random * b/Random *
index 01e79c3..04c92f1 100644
--- a/Random *	
+++ b/Random *	
@@ -1,3 +1,5 @@
 1
+  a
 2
+  b
 3
diff --git a/Random Crap b/Random Crap
index 01e79c3..283ac91 100644
--- a/Random Crap	
+++ b/Random Crap	
@@ -1,3 +1,5 @@
 1
+  whoa
 2
+  dude
 3
Next: Jeff King
Message 1 of 2 in “[BUG] regarding `git add -p` and files containing wildcard characters”
  1. unixway.drive@gmail.comDec 9, 2016
  2. Jeff KingDec 9, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.