3

(Slightly different question than Git diff branch against working tree not including merges)

Essentially I want git diff origin/develop...working-tree.

More technically what I want is git diff $(git-merge-base origin/develop HEAD) which will diff merge-base against working tree; Yet I want to keep the ... shorthand at the same time.

The origin/develop... part calculates the correct merge-base (merge-base with HEAD), but it also is hardcoded to assume that the comparison is against HEAD as well. Is there a way to keep the ... shorthand reference, but diff against working tree?

Alexander Bird
  • 38,679
  • 42
  • 124
  • 159

2 Answers2

3

Update Nov. 2020: Yes, that is now possible.

Running git diff --merge-base <commit> is equivalent to running git diff $(git merge-base <commit> HEAD) which should give you a diff between the merge-base and the current working tree.

With Git 2.30 (Q1 2021), "git diff A...B(man)" learned "git diff --merge-base A B(man), which is a longer short-hand to say the same thing.

See commit cce7d6e, commit 0f5a1d4, commit df7dbab, commit 177a830, commit 4c3fe82 (20 Sep 2020), commit 3d09c22 (14 Sep 2020), and commit 308d7a7, commit a8fa6a0, commit b277b73, commit 8023a5e (17 Sep 2020) by Denton Liu (Denton-L).
(Merged by Junio C Hamano -- gitster -- in commit b6fb70c, 02 Nov 2020)

builtin/diff-index: learn --merge-base

Signed-off-by: Denton Liu

There is currently no easy way to take the diff between the working tree or index and the merge base between an arbitrary commit and HEAD.
Even diff's ... notation doesn't allow this because it only works between commits.

However, the ability to do this would be desirable to a user who would like to see all the changes they've made on a branch plus uncommitted changes without taking into account changes made in the upstream branch.

Teach diff-index and diff (with one commit) the --merge-base option which allows a user to use the merge base of a commit and HEAD as the "before" side.

'git diff-index' [-m] [--cached] [--merge-base] [<common diff options>] <tree-ish> [<path>...]

git diff-index now includes in its man page:

--merge-base

Instead of comparing <tree-ish> directly, use the merge base between <tree-ish> and HEAD instead.
<tree-ish> must be a commit.

git diff now includes in its man page:

If --merge-base is given, instead of using <commit>, use the merge base of <commit> and HEAD.
git diff --merge-base A is equivalent to git diff $(git merge-base A HEAD).

git diff now includes in its man page:

in the --merge-base case and in the last two forms that use .. notations, can be any <tree>.

And:

builtin/diff-tree: learn --merge-base

Signed-off-by: Denton Liu

The previous commit introduced --merge-base a way to take the diff between the working tree or index and the merge base between an arbitrary commit and HEAD.

It makes sense to extend this option to support the case where two commits are given too and behave in a manner identical to git diff A...B(man).

Introduce the --merge-base flag as an alternative to triple-dot notation.

Thus, we would be able to write the above as git diff --merge-base A B(man).

git diff-tree now includes in its man page:

--merge-base

Instead of comparing the <tree-ish>s directly, use the merge base between the two <tree-ish>s as the "before" side.
There must be two <tree-ish>s given and they must both be commits.

git diff now includes in its man page:

If --merge-base is given, use the merge base of the two commits for the "before" side.
git diff --merge-base A B is equivalent to git diff $(git merge-base A B) B.


With Git 2.33 (Q3 2021), "git diff"(man) --merge-base documentation has been updated.

See commit eb44863 (10 Jul 2021) by Denton Liu (Denton-L).
(Merged by Junio C Hamano -- gitster -- in commit 6ca224f, 28 Jul 2021)

git-diff: fix missing --merge-base docs

Signed-off-by: Denton Liu

When git diff --merge-base(man) was introduced at around Git 2.30, the documentation included a few errors.

In the example given for git diff --cached --merge-base, the --cached flag was omitted for the --merge-base example.
Add the missing flag.

In the git diff <commit> case, we failed to mention that --merge-base is an available option.
Give the usage of --merge-base as an option there.

Finally, there are two errors in the usage of git diff.
Firstly, we do not mention --merge-base in the git diff --cached case.
Mention it so that it's consistent with the documentation.
Secondly, we put the [--merge-base] in between <commit> and [<commit>...].
Move the [--merge-base] so that it's beside [<options>] which is a more logical grouping.

git diff now includes in its man page:

git diff --cached --merge-base A is equivalent to git diff --cached $(git merge-base A HEAD).

git diff now includes in its man page:

'git diff' [<options>] [--merge-base] <commit> [--] [<path>...]

git diff now includes in its man page:

If --merge-base is given, instead of using <commit>, use the merge base of <commit> and HEAD.
git diff --merge-base A is equivalent to git diff $(git merge-base A HEAD).

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I have Git `2.30.0` version but get this error: `error: invalid option: --merge-base`, any idea why? – haridsv Feb 03 '21 at 06:27
  • @haridsv What command did you type? I have git version 2.30.0.windows.2, I just tried `git diff --merge-base @~1` and I did not get any error message. Same for `git diff-index --merge-base @~1` – VonC Feb 03 '21 at 09:18
  • Interesting... I thought the commit ref is optional (see: https://git-scm.com/docs/git-diff) so expecting it to diff the `HEAD` against merge base, I just typed `git diff --merge-base`, but when I give a commit ref like in your example, the option got recognized. However, it is not working as I expected. When I run `git diff --merge-base HEAD`, I get no diff, but there is diff that I can see by typing ` git diff $(git merge-base master HEAD)`. Are they not the same? – haridsv Feb 03 '21 at 11:30
  • @haridsv `git diff` alone would show changes between the working tree and the index. If `--merge-base` is given, instead of using ``, use the merge base of `` and `HEAD`. `git diff --merge-base A` is equivalent to `git diff $(git merge-base A HEAD)`. In your case, `git diff --merge-base HEAD` would be equivalent to `git diff $(git merge-base HEAD HEAD)`, which would result in `git diff HEAD`, which would compare HEAD and index. If nothing was added, the result would be empty. – VonC Feb 03 '21 at 11:39
  • @haridsv I just tried `git diff $(git merge-base master HEAD)` and got nothing. I suppose it depends where your HEAD is (other branch? detached HEAD?) – VonC Feb 03 '21 at 11:40
  • Thanks for the tip, I guess the right equivalent for ` git diff $(git merge-base master HEAD)` is `git diff --merge-base master HEAD`, I can confirm that both produce the same output in my case. – haridsv Feb 04 '21 at 12:15
  • Is there a difference between `git diff --merge-base master HEAD` and `git diff master...HEAD` ? – haridsv Feb 04 '21 at 12:19
  • 1
    @haridsv No, it should be the same thing, as mentioned by torek in https://stackoverflow.com/a/41251624/6309 – VonC Feb 04 '21 at 15:42
1

No. You cannot combine the short-hand notation with a diff against the work-tree. You must use the longer form.

You can make a Git alias that invokes the shell:

alias.basevtree=!git diff $(git merge-base @{u} HEAD)

(I'm not sure what your ^ was doing in there) and then run git basevtree, but you cannot get it with the three-dot syntax.

torek
  • 448,244
  • 59
  • 642
  • 775