Just like "git merge -" is a short-hand for "git merge @{-1}" to conveniently merge the previous branch, "git diff -" is a short-hand for "git diff @{-1}" to conveniently diff against the previous branch. Allow the usage of "-" in the dot dot notation to allow the use of "git diff -..HEAD^" as a short-hand for "git diff @{-1}..HEAD^". Signed-off-by: mash <mash+git@xxxxxxxxxxxxx> --- This is a GSoC microproject. I'm not sure how useful this change is. Please review it and take it apart. I'm not very happy with the change of handle_revision_arg. Maybe I should teach sha1_name.c:get_sha1_basic how to handle a dash instead. Documentation was not updated. I could only think of updating revisions.txt but that might be misleading since the use of dash does not work everywhere. revision.c | 22 ++++++++++++++++++-- t/t4063-diff-last.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100755 t/t4063-diff-last.sh diff --git a/revision.c b/revision.c index b37dbec..c331bd5 100644 --- a/revision.c +++ b/revision.c @@ -1439,6 +1439,7 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi const char *arg = arg_; int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME; unsigned get_sha1_flags = 0; + static const char previous_branch[] = "@{-1}"; flags = flags & UNINTERESTING ? flags | BOTTOM : flags & ~BOTTOM; @@ -1457,6 +1458,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi if (!*next) next = head_by_default; + else if (!strcmp(next, "-")) + next = previous_branch; if (dotdot == arg) this = head_by_default; if (this == head_by_default && next == head_by_default && @@ -1469,6 +1472,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi *dotdot = '.'; return -1; } + } else if (!strcmp(this, "-")) { + this = previous_branch; } if (!get_sha1_committish(this, from_sha1) && !get_sha1_committish(next, sha1)) { @@ -1568,6 +1573,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi if (revarg_opt & REVARG_COMMITTISH) get_sha1_flags = GET_SHA1_COMMITTISH; + if (!strcmp(arg, "-")) + arg = previous_branch; if (get_sha1_with_context(arg, get_sha1_flags, sha1, &oc)) return revs->ignore_missing ? 0 : -1; if (!cant_be_filename) @@ -1578,6 +1585,15 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi return 0; } +/* + * Check if the argument is supposed to be a revision argument instead of an + * option even though it starts with a dash. + */ +static int is_revision_arg(const char *arg) +{ + return *arg == '\0' || starts_with(arg, ".."); +} + struct cmdline_pathspec { int alloc; int nr; @@ -1621,7 +1637,9 @@ static void read_revisions_from_stdin(struct rev_info *revs, seen_dashdash = 1; break; } - die("options not supported in --stdin mode"); + if (!is_revision_arg(sb.buf + 1)) { + die("options not supported in --stdin mode"); + } } if (handle_revision_arg(sb.buf, revs, 0, REVARG_CANNOT_BE_FILENAME)) @@ -2205,7 +2223,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s read_from_stdin = 0; for (left = i = 1; i < argc; i++) { const char *arg = argv[i]; - if (*arg == '-') { + if (*arg == '-' && !is_revision_arg(arg + 1)) { int opts; opts = handle_revision_pseudo_opt(submodule, diff --git a/t/t4063-diff-last.sh b/t/t4063-diff-last.sh new file mode 100755 index 0000000..1f635cb --- /dev/null +++ b/t/t4063-diff-last.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +test_description='diff against last branch' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo hello >world && + git add world && + git commit -m initial && + git branch other && + echo "hello again" >>world && + git add world && + git commit -m second +' + +test_expect_success '"diff -" does not work initially' ' + test_must_fail git diff - +' + +test_expect_success '"diff -" diffs against previous branch' ' + git checkout other && + + cat <<-\EOF >expect && + diff --git a/world b/world + index c66f159..ce01362 100644 + --- a/world + +++ b/world + @@ -1,2 +1 @@ + hello + -hello again + EOF + + git diff - >out && + test_cmp expect out +' + +test_expect_success '"diff -.." diffs against previous branch' ' + git diff -.. >out && + test_cmp expect out +' + +test_expect_success '"diff ..-" diffs inverted' ' + cat <<-\EOF >expect && + diff --git a/world b/world + index ce01362..c66f159 100644 + --- a/world + +++ b/world + @@ -1 +1,2 @@ + hello + +hello again + EOF + + git diff ..- >out && + test_cmp expect out +' + +test_done -- 2.9.3