why moved code is not colored in git diff?

前端 未结 2 1273
悲哀的现实
悲哀的现实 2021-02-05 22:49

I install latest git and configure it to highlight moved code:

$ git config diff.colormoved default

Here is how it looks when code is moved (se

2条回答
  •  深忆病人
    2021-02-05 23:08

    Note there is another scenario where colored moved code (when the amount of code is enough) would have an improper side-effect:
    "git diff --color-moved --cc --stat -p" did not work well due to funny interaction between a bug in color-moved and the rest.

    This has been fixed in Git 2.21 (Feb. 2019)

    See commit dac03b5, commit 04b19fc, commit 8290faa, commit 8817f0c, commit 48edf3a, commit 426fd36 (24 Jan 2019) by Jeff King (peff).
    (Merged by Junio C Hamano -- gitster -- in commit 5d2710b, 05 Feb 2019)

    diff: clear emitted_symbols flag after use

    There's an odd bug when "log --color-moved" is used with the combination of "--cc --stat -p": the stat for merge commits is erroneously shown with the diff of the next commit.

    The included test demonstrates the issue.
    Our history looks something like this:

    A-B-M--D
       \ /
        C
    

    When we run "git log --cc --stat -p --color-moved" starting at D, we get this sequence of events:

    1. The diff for D is using -p, so diff_flush() calls into diff_flush_patch_all_file_pairs(). There we see that o->color_moved is in effect, so we point o->emitted_symbols to a static local struct, causing diff_flush_patch() to queue the symbols instead of actually writing them out.
      We then do our move detection, emit the symbols, and clear the struct. But we leave o->emitted_symbols pointing to our struct.

    2. Next we compute the diff for M. This is a merge, so we use the combined diff code.
      In find_paths_generic(), we compute the pairwise diff between each commit and its parent. Normally this is done with DIFF_FORMAT_NO_OUTPUT, since we're just looking for intersecting paths. But since "--stat --cc" shows the first-parent stat, and since we're computing that diff anyway, we enable DIFF_FORMAT_DIFFSTAT for the first parent. This outputs the stat information immediately, saving us from running a separate first-parent diff later.
      But where does that output go? Normally it goes directly to stdout, but because o->emitted_symbols is set, we queue it. As a result, we don't actually print the diffstat for the merge commit (yet), which is wrong.

      1. Next we compute the diff for C. We're actually showing a patch again, so we end up in diff_flush_patch_all_file_pairs(), but this time we have the queued stat from step 2 waiting in our struct.
        We add new elements to it for C's diff, and then flush the whole thing. And we see the diffstat from M as part of C's diff, which is wrong.

    So triggering the bug really does require the combination of all of those options.

提交回复
热议问题