RE: Any way to get complete diff up to a tag?
Show 21 quoted lines
> -----Original Message-----
> From: git-owner@vger.kernel.org [mailto:git-owner@vger.kernel.org] On
> Behalf Of Linus Torvalds
> Sent: den 6 maj 2010 19:09
> To: Peter Kjellerstedt
> Cc: Johannes Sixt; git@vger.kernel.org; Björn Steinbrink
> Subject: RE: Any way to get complete diff up to a tag?
>
> On Thu, 6 May 2010, Peter Kjellerstedt wrote:
> >
> > Since the 4b825dc642cb6eb9a060e54bf8d69288fbee4904 SHA1 is somewhat
> > cumbersome to remember, wouldn't it be an idea to give it some kind
> > of alias or mnemonic? E.g., something like @~ (or some other mix of
> > odd characters which do not clash with all the other similar
> > constructs already used for references).
>
> Well, you don't strictly speaking have to "remember" it, you can always
> just re-generate it. The most straightforward way to do that is
> probably
>
> git hash-object -t tree --stdin < /dev/null
Thank you, that is good to know.
Show 19 quoted lines
> although I admit that maybe we could have some syntax for "git diff"
> that would do the "diff against empty tree" automatically. It does
> seem to be conceptually a reasonable thing to do.
>
> For example, right now if you give "git diff" a single SHA1, it will
> work against the working tree. Except if you add "--cached", to say
> that you want the diff against the index. I don't think it would be in
> any way _wrong_ to make "--root" mean that you want it against an
> empty tree.
>
> [ We already accept "--root", but it has no meaning for "git diff"
> with a single SHA1. It matters for showing the root commit for
> 'git-diff-tree'.
>
> And means something totally different for git-format-patch ]
>
> So we certainly _could_ do something like
>
> git diff --root <treeish>
I went ahead and implemented support for --root as an option to git diff (patch attached for reference). However, I then realized that there are probably more commands that would benefit from the same support, e.g., git diff-index. Then I thought about git diff-tree and realized that it could also benefit from my version of --root, but as you mentioned above, it already has a --root option with a different semantic... I also figured it would be a hassle for me to find all commands who can use a --root option, not knowing the internals of git well enough yet.
So I then went back to my original idea of making an alias for the empty tree, and came up with a two line patch which I will send as a separate patch, and see what you guys think of the idea.
Show 6 quoted lines
> and make it do what you want. That said, the "empty tree" thing works
> for all versions of git (well, some older versions of git need the
> actual object, but you could always use "-w" on that git-hash-object
> command line, and then it really should work for every git version).
>
> Linus
//Peter
From d9d482db98aa3ff3545cf66a8f851cc459b0eacd Mon Sep 17 00:00:00 2001
From: Peter Kjellerstedt <pkj@axis.com>
Date: Fri, 7 May 2010 17:11:19 +0200
Subject: [PATCH] diff: Make git diff support the --root option
Using 'git diff --root <tree-ish>' will give all the changes between the empty tree and <tree-ish>. It is also possible to use 'git diff --root --cached' to get all changes between the empty tree and the current index.
Signed-off-by: Peter Kjellerstedt <pkj@axis.com>
---
builtin/diff.c | 28 ++++++++++++++++++++++------
revision.c | 12 ++++++++++++
revision.h | 1 +
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/builtin/diff.c b/builtin/diff.c
index ffcdd05..8da59dd 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -253,6 +253,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
const char *path = NULL;
struct blobinfo blob[2];
int nongit;
+ int cached = 0;
int result = 0;
/*
@@ -316,10 +317,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
setup_pager();
/*
- * Do we have --cached and not have a pending object, then
- * default to HEAD by hand. Eek.
+ * If we have --cached and/or --root we may need to add the empty tree
+ * or HEAD by hand. Eek.
*/
- if (!rev.pending.nr) {
+ if (rev.pending.nr <= 1) {
int i;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -327,14 +328,29 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
break;
else if (!strcmp(arg, "--cached") ||
!strcmp(arg, "--staged")) {
- add_head_to_pending(&rev);
- if (!rev.pending.nr)
- die("No HEAD commit to compare with (yet)");
+ cached = 1;
break;
}
}
}
+ if (!rev.pending.nr) {
+ if (rev.show_root_diff) {
+ add_empty_tree_to_pending(&rev);
+ if (!rev.pending.nr)
+ die("No empty tree to compare with");
+ } else if (cached) {
+ add_head_to_pending(&rev);
+ if (!rev.pending.nr)
+ die("No HEAD commit to compare with (yet)");
+ }
+ } else if (rev.pending.nr == 1 && rev.show_root_diff && !cached) {
+ add_empty_tree_to_pending(&rev);
+ if (rev.pending.nr != 2)
+ die("No empty tree to compare with");
+ rev.diffopt.flags ^= DIFF_OPT_REVERSE_DIFF;
+ }
+
for (i = 0; i < rev.pending.nr; i++) {
struct object_array_entry *list = rev.pending.objects+i;
struct object *obj = list->item;
diff --git a/revision.c b/revision.c
index f4b8b38..c3a78dc 100644
--- a/revision.c
+++ b/revision.c
@@ -169,6 +169,18 @@ void add_head_to_pending(struct rev_info *revs)
add_pending_object(revs, obj, "HEAD");
}
+void add_empty_tree_to_pending(struct rev_info *revs)
+{
+ unsigned char sha1[20];
+ struct object *obj;
+ if (get_sha1(EMPTY_TREE_SHA1_HEX, sha1))
+ return;
+ obj = parse_object(sha1);
+ if (!obj)
+ return;
+ add_pending_object(revs, obj, EMPTY_TREE_SHA1_HEX);
+}
+
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
{
struct object *object;
diff --git a/revision.h b/revision.h
index 568f1c9..e1a7d9d 100644
--- a/revision.h
+++ b/revision.h
@@ -176,6 +176,7 @@ extern void add_object(struct object *obj,
extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name);
extern void add_head_to_pending(struct rev_info *);
+extern void add_empty_tree_to_pending(struct rev_info *revs);
enum commit_action {
commit_ignore,
--
1.7.0.1