--- /dev/null
+#!/bin/sh
+
+test_description='various tests of reflog walk (log -g) behavior'
+. ./test-lib.sh
+
+test_expect_success 'set up some reflog entries' '
+ test_commit one &&
+ test_commit two &&
+ git checkout -b side HEAD^ &&
+ test_commit three &&
+ git merge --no-commit master &&
+ echo evil-merge-content >>one.t &&
+ test_tick &&
+ git commit --no-edit -a
+'
+
+do_walk () {
+ git log -g --format="%gd %gs" "$@"
+}
+
+sq="'"
+test_expect_success 'set up expected reflog' '
+ cat >expect.all <<-EOF
+ HEAD@{0} commit (merge): Merge branch ${sq}master${sq} into side
+ HEAD@{1} commit: three
+ HEAD@{2} checkout: moving from master to side
+ HEAD@{3} commit: two
+ HEAD@{4} commit (initial): one
+ EOF
+'
+
+test_expect_success 'reflog walk shows expected logs' '
+ do_walk >actual &&
+ test_cmp expect.all actual
+'
+
+test_expect_failure 'reflog can limit with --no-merges' '
+ grep -v merge expect.all >expect &&
+ do_walk --no-merges >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'reflog can limit with pathspecs' '
+ grep two expect.all >expect &&
+ do_walk -- two.t >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'pathspec limiting handles merges' '
+ # we pick up:
+ # - the initial commit of one
+ # - the checkout back to commit one
+ # - the evil merge which touched one
+ sed -n "1p;3p;5p" expect.all >expect &&
+ do_walk -- one.t >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure '--parents shows true parents' '
+ # convert newlines to spaces
+ echo $(git rev-parse HEAD HEAD^1 HEAD^2) >expect &&
+ git rev-list -g --parents -1 HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'walking multiple reflogs shows all' '
+ # We expect to see all entries for all reflogs, but interleaved by
+ # date, with order on the command line breaking ties. We
+ # can use "sort" on the separate lists to generate this,
+ # but note two tricks:
+ #
+ # 1. We use "{" as the delimiter, which lets us skip to the reflog
+ # date specifier as our second field, and then our "-n" numeric
+ # sort ignores the bits after the timestamp.
+ #
+ # 2. POSIX leaves undefined whether this is a stable sort or not. So
+ # we use "-k 1" to ensure that we see HEAD before master before
+ # side when breaking ties.
+ {
+ do_walk --date=unix HEAD &&
+ do_walk --date=unix side &&
+ do_walk --date=unix master
+ } >expect.raw &&
+ sort -t "{" -k 2nr -k 1 <expect.raw >expect &&
+ do_walk --date=unix HEAD master side >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'date-limiting does not interfere with other logs' '
+ do_walk HEAD@{1979-01-01} HEAD >actual &&
+ test_cmp expect.all actual
+'
+
+test_expect_failure 'walk prefers reflog to ref tip' '
+ head=$(git rev-parse HEAD) &&
+ one=$(git rev-parse one) &&
+ ident="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE" &&
+ echo "$head $one $ident broken reflog entry" >>.git/logs/HEAD &&
+
+ echo $one >expect &&
+ git log -g --format=%H -1 >actual &&
+ test_cmp expect actual
+'
+
+test_done