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 <[email protected]>
---
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