1

Ok I give up, I am a Bash noob.

This:

$ git log --no-walk --oneline 6980e6ecede8e188f434f6da669c2297f28decfe 458567536c1f20498da033cb0e42da74439ef12e

prints:

4585675 NNN bethDataFiles, allBethFiles belong to game/game/constants.py
6980e6e NNN bethDataFiles, allBethFiles belong to game/game/constants.py

This:

git log -g --pretty=format:'%ai %H' | awk '$0 >= "2016-04-13" && $0 <= "2016-04-15"'| cut -d' ' -f 4 | awk '!a[$0]++' | tr '\n' ' '

prints me a range of commits:

ba4ee4b099d23642e6cad56d9f41974f6e767781 1daaede0f4e11cae0e0bb00b9ebb43bba4f5671 ...

Now why on earth piping this command to git log as in:

git log -g --pretty=format:'%ai %H' | awk '$0 >= "2016-04-13" && $0 <= "2016-04-15"'| cut -d' ' -f 4 | awk '!a[$0]++' | tr '\r\n' ' ' | git log --format='%h %s %ai' --no-walk

only shows me the first commit:

ba4ee4b _load_active_plugins pre BAPI code - superseded by games.py API: 2016-04-14 19:38:41 +0200

?

$ git --version
git version 2.6.1.windows.1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361

3 Answers3

4

git log does not read any input from stdin. Try doing echo "abcd123" | git log --no-walk and you will notice that git log will ignore stdin. It will look for a commit hash specified as an argument, but there is none. Hence, it will use the default HEAD, and print the latest commit on your current branch.

To print ranges of commit, you could for example do:

If you know the first and last commit hash:

git log abcd123..4567abc

If you know the time interval:

git log --since="10 days ago" --until="5 days ago"

Or if you know the specific dates:

git log --since="2016-04-13" --until="2016-04-15"
Alderath
  • 3,761
  • 1
  • 25
  • 43
  • Thanks, this clears the confusion up but I want to print info on those specific commits that are not a continuous range. – Mr_and_Mrs_D May 19 '16 at 17:30
  • 2
    Actually, `git rev-list` *does* have a `--stdin` argument, and since `git log` and `git rev-list` share most of their code, it turns out `git log` has an (un-advertised) `--stdin` too. – torek May 19 '16 at 17:39
  • 1
    Too late to edit comment: I checked the documentation and `--stdin` is actually advertised. – torek May 19 '16 at 17:49
3

There's a general form with bash and Unix utilities:

... | ... | ... | xargs cmd

(xargs runs cmd more than once as needed after inserting stdin as arguments), or:

cmd $(... | ... | ...)

which runs the pipeline, then provides its output as arguments to cmd.

However, with git log you don't need this as it accepts --stdin to get it to read revision IDs from standard input.

I think we can simplify your pipeline (incidentally, I did not realize some versions of awk know how to compare dates directly; older awk did not):

git log -g --pretty=format:'%ai %H' | \
    awk '$0 >= "2016-04-13" && $0 <= "2016-04-15"' | \
    cut -d' ' -f 4 | awk '!a[$0]++' | tr '\n' ' '

We want the revisions to be one per line so there's no need for the tr. We can also use the original awk to check the uniqueness of the hash ID. So:

git log -g --pretty=format:'%ai %H' | \
    awk '$0 >= "2016-04-13" && $0 <= "2016-04-15" && !a[$4]++ { print $4 }' | \
    git log --no-walk --stdin

Incidentally, it's only because git log -g does a reflog walk (which may produce duplicate hashes) that we need the associative array a to discard repeat hashes.

(edited per comment, but still untested)

torek
  • 448,244
  • 59
  • 642
  • 775
  • "it's only because git log -g does a reflog walk (which may produce duplicate hashes) that we need the associative array a to discard repeat hashes" - yep I realized that. Thanks for cleaning up my noobish pipeline - the `tr` I had added cause I thought that the input being `\n` delimited might make a difference - it was me hitting in the dark – Mr_and_Mrs_D May 19 '16 at 17:51
  • `cut -d' ' -f 4` should still be required in the last example, is it not? – Josh Klodnicki Aug 24 '21 at 20:11
  • @JoshKlodnicki: not if I did it right. Note that this tests `a[$4]`, not `a[$0]`. `$4` is from `%ai %H` producing, e.g., `2021-08-16 12:15:44 -0700 225bc32a989d7a22fa6addafd4ce7dcd04675dbf`. Comparing with `$0` (rather than `$1 $2 $3` put together) seems a bit iffy unless the awk you're using explicitly says that it uses the date-and-time (and maybe offset, or not) and then stops, but I got that from the original post and haven't tested it carefully. – torek Aug 25 '21 at 07:55
  • 1
    @torek Yes, awk works fine, but `git log --stdin` expects a list of commit hashes (without the dates). I am suggesting adding `cut` *after* the awk, unless I am missing something. Of course, selecting the field within awk (`print $4`) would probably be even better. – Josh Klodnicki Aug 25 '21 at 13:42
  • 1
    @JoshKlodnicki: oh, I see, quite right! Well, that's what happens with untested code. :-) I'll edit the awk to add `{ print $4 }`... – torek Aug 25 '21 at 20:34
  • @torek Thank you for taking the time for a 5-year-old post! – Josh Klodnicki Aug 26 '21 at 12:35
2
  git log --format='%h %s %ai' --no-walk \
       $(git log -g --pretty=format:'%ai %H' \
             | awk '$0 >= "2016-04-13" && $0 <= "2016-04-15"'\
             | cut -d' ' -f 4 | awk '!a[$0]++' | tr '\r\n' ' '
        )

Or slightly better

  git log -g --pretty=format:'%ai %H' | \
        awk '$0 >= "2016-04-13" && $0 <= "2016-04-15"' |\
        cut -d' ' -f 4 | awk '!a[$0]++' | \
        xargs git log --format='%h %s %ai' --no-walk

But I wonder why don't you wish to use --since and --until options of git log ?

user3159253
  • 16,836
  • 3
  • 30
  • 56
  • Thanks this works but could you elaborate a bit on the differences on those 2 and why the second is better ? As to why I do use `--since` and co: http://stackoverflow.com/q/37311494/281545 – Mr_and_Mrs_D May 19 '16 at 17:36