mirror of
https://github.com/git/git
synced 2024-08-24 10:15:51 +00:00
![Jeff King](/assets/img/avatar_default.png)
Since its inception, the general strategy of the reflog-walk code has been to start with the tip commit for the ref, and as we traverse replace each commit's parent pointers with fake parents pointing to the previous reflog entry. This lets us traverse the reflog as if it were a real history, but it has some user-visible oddities. Namely: 1. The fake parents are used for commit selection and display. So for example, "--merges" or "--no-merges" are not useful, because the history appears as a linear string of commits. Likewise, pathspec limiting is based on the diff between adjacent entries, not the changes actually introduced by a commit. These are often the same (e.g., because the entry was just running "git commit" and the adjacent entry _is_ the true parent), but it may not be in several common cases. For instance, using "git reset" to jump around history, or "git checkout" to move HEAD. 2. We reverse-map each commit back to its reflog. So when it comes time to show commit X, we say "a-ha, we added X because it was at the tip of the 'foo' reflog, so let's show the foo reflog". But this leads to nonsense results when you ask to traverse multiple reflogs: if two reflogs have the same tip commit, we only map back to one of them. Instead, we should show both. 3. If the tip of the reflog and the ref tip disagree on the current value, we show the ref tip but give no indication of the value in the reflog. This situation isn't supposed to happen (since any ref update should touch the reflog). But if it does, given that the requested operation is to show the reflog, it makes sense to prefer that. This commit adds a new script with several expect_failure tests to demonstrate the problems. This could be part of the existing t1411, but it's a bit easier to start from a fresh state, where we know exactly what will be in the log. Since the new multiple-reflog tests are checking the actual output, we can drop the "make sure we don't segfault" tests from t1411, which are a strict subset of what we're doing here. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
175 lines
4.4 KiB
Bash
Executable file
175 lines
4.4 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='Test reflog display routines'
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success 'setup' '
|
|
echo content >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m one
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
|
|
Reflog message: commit (initial): one
|
|
EOF
|
|
test_expect_success 'log -g shows reflog headers' '
|
|
git log -g -1 >tmp &&
|
|
grep ^Reflog <tmp >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
e46513e HEAD@{0}: commit (initial): one
|
|
EOF
|
|
test_expect_success 'oneline reflog format' '
|
|
git log -g -1 --oneline >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'reflog default format' '
|
|
git reflog -1 >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
commit e46513e
|
|
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
|
|
Reflog message: commit (initial): one
|
|
Author: A U Thor <author@example.com>
|
|
|
|
one
|
|
EOF
|
|
test_expect_success 'override reflog default format' '
|
|
git reflog --format=short -1 >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
|
|
Reflog message: commit (initial): one
|
|
EOF
|
|
test_expect_success 'using @{now} syntax shows reflog date (multiline)' '
|
|
git log -g -1 HEAD@{now} >tmp &&
|
|
grep ^Reflog <tmp >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
|
|
EOF
|
|
test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
|
|
git log -g -1 --oneline HEAD@{now} >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
HEAD@{Thu Apr 7 15:13:13 2005 -0700}
|
|
EOF
|
|
test_expect_success 'using @{now} syntax shows reflog date (format=%gd)' '
|
|
git log -g -1 --format=%gd HEAD@{now} >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
|
|
Reflog message: commit (initial): one
|
|
EOF
|
|
test_expect_success 'using --date= shows reflog date (multiline)' '
|
|
git log -g -1 --date=default >tmp &&
|
|
grep ^Reflog <tmp >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
|
|
EOF
|
|
test_expect_success 'using --date= shows reflog date (oneline)' '
|
|
git log -g -1 --oneline --date=default >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
HEAD@{1112911993 -0700}
|
|
EOF
|
|
test_expect_success 'using --date= shows reflog date (format=%gd)' '
|
|
git log -g -1 --format=%gd --date=raw >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
|
|
Reflog message: commit (initial): one
|
|
EOF
|
|
test_expect_success 'log.date does not invoke "--date" magic (multiline)' '
|
|
test_config log.date raw &&
|
|
git log -g -1 >tmp &&
|
|
grep ^Reflog <tmp >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
e46513e HEAD@{0}: commit (initial): one
|
|
EOF
|
|
test_expect_success 'log.date does not invoke "--date" magic (oneline)' '
|
|
test_config log.date raw &&
|
|
git log -g -1 --oneline >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
HEAD@{0}
|
|
EOF
|
|
test_expect_success 'log.date does not invoke "--date" magic (format=%gd)' '
|
|
test_config log.date raw &&
|
|
git log -g -1 --format=%gd >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
cat >expect <<'EOF'
|
|
HEAD@{0}
|
|
EOF
|
|
test_expect_success '--date magic does not override explicit @{0} syntax' '
|
|
git log -g -1 --format=%gd --date=raw HEAD@{0} >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
: >expect
|
|
test_expect_success 'empty reflog file' '
|
|
git branch empty &&
|
|
git reflog expire --expire=all refs/heads/empty &&
|
|
|
|
git log -g empty >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
# This guards against the alternative of showing the diffs vs. the
|
|
# reflog ancestor. The reflog used is designed to list the commits
|
|
# more than once, so as to exercise the corresponding logic.
|
|
test_expect_success 'git log -g -p shows diffs vs. parents' '
|
|
test_commit two &&
|
|
git branch flipflop &&
|
|
git update-ref refs/heads/flipflop -m flip1 HEAD^ &&
|
|
git update-ref refs/heads/flipflop -m flop1 HEAD &&
|
|
git update-ref refs/heads/flipflop -m flip2 HEAD^ &&
|
|
git log -g -p flipflop >reflog &&
|
|
grep -v ^Reflog reflog >actual &&
|
|
git log -1 -p HEAD^ >log.one &&
|
|
git log -1 -p HEAD >log.two &&
|
|
(
|
|
cat log.one; echo
|
|
cat log.two; echo
|
|
cat log.one; echo
|
|
cat log.two
|
|
) >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'reflog exists works' '
|
|
git reflog exists refs/heads/master &&
|
|
! git reflog exists refs/heads/nonexistent
|
|
'
|
|
|
|
test_done
|