Re: `git range-diff` lists chunks with uninteresting changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi squirrel,

On Sat, 20 Aug 2022, squirrel wrote:

> When someone makes a PR, they may be asked to rebase their feature branch onto
> main to resolve conflicts. It may be useful to quickly see what changed during
> the rebase, that is how the new version of PR is different to the old one.
>
> If the PR branch has not been reparented, you may get away with `git diff`.
> But if it has, `git diff` may contain a lot of changes from upstream. Instead,
> `git range-diff` can be used.
>
> The problem with this is that in this case `git range-diff` can show chunks
> with changes that have nothing to do with changes in the PR. Consider this
> repository (commands are runnable):
>
>     git init
>     git branch -m main
>     echo -e "a\nb\nc\nd\ne\n1\n2\n3\nf" > file
>     git add file
>     git commit -am "a b c d e f"
>
>     git checkout -b foo
>     echo -e "a\nb\nc\nd\ne\n1\n2\n3\nfoo" > file
>     git commit -am "f -> foo"
>
>     git checkout main
>     git checkout -b cat
>     echo -e "a\nb\ncat\nd\ne\n1\n2\n3\nf" > file
>     git commit -am "c -> cat"
>
> We got a few letters of alphabet on separate lines on main, and in branch
> foo `f` is changed to `foo`, and in branch cat `c` is changed to `cat`.
>
>     $ git log --all --graph --pretty=oneline
>     * 90e873e3 (HEAD -> cat) c -> cat
>     | * 3d8c1baf (foo) f -> foo
>     |/
>     * 4d2337dd (main) a b c d e f
>
> Now, still on cat, let's combine the two changes.
>
>     $ git rebase foo
>     Successfully rebased and updated refs/heads/cat
>
>     $ git log --all --graph --pretty=oneline
>     * 98e554a0 (HEAD -> cat) c -> cat
>     * 3d8c1baf (foo) f -> foo
>     * 4d2337dd (main) a b c d e f
>
> Now, `git rebase foo` worked automatically, so *the change* of the last commit
> on `cat` is the same as it was without rebase, which is changing `c` to `cat`.
> But if we run `git range-diff`, we will see this:
>
>     $ git range-diff 90e873e3...cat
>     -:  ------- > 1:  3d8c1ba f -> foo
>     1:  90e873e ! 2:  98e554a c -> cat
>         @@ file
>          +cat
>           d
>           e
>         - f
>         + foo
>
> It seems that this chunk is included for the sole reason that the change from
> `foo` is sort of close. If we try the same code, but put the lines `c` and `f`
> further apart, for example by replacing `e\n` with `e\n1\n2\n3\n` in the
> commands above, the output would be, as expected,
>
>     $ git range-diff f1e0a6cc3...cat
>     -:  ------- > 1:  4db06be f -> foo
>     1:  f1e0a6c = 2:  cc56db7 c -> cat
>
> I suggest not showing uninteresting chunks like that, or perhaps having a
> command line option that controls how close together the changes must be in
> order to be included in the output.

In a generic tool like `range-diff`, it is virtually guaranteed that the
default operation does not satisfy all use cases. This example
demonstrates that ;-)

In general, the `A...B` form does what users want, namely show you pairs
between the "left" and the "right" commits in that symmetric range.

However, you _can_ use `range-diff` in a way that it produces what you
want. In the example you provided above, `git range-diff foo cat@{1} cat`
should do it. That would be the `<upstream> <before> <after>` form.

In general, you might need to play with `git merge-base --fork-point` (see
*1* for more information). I could imagine that the following command
might give you what you want in even more cases:

	git range-diff \
		$(git merge-base --fork-point @{u} @{1})..@{1} \
		$(git merge-base --fork-point @{u} HEAD)..HEAD

Ciao,
Johannes

Footnote *1*: https://git-scm.com/docs/git-merge-base#_discussion_on_fork_point_mode




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux