summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--revision.c28
-rwxr-xr-xt/t1411-reflog-show.sh22
2 files changed, 47 insertions, 3 deletions
diff --git a/revision.c b/revision.c
index e3ca9361b4..ac20d1aaed 100644
--- a/revision.c
+++ b/revision.c
@@ -2848,6 +2848,7 @@ static struct commit *get_revision_1(struct rev_info *revs)
free(entry);
if (revs->reflog_info) {
+ save_parents(revs, commit);
fake_reflog_parent(revs->reflog_info, commit);
commit->object.flags &= ~(ADDED | SEEN | SHOWN);
}
@@ -3083,6 +3084,8 @@ void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
define_commit_slab(saved_parents, struct commit_list *);
+#define EMPTY_PARENT_LIST ((struct commit_list *)-1)
+
void save_parents(struct rev_info *revs, struct commit *commit)
{
struct commit_list **pp;
@@ -3093,16 +3096,35 @@ void save_parents(struct rev_info *revs, struct commit *commit)
}
pp = saved_parents_at(revs->saved_parents_slab, commit);
- assert(*pp == NULL);
- *pp = copy_commit_list(commit->parents);
+
+ /*
+ * When walking with reflogs, we may visit the same commit
+ * several times: once for each appearance in the reflog.
+ *
+ * In this case, save_parents() will be called multiple times.
+ * We want to keep only the first set of parents. We need to
+ * store a sentinel value for an empty (i.e., NULL) parent
+ * list to distinguish it from a not-yet-saved list, however.
+ */
+ if (*pp)
+ return;
+ if (commit->parents)
+ *pp = copy_commit_list(commit->parents);
+ else
+ *pp = EMPTY_PARENT_LIST;
}
struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)
{
+ struct commit_list *parents;
+
if (!revs->saved_parents_slab)
return commit->parents;
- return *saved_parents_at(revs->saved_parents_slab, commit);
+ parents = *saved_parents_at(revs->saved_parents_slab, commit);
+ if (parents == EMPTY_PARENT_LIST)
+ return NULL;
+ return parents;
}
void free_saved_parents(struct rev_info *revs)
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
index 9a105fe21f..6f47c0dd0e 100755
--- a/t/t1411-reflog-show.sh
+++ b/t/t1411-reflog-show.sh
@@ -144,4 +144,26 @@ test_expect_success 'empty reflog file' '
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_done