Thread (3 messages) flat view 3 messages, 2 authors, 2016-06-15

Re: FYI: git-am allows creation of empty commits.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:20
Subsystem: the rest · Maintainer: Linus Torvalds

Possibly related (same subject, not in this thread)

ebiederm@xmission.com (Eric W. Biederman) writes:
Is this something that we always want to test for in the porcelain
or do we want to move a check into git-commit-tree?

For getting a reasonable error message where you have the test
seems to be the only sane place, but having the check deeper
down would be more likely to catch this kind of thing.
I think 99.9% of the time it is a mistake if a single-parented
commit has the same tree as its parent commit has, so having a
check in commit-tree may not be a bad idea.

If you want to do it, however, you need to be a bit careful
about merges.  In a multi-parented commit, it is legitimate if
the merge result exactly match one of the parents (in fact
"git-merge -s ours" can be used to create a merge that matches
its first parent).

The commit-tree program is one of the oldest part of the system,
and as a mechanism, does not set nor enforce policies like this.
It has been more liberal than the best current practice, such as
(1) don't do single-parent empty commit; (2) don't list the same
parent twice.  The second one was introduced in mid-June last
year, which is "long after it was invented" in git timescale.

On the other hand, it is more anal than it could be.  It does
not take a tag that points to a commit to its -p parameter.
That's because we did not have tag objects in the beginning, and
by the time tags were introduced, nobody ran commit-tree by hand
anymore.

-- >8 --
[PATCH] commit-tree: disallow an empty single-parent commit.

Also allow "git-commit-tree -p v2.6.16-rc2", instead of having
to say "git-commit-tree -p v2.6.16-rc2^0".

Signed-off-by: Junio C Hamano <redacted>
---
diff --git a/commit-tree.c b/commit-tree.c
index 88871b0..14a7552 100644
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -45,12 +45,14 @@ static void check_valid(unsigned char *s
 {
 	void *buf;
 	char type[20];
+	unsigned char real_sha1[20];
 	unsigned long size;
 
-	buf = read_sha1_file(sha1, type, &size);
-	if (!buf || strcmp(type, expect))
+	buf = read_object_with_reference(sha1, expect, &size, real_sha1);
+	if (!buf)
 		die("%s is not a valid '%s' object", sha1_to_hex(sha1), expect);
 	free(buf);
+	memcpy(sha1, real_sha1, 20);
 }
 
 /*
@@ -75,6 +77,19 @@ static int new_parent(int idx)
 	return 1;
 }
 
+static int check_empty_commit(const unsigned char *tree_sha1,
+			      const unsigned char *parent_sha1)
+{
+	unsigned char sha1[20];
+	char refit[50];
+	sprintf(refit, "%s^{tree}", sha1_to_hex(parent_sha1));
+	if (get_sha1(refit, sha1))
+		die("cannot determine tree in parent commit.");
+	if (!memcmp(sha1, tree_sha1, 20))
+		return error ("empty commit?  aborting.");
+	return 0;
+}
+
 int main(int argc, char **argv)
 {
 	int i;
@@ -105,6 +120,9 @@ int main(int argc, char **argv)
 	}
 	if (!parents)
 		fprintf(stderr, "Committing initial tree %s\n", argv[1]);
+	if (parents == 1)
+		if (check_empty_commit(tree_sha1, parent_sha1[0]))
+			exit(1);
 
 	init_buffer(&buffer, &size);
 	add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help