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

[PATCH] Short-circuit git-clone-pack while cloning locally (take 2).

From
Junio C Hamano <junkio@cox.net>
Date
Jul 6, 2005, 20:04 UTC
Message-ID
<7vd5pvwvju.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<Pine.LNX.4.58.0507060911510.3570@g5.osdl.org>

When we are cloning a repository on a local filesystem, it is faster to just create a hard linkfarm of .git/object hierarchy and copy the .git/refs files. By default, the script uses the clone-pack method, but it can be told with the -l flag to do the hard linkfarm (falling back on recursive file copy) to replicate the .git/object hierarchy.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 git-clone-script |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 67 insertions(+), 1 deletions(-)
2bff57b39b9fd13b1319d0192e2a887eb82fa189
diff --git a/git-clone-script b/git-clone-script
--- a/git-clone-script
+++ b/git-clone-script
@@ -1,4 +1,70 @@
 #!/bin/sh
+#
+# Copyright (c) 2005, Linus Torvalds
+# Copyright (c) 2005, Junio C Hamano
+# 
+# Clone a repository into a different directory that does not yet exist.
+
+usage() {
+	echo >&2 "* git clone [-l] <repo> <dir>"
+	exit 1
+}
+
+use_local=no
+while
+	case "$#,$1" in
+	0,*) break ;;
+        *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
+	*,-*) usage ;;
+	*) break ;;
+	esac
+do
+	shift
+done
+
 repo="$1"
 dir="$2"
-mkdir "$dir" && cd "$dir" && git-init-db && git-clone-pack "$repo"
+mkdir "$dir" &&
+D=$(
+	(cd "$dir" && git-init-db && pwd)
+) &&
+test -d "$D" || usage
+
+# We do local magic only when the user tells us to.
+case "$use_local" in
+yes)
+	( cd "$repo/objects" ) || {
+		repo="$repo/.git"
+		( cd "$repo/objects" ) || {
+		    echo >&2 "-l flag seen but $repo is not local."
+		    exit 1
+		}
+	}
+
+	# See if we can hardlink and drop "l" if not.
+	sample_file=$(cd "$repo" && \
+		      find objects -type f -print | sed -e 1q)
+
+	# objects directory should not be empty since we are cloning!
+	test -f "$repo/$sample_file" || exit
+
+	l=
+	if ln "$repo/$sample_file" "$D/.git/objects/sample" 2>/dev/null
+	then
+		l=l
+	fi &&
+	rm -f "$D/.git/objects/sample" &&
+	cp -r$l "$repo/objects" "$D/.git/" || exit 1
+
+	# Make a duplicate of refs and HEAD pointer
+	HEAD=
+	if test -f "$repo/HEAD"
+	then
+		HEAD=HEAD
+	fi
+	tar Ccf "$repo" - refs $HEAD | tar Cxf "$D/.git" - || exit 1
+	exit 0
+	;;
+esac
+
+cd "$D" && git clone-pack "$repo"
Previous: Junio C Hamano
Message 14 of 14 in “expensive local git clone”
  1. David S. MillerJul 4, 2005
  2. Linus TorvaldsJul 4, 2005
  3. Petr BaudisJul 4, 2005
  4. David S. MillerJul 4, 2005
  5. Junio C HamanoJul 4, 2005
  6. David S. MillerJul 4, 2005
  7. Junio C HamanoJul 4, 2005
  8. Linus TorvaldsJul 4, 2005
  9. Short-cut git-fetch-pack while cloning locally.Junio C Hamano, Jul 5, 2005
  10. Linus TorvaldsJul 6, 2005
  11. Short-circuit git-clone-pack while cloning locally.Junio C Hamano, Jul 6, 2005
  12. Linus TorvaldsJul 6, 2005
  13. Junio C HamanoJul 6, 2005
  14. Short-circuit git-clone-pack while cloning locally (take 2).Junio C Hamano, Jul 6, 2005

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.