Skip to content

Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll

Stan Hu requested to merge stanhu/gitlab-ce:disable-git-follow into master

git doesn't work properly when --follow and --skip are specified together. We could even be omitting commits in the Web log as a result.

Here are the gory details. Let's say you ran:

git log -n=5 --skip=2 README

This is the working case since it omits --follow. This is what happens:

  1. git starts at HEAD and traverses down the tree until it finds the top-most commit relevant to README.
  2. Once this is found, this commit is returned via get_revision_1().
  3. If the skip_count is positive, decrement and repeat step 2. Otherwise go onto step 4.
  4. show_log() gets called with that commit.
  5. Repeat step 1 until we have all five entries.

That's exactly what we want. What happens when you use --follow? You have to understand how step 1 is performed:

  • When you specify a pathspec on the command-line (e.g. README), a flag prune gets set here.
  • If the prune flag is active, get_commit_action() determines whether the commit should be scanned for matching paths.
  • In the case of --follow, however, prune is disabled here.
  • As a result, a commit is never scanned for matching paths and therefore never pruned. HEAD will always get returned as the first commit, even if it's not relevant to the README.
  • Making matters worse, the --skip in the example above would actually skip a every other entry after HEAD N times. If README were changed in these skipped commits, we would actually miss information!

Since git uses a matching algorithm to determine whether a file was renamed, I believe git needs to generate a diff of each commit to do this and traverse each commit one-by-one to do this. I think that's the rationale for disabling the prune functionality since you can't just do a simple string comparison.

Closes #4181 (closed), #4229 (closed), #3574 (closed), #2410 (closed)

Merge request reports