1

I am trying to identify all commits with a message not starting with [core]. These are my failed attempts:

  1. Simple approach

    git rev-list --grep '^(?!(\[core\]).).+' "branch1...branch2"
    
    • empty result
  2. Enable extended flag

    git rev-list -E --grep '^(?!(\[core\]).).+' "branch1...branch2"
    
    • Error message fatal: command line, '^(?!(\[core\]).).+': Invalid preceding regular expression.

    • It seems that a negative look-ahead is not supported by git grep.

  3. Comparing the list of all commits to the list of those with the tag (cf. this answer):

    git rev-list "branch1...branch2" | grep -Fxv <(git rev-list -E --grep '^\[core\].+' "branch1...branch2")
    
    • Results in sh: syntax error near unexpected token `('

P.S: I cannot upgrade to Git 2.x, so --invert-grep is not an option

Community
  • 1
  • 1
PhilLab
  • 4,777
  • 1
  • 25
  • 77
  • The failure in three is the space you added between `<` and `(`. Remove that. But if that regexp didn't work with `rev-list` in the first two attempts why do you think it'll work in the third attempt? – Etan Reisner Jun 12 '15 at 11:22
  • oh, I actually used the negative equivalent in the third attempt. That's the problem when you try to provide a minimal example for your question and not your original problem :-). Removing the space did not change anything – PhilLab Jun 12 '15 at 11:25
  • 1
    What shell are you using? `<(...)` is process substitution and should work fine in bash but won't in ash/dash/csh/etc. – Etan Reisner Jun 12 '15 at 11:35
  • Ok, it seems that the process substitution is indeed the problem. I am using the git bash under Windows. When I execute the command in a git hook, the error is ``cannot make pipe for process substitution: Function not implemented`` – PhilLab Jun 12 '15 at 11:50
  • Yeah, it seems that the bash in git-bash doesn't support process substitution. Command substitution works though. Try the snippet in my answer? – Etan Reisner Jun 12 '15 at 12:44

2 Answers2

1

Something like this might work.

git rev-list "branch1...branch2" --not $(git rev-list --grep '^\[core\]')

Select the revisions in that list that match the pattern you don't want and then use --not to negate that list of revisions in another call to rev-list.

You could also avoid the process substitution in your third attempt by using an actual file like this:

git rev-list -E --grep '^\[core\].+' "branch1...branch2" > core.list
git rev-list "branch1...branch2" | grep -Fxvf core.list
Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
  • This results first the usage option of git rev-list (``--not`` seems to be unknown) and then the hashes of all commits in the range. Which git version is needed for that? I have to stay below 2.0 for now. – PhilLab Jun 12 '15 at 14:24
  • 1
    I'm using 1.8.2.1 but it is also in the help for 1.7.1. What version are you using? But in a quick test of the theory this list may not have worked out quite correctly and I'm not sure why. – Etan Reisner Jun 12 '15 at 17:02
  • I've now solved the problem using a bash file (see http://stackoverflow.com/a/30829547/1531708) but since I'm not completely satisfied, I still leave this question unanswered. – PhilLab Jun 14 '15 at 12:50
  • That's the same as my second solution isn't it? Only with a shell variable instead of a temporary file (which may have line length limit problems if the list of valid commits is huge but is probably fine in practice). – Etan Reisner Jun 14 '15 at 16:56
1

If it fits your requirements to use a batch file, this is one solution:

#!/bin/sh
range="branch1...branch2"
validCommits=`git rev-list -E --grep '^\[core\]' "$range"`
badCommits=`git rev-list "$range" | grep -Fxv "$validCommits"`
PhilLab
  • 4,777
  • 1
  • 25
  • 77
  • This doesn't actually work does it? That's going to fail to ignore any of the commits correctly because you are only giving grep a single argument (of all the commits split by newlines as the search term). – Etan Reisner Jun 14 '15 at 16:58
  • It is indeed comparable to your second solution and the reason why it works is that $validCommits is a new-line separated list of commits. Wrapping it with `""` preserves them and the `grep -Fx` enables matching per line – PhilLab Jun 15 '15 at 15:30
  • It certainly does seem to work though I cannot for the life of me understand why. `-x` means matches (from the pattern) must match an entire line in the source text. I don't see what is causing grep to split the input into lines so that they can match independently... unless that's an accident or a side-effect of the per-line nature of how matches work in grep. But ok. – Etan Reisner Jun 15 '15 at 16:20
  • Also `-x` doesn't seem to affect that splitting behavior but is important if you want only whole line matches (I'm not sure you actually care about that in this case but it is certainly more correct to specify that you do). – Etan Reisner Jun 15 '15 at 16:21