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

Re: Why repository grows after "git gc"? / Purpose of *.keep files?

From
JRJuergen Ruehle <j.ruehle@bmiag.de>
Date
May 14, 2008, 09:10 UTC
Message-ID
<18474.44155.823000.368851@lapjr.intranet.kiel.bmiag.de>
In-Reply-To
<7vy76dperf.fsf@gitster.siamese.dyndns.org>
Junio C Hamano writes:
 > The output from rev-list is not surprising.  --unpacked=$this.pack implies
 > the usual --unpacked behaviour (i.e. only show unpacked objects by not
 > traversing into commits that are packed)

The problem is unconditional traversing into commits that are unpacked. This behavior is immediately obvious if the packed blob in the .keep pack is large. I've been using the following since the large object discussion with Dana, but it might be completely broken (though the test case is probably correct).

--

Previously --unpacked would filter on the commit level, ignoring whether the objects comprising the commit actually were packed or unpacked.

This makes it impossible to store e.g. excessively large blobs in different packs from the commits referencing them, since the next repack of such a commit will suck all referenced blobs into the same pack.

This change moves the unpacked check to the output stage and no longer checks
the flag during commit traversal and adds a trivial test demonstrating the
problem.
---
 Note that t6009 is already taken, so it might be better to merge the test
 into one of the other rev-list tests.
 list-objects.c               |    6 ++++--
 revision.c                   |    2 --
 t/t6009-rev-list-unpacked.sh |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 4 deletions(-)
 create mode 100644 t/t6009-rev-list-unpacked.sh
diff --git a/list-objects.c b/list-objects.c
index c8b8375..b378c0f 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -146,7 +146,8 @@ void traverse_commit_list(struct rev_info *revs,
 
 	while ((commit = get_revision(revs)) != NULL) {
 		process_tree(revs, commit->tree, &objects, NULL, "");
-		show_commit(commit);
+		if (!revs->unpacked || !has_sha1_pack(commit->object.sha1, revs->ignore_packed))
+			show_commit(commit);
 	}
 	for (i = 0; i < revs->pending.nr; i++) {
 		struct object_array_entry *pending = revs->pending.objects + i;
@@ -173,7 +174,8 @@ void traverse_commit_list(struct rev_info *revs,
 		    sha1_to_hex(obj->sha1), name);
 	}
 	for (i = 0; i < objects.nr; i++)
-		show_object(&objects.objects[i]);
+		if (!revs->unpacked || !has_sha1_pack(objects.objects[i].item->sha1, revs->ignore_packed))
+			show_object(&objects.objects[i]);
 	free(objects.objects);
 	if (revs->pending.nr) {
 		free(revs->pending.objects);
diff --git a/revision.c b/revision.c
index 4231ea2..0e90d3b 100644
--- a/revision.c
+++ b/revision.c
@@ -1508,8 +1508,6 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
 	if (commit->object.flags & SHOWN)
 		return commit_ignore;
-	if (revs->unpacked && has_sha1_pack(commit->object.sha1, revs->ignore_packed))
-		return commit_ignore;
 	if (revs->show_all)
 		return commit_show;
 	if (commit->object.flags & UNINTERESTING)
diff --git a/t/t6009-rev-list-unpacked.sh b/t/t6009-rev-list-unpacked.sh
new file mode 100644
index 0000000..6b65e83
--- /dev/null
+++ b/t/t6009-rev-list-unpacked.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='test git rev-list --unpacked --objects'
+
+. ./test-lib.sh
+
+# Create an unpacked commit that references a packed object.
+
+test_expect_success setup '
+	echo Hallo > foo &&
+	git add foo &&
+	test_tick &&
+	git commit -m "A" &&
+        git gc &&
+	echo Cello > bar &&
+	git add bar &&
+	test_tick &&
+	git commit -m "B"
+'
+
+test_expect_success \
+    'object list should contain foo' '
+    git rev-list --all --objects | grep -q "foo"
+'
+
+test_expect_success \
+    'unpacked object list should not contain foo' '
+    test_must_fail "git rev-list --all --unpacked --objects | grep -q \"foo\""
+'
+
+
+test_done
-- 
1.5.5.1.382.g7d84c
Previous: Junio C HamanoNext: Nicolas Pitre
Message 18 of 35 in “Why repository grows after "git gc"? / Purpose of *.keep files?”
  1. Teemu LikonenMay 12, 2008
  2. Teemu LikonenMay 12, 2008
  3. Johannes SchindelinMay 12, 2008
  4. Teemu LikonenMay 12, 2008
  5. Nicolas PitreMay 12, 2008
  6. Teemu LikonenMay 12, 2008
  7. Nicolas PitreMay 12, 2008
  8. Govind SalinasMay 12, 2008
  9. Nicolas PitreMay 12, 2008
  10. Govind SalinasMay 12, 2008
  11. Teemu LikonenMay 12, 2008
  12. Mike HommeyMay 12, 2008
  13. Mike HommeyMay 12, 2008
  14. Shawn O. PearceMay 13, 2008
  15. Mike HommeyMay 13, 2008
  16. Nicolas PitreMay 14, 2008
  17. Junio C HamanoMay 14, 2008
  18. Juergen RuehleMay 14, 2008
  19. Nicolas PitreMay 14, 2008
  20. Junio C HamanoMay 14, 2008
  21. Linus TorvaldsMay 14, 2008
  22. Linus TorvaldsMay 14, 2008
  23. Nicolas PitreMay 14, 2008
  24. Linus TorvaldsMay 14, 2008
  25. A Large Angry SCMMay 14, 2008
  26. Nicolas PitreMay 12, 2008
  27. David TweedMay 12, 2008
  28. Shawn O. PearceMay 12, 2008
  29. Junio C HamanoMay 12, 2008
  30. Shawn O. PearceMay 13, 2008
  31. Paolo BonziniMay 13, 2008
  32. Shawn O. PearceMay 13, 2008
  33. Teemu LikonenMay 13, 2008
  34. Stephen R. van den BergMay 13, 2008
  35. Teemu LikonenMay 14, 2008

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.