22

How to generate changelog of commits groupped by date, in format:

[date today]
- commit message1
- commit message2
- commit message3
...
[date day+3]
- commit message1
- commit message2
- commit message3
...
(skip this day if no commits)

[date day+1]
- commit message1
- commit message2
- commit message3
... 
[date since]
- commit message1
- commit message2
- commit message3

Any git log command, or smart bash script?

takeshin
  • 49,108
  • 32
  • 120
  • 164

5 Answers5

29

Here is dirty, but working version of the script I came up with:

#!/bin/bash
# Generates changelog day by day
NEXT=$(date +%F)
echo "CHANGELOG"
echo ----------------------
git log --no-merges --format="%cd" --date=short | sort -u -r | while read DATE ; do
    echo
    echo [$DATE]
    GIT_PAGER=cat git log --no-merges --format=" * %s" --since=$DATE --until=$NEXT
    NEXT=$DATE
done
takeshin
  • 49,108
  • 32
  • 120
  • 164
  • 1
    Just use a pipe into the loop: `produce-and-sort-dates | while read DATE; do …; done`. Incidentally, you might want `GIT_PAGER=cat git log …` for the second one (to prevent *git log* from using a pager when the whole script’s output is going to a terminal). Also, you probably want to be consistent with `--no-merges`, otherwise you might get `[date]` headers without any commits if all the commits for a day were merges. – Chris Johnsen Jun 05 '10 at 20:36
  • Thank you Chris. I have updated the code. (Previously I was trying to add the pipe at the end of the loop) – takeshin Jun 05 '10 at 21:19
  • @takeshin great script. However there's an issue with the dates. Specifically, it aggregates today's commits into yesterday. I replaced the `GIT_PAGER` line with this and it's fixed: `GIT_PAGER=cat git log --no-merges --format=" * %s" --since="$DATE 00:00" --until="$DATE 23:59"` No need for `$NEXT` variable after this change – lsaffie Jul 15 '16 at 19:07
13

I couldn't get the accepted answer to handle today's commits as my setup didn't handle the NEXT variable properly on the first iteration. Git's log parameters will accept a time too, which removes the need for a NEXT date:

#!/bin/bash
# Generates changelog day by day
echo "CHANGELOG"
echo ----------------------
git log --no-merges --format="%cd" --date=short | sort -u -r | while read DATE ; do
    echo
    echo [$DATE]
    GIT_PAGER=cat git log --no-merges --format=" * %s" --since="$DATE 00:00:00" --until="$DATE 24:00:00"
done
kristianlm
  • 1,071
  • 1
  • 10
  • 14
  • This is really nice. The only thing is that echo [$DATE] doesn't work cause it try to evaluate an expression or whatever. So just remove the brackets and it's fine – Yanis Mar 03 '15 at 09:40
  • the good one. thanks – Vzans Apr 09 '23 at 16:36
1

git log has --since and --until, it shouldn't be hard to wrap some stuff around that.

Daenyth
  • 35,856
  • 13
  • 85
  • 124
1

That would require most certainly some kind of script.
A bit like this commandline-fu

for k in `git branch|perl -pe s/^..//`;do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k|head -n 1`\\t$k;done|sort -r

(not exactly what you are after but can gives you an idea nonetheless)

I know about GitStats which has also data organized by date (but not the commit messages)


Note: the git branch part of this command is ill-fitted for scripting, as Jakub Narębski comments.
git for-each-ref or git show-ref are natural candidate for scripting commands, being plumbing commands.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for this informative answer. One more thing which I need to know: How to list all the commits for the specific, single day: `git log --since="2010-06-02" --until="2010-06-02"` list nothing. – takeshin Jun 04 '10 at 19:32
  • @takeshin: did you try `git log --since="2010-06-02" --until="2010-06-03"` ? (from one day - 02 - to another - 03 -) – VonC Jun 04 '10 at 19:38
  • @VonC, yeah, but in the simple loop I know only the date, not the next date. – takeshin Jun 04 '10 at 19:40
  • @VonC, My plan is: to generate unique list of dates: `git log --pretty="format: %ad" --date=short | uniq` and iterate them in the loop, similar to this from your answer. – takeshin Jun 04 '10 at 19:43
  • @takeshin: may be by combining some kind of datetime operation to set the appropriate variables (oneDay, OneDayPlusOne), like in Perl for instance: http://datetime.perl.org/index.cgi?FAQBasicUsage and http://datetime.perl.org/?Modules – VonC Jun 04 '10 at 22:54
  • 1
    Don't use `git branch` output for scripting; it is user-interface command, and its output can change. Use `git show-ref` or `git for-each-ref` which are intended for scripting. – Jakub Narębski Jun 05 '10 at 12:32
  • Case in point about not using `git branch`: This breaks when you're in the middle of a rebase. – Michael Deardeuff Mar 06 '19 at 19:07
0

I wrote a script in python to create a week-by-week git log.

You could easily change it to days, months, etc by changing the timedelta

https://gist.github.com/NahimNasser/4772132