git/list[1] front-page[2] threads[3] people[4] search[5] about
 

RE: Any way to get complete diff up to a tag?

From
Peter Kjellerstedt <peter.kjellerstedt@axis.com>
Date
May 7, 2010, 16:35 UTC
Message-ID
<A612847CFE53224C91B23E3A5B48BAC74482E5113B@xmail3.se.axis.com>
In-Reply-To
<alpine.LFD.2.00.1005060955000.901@i5.linux-foundation.org>
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
Previous: Greg TroxelNext: Knittl
Message 11 of 13 in “Any way to get complete diff up to a tag?”
  1. Peter KjellerstedtMay 6, 2010
  2. Bert WesargMay 6, 2010
  3. Björn SteinbrinkMay 6, 2010
  4. Peter KjellerstedtMay 6, 2010
  5. Santi BéjarMay 6, 2010
  6. Johannes SixtMay 6, 2010
  7. Peter KjellerstedtMay 6, 2010
  8. Björn SteinbrinkMay 6, 2010
  9. Linus TorvaldsMay 6, 2010
  10. Greg TroxelMay 6, 2010
  11. Peter KjellerstedtMay 7, 2010
  12. KnittlMay 6, 2010
  13. Peter KjellerstedtMay 7, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.