commit-graph: build graph from starting commits
Teach git-commit-graph to read commits from stdin when the --stdin-commits flag is specified. Commits reachable from these commits are added to the graph. This is a much faster way to construct the graph than inspecting all packed objects, but is restricted to known tips. For the Linux repository, 700,000+ commits were added to the graph file starting from 'master' in 7-9 seconds, depending on the number of packfiles in the repo (1, 24, or 120). Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		 Derrick Stolee
					Derrick Stolee
				
			
				
					committed by
					
						 Junio C Hamano
						Junio C Hamano
					
				
			
			
				
	
			
			
			 Junio C Hamano
						Junio C Hamano
					
				
			
						parent
						
							049d51a2bb
						
					
				
				
					commit
					3d5df01b5e
				
			| @ -36,7 +36,13 @@ COMMANDS | ||||
| Write a commit graph file based on the commits found in packfiles. | ||||
| + | ||||
| With the `--stdin-packs` option, generate the new commit graph by | ||||
| walking objects only in the specified pack-indexes. | ||||
| walking objects only in the specified pack-indexes. (Cannot be combined | ||||
| with --stdin-commits.) | ||||
| + | ||||
| With the `--stdin-commits` option, generate the new commit graph by | ||||
| walking commits starting at the commits specified in stdin as a list | ||||
| of OIDs in hex, one OID per line. (Cannot be combined with | ||||
| --stdin-packs.) | ||||
|  | ||||
| 'read':: | ||||
|  | ||||
| @ -60,6 +66,12 @@ $ git commit-graph write | ||||
| $ echo <pack-index> | git commit-graph write --stdin-packs | ||||
| ------------------------------------------------ | ||||
|  | ||||
| * Write a graph file containing all reachable commits. | ||||
| + | ||||
| ------------------------------------------------ | ||||
| $ git show-ref -s | git commit-graph write --stdin-commits | ||||
| ------------------------------------------------ | ||||
|  | ||||
| * Read basic information from the commit-graph file. | ||||
| + | ||||
| ------------------------------------------------ | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
| static char const * const builtin_commit_graph_usage[] = { | ||||
| 	N_("git commit-graph [--object-dir <objdir>]"), | ||||
| 	N_("git commit-graph read [--object-dir <objdir>]"), | ||||
| 	N_("git commit-graph write [--object-dir <objdir>] [--stdin-packs]"), | ||||
| 	N_("git commit-graph write [--object-dir <objdir>] [--stdin-packs|--stdin-commits]"), | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
| @ -18,13 +18,14 @@ static const char * const builtin_commit_graph_read_usage[] = { | ||||
| }; | ||||
|  | ||||
| static const char * const builtin_commit_graph_write_usage[] = { | ||||
| 	N_("git commit-graph write [--object-dir <objdir>] [--stdin-packs]"), | ||||
| 	N_("git commit-graph write [--object-dir <objdir>] [--stdin-packs|--stdin-commits]"), | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
| static struct opts_commit_graph { | ||||
| 	const char *obj_dir; | ||||
| 	int stdin_packs; | ||||
| 	int stdin_commits; | ||||
| } opts; | ||||
|  | ||||
| static int graph_read(int argc, const char **argv) | ||||
| @ -79,6 +80,8 @@ static int graph_write(int argc, const char **argv) | ||||
| { | ||||
| 	const char **pack_indexes = NULL; | ||||
| 	int packs_nr = 0; | ||||
| 	const char **commit_hex = NULL; | ||||
| 	int commits_nr = 0; | ||||
| 	const char **lines = NULL; | ||||
| 	int lines_nr = 0; | ||||
| 	int lines_alloc = 0; | ||||
| @ -89,6 +92,8 @@ static int graph_write(int argc, const char **argv) | ||||
| 			N_("The object directory to store the graph")), | ||||
| 		OPT_BOOL(0, "stdin-packs", &opts.stdin_packs, | ||||
| 			N_("scan pack-indexes listed by stdin for commits")), | ||||
| 		OPT_BOOL(0, "stdin-commits", &opts.stdin_commits, | ||||
| 			N_("start walk at commits listed by stdin")), | ||||
| 		OPT_END(), | ||||
| 	}; | ||||
|  | ||||
| @ -96,10 +101,12 @@ static int graph_write(int argc, const char **argv) | ||||
| 			     builtin_commit_graph_write_options, | ||||
| 			     builtin_commit_graph_write_usage, 0); | ||||
|  | ||||
| 	if (opts.stdin_packs && opts.stdin_commits) | ||||
| 		die(_("cannot use both --stdin-commits and --stdin-packs")); | ||||
| 	if (!opts.obj_dir) | ||||
| 		opts.obj_dir = get_object_directory(); | ||||
|  | ||||
| 	if (opts.stdin_packs) { | ||||
| 	if (opts.stdin_packs || opts.stdin_commits) { | ||||
| 		struct strbuf buf = STRBUF_INIT; | ||||
| 		lines_nr = 0; | ||||
| 		lines_alloc = 128; | ||||
| @ -110,13 +117,21 @@ static int graph_write(int argc, const char **argv) | ||||
| 			lines[lines_nr++] = strbuf_detach(&buf, NULL); | ||||
| 		} | ||||
|  | ||||
| 		pack_indexes = lines; | ||||
| 		packs_nr = lines_nr; | ||||
| 		if (opts.stdin_packs) { | ||||
| 			pack_indexes = lines; | ||||
| 			packs_nr = lines_nr; | ||||
| 		} | ||||
| 		if (opts.stdin_commits) { | ||||
| 			commit_hex = lines; | ||||
| 			commits_nr = lines_nr; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	write_commit_graph(opts.obj_dir, | ||||
| 			   pack_indexes, | ||||
| 			   packs_nr); | ||||
| 			   packs_nr, | ||||
| 			   commit_hex, | ||||
| 			   commits_nr); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -551,7 +551,9 @@ static void close_reachable(struct packed_oid_list *oids) | ||||
|  | ||||
| void write_commit_graph(const char *obj_dir, | ||||
| 			const char **pack_indexes, | ||||
| 			int nr_packs) | ||||
| 			int nr_packs, | ||||
| 			const char **commit_hex, | ||||
| 			int nr_commits) | ||||
| { | ||||
| 	struct packed_oid_list oids; | ||||
| 	struct packed_commit_list commits; | ||||
| @ -591,7 +593,28 @@ void write_commit_graph(const char *obj_dir, | ||||
| 			close_pack(p); | ||||
| 		} | ||||
| 		strbuf_release(&packname); | ||||
| 	} else | ||||
| 	} | ||||
|  | ||||
| 	if (commit_hex) { | ||||
| 		for (i = 0; i < nr_commits; i++) { | ||||
| 			const char *end; | ||||
| 			struct object_id oid; | ||||
| 			struct commit *result; | ||||
|  | ||||
| 			if (commit_hex[i] && parse_oid_hex(commit_hex[i], &oid, &end)) | ||||
| 				continue; | ||||
|  | ||||
| 			result = lookup_commit_reference_gently(&oid, 1); | ||||
|  | ||||
| 			if (result) { | ||||
| 				ALLOC_GROW(oids.list, oids.nr + 1, oids.alloc); | ||||
| 				oidcpy(&oids.list[oids.nr], &(result->object.oid)); | ||||
| 				oids.nr++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!pack_indexes && !commit_hex) | ||||
| 		for_each_packed_object(add_packed_commits, &oids, 0); | ||||
|  | ||||
| 	close_reachable(&oids); | ||||
|  | ||||
| @ -38,6 +38,8 @@ struct commit_graph *load_commit_graph_one(const char *graph_file); | ||||
|  | ||||
| void write_commit_graph(const char *obj_dir, | ||||
| 			const char **pack_indexes, | ||||
| 			int nr_packs); | ||||
| 			int nr_packs, | ||||
| 			const char **commit_hex, | ||||
| 			int nr_commits); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -177,6 +177,19 @@ test_expect_success 'build graph from latest pack with closure' ' | ||||
| graph_git_behavior 'graph from pack, commit 8 vs merge 1' full commits/8 merge/1 | ||||
| graph_git_behavior 'graph from pack, commit 8 vs merge 2' full commits/8 merge/2 | ||||
|  | ||||
| test_expect_success 'build graph from commits with closure' ' | ||||
| 	cd "$TRASH_DIRECTORY/full" && | ||||
| 	git tag -a -m "merge" tag/merge merge/2 && | ||||
| 	git rev-parse tag/merge >commits-in && | ||||
| 	git rev-parse merge/1 >>commits-in && | ||||
| 	cat commits-in | git commit-graph write --stdin-commits && | ||||
| 	test_path_is_file $objdir/info/commit-graph && | ||||
| 	graph_read_expect "6" | ||||
| ' | ||||
|  | ||||
| graph_git_behavior 'graph from commits, commit 8 vs merge 1' full commits/8 merge/1 | ||||
| graph_git_behavior 'graph from commits, commit 8 vs merge 2' full commits/8 merge/2 | ||||
|  | ||||
| test_expect_success 'setup bare repo' ' | ||||
| 	cd "$TRASH_DIRECTORY" && | ||||
| 	git clone --bare --no-local full bare && | ||||
|  | ||||
		Reference in New Issue
	
	Block a user