{"thread":{"id":"1104","subject":"expensive local git clone","startedAt":"2005-07-04T19:57:44Z","lastAt":"2005-07-06T20:04:21Z","messageCount":14,"participants":["David S. Miller","Linus Torvalds","Petr Baudis","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"5639","messageId":"20050704.125744.59481768.davem@davemloft.net","threadId":"1104","inReplyTo":null,"subject":"expensive local git clone","fromName":"David S. Miller","fromEmail":"davem@davemloft.net","sentAt":"2005-07-04T19:57:44Z","receivedAt":"2005-07-04T19:57:44Z","isPatch":false,"sender":{"key":"davem@davemloft.net","avatar":null},"body":"\nI'm still seeing git-local-pull going crazy when attemping local\nclones of kernel trees, this is from top:\n\n22032 davem     18   0 63392  59m  920 R 76.0  5.9   5:33.15 git-local-pull     \n\nand it's still chugging along.  This is from a simple:\n\nbash$ git-clone-script /home/davem/src/GIT/linux-2.6/.git /home/davem/src/GIT/sparc-2.6\n\ninvocation.\n\nI can't be the only person in the world seeing this :-)\nIt usually grows to around 88MB and runs for 8 minutes before\nit finishes.\n\nIt must be walking the whole commit tree to the root or something\nsilly like that.\n"},{"id":"5642","messageId":"Pine.LNX.4.58.0507041327580.3570@g5.osdl.org","threadId":"1104","inReplyTo":"20050704.125744.59481768.davem@davemloft.net","subject":"Re: expensive local git clone","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-04T20:39:09Z","receivedAt":"2005-07-04T20:39:09Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 4 Jul 2005, David S. Miller wrote:\n> \n> I can't be the only person in the world seeing this :-)\n> It usually grows to around 88MB and runs for 8 minutes before\n> it finishes.\n\nI'm making something based on pack-files.\n\ngit-local-pull is indeed walking the whole tree and copying one file at a\ntime. We shouldn't use \"git-fetch-script\" in \"git clone\" (it's really\ndesigned for doing one file at a time and for small updates),\n\nThat said, the pack-file thing I'm working on won't be perfect either, and\nthe main advantage is that it should work over ssh. The fastest way to do\na clone is really to do a recursive hardlinked tree, so you may well want\nto just do\n\n\t#!/bin/sh\n\tmkdir \"$2\" && cp -rl \"$1/.git\" \"$2/.git\"\n\nand it should be about a million times faster and equally effective.\n\nUntested, of course.\n\n\t\tLinus\n"},{"id":"5643","messageId":"20050704204235.GE21128@pasky.ji.cz","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507041327580.3570@g5.osdl.org","subject":"Re: expensive local git clone","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-07-04T20:42:35Z","receivedAt":"2005-07-04T20:42:35Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Mon, Jul 04, 2005 at 10:39:09PM CEST, I got a letter\nwhere Linus Torvalds <torvalds@osdl.org> told me that...\n> That said, the pack-file thing I'm working on won't be perfect either, and\n> the main advantage is that it should work over ssh. The fastest way to do\n> a clone is really to do a recursive hardlinked tree, so you may well want\n> to just do\n> \n> \t#!/bin/sh\n> \tmkdir \"$2\" && cp -rl \"$1/.git\" \"$2/.git\"\n> \n> and it should be about a million times faster and equally effective.\n> \n> Untested, of course.\n\nI wouldn't do that on anything but .git/objects. ;-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\n<Espy> be careful, some twit might quote you out of context..\n"},{"id":"5645","messageId":"20050704.140043.112609056.davem@davemloft.net","threadId":"1104","inReplyTo":"20050704204235.GE21128@pasky.ji.cz","subject":"Re: expensive local git clone","fromName":"David S. Miller","fromEmail":"davem@davemloft.net","sentAt":"2005-07-04T21:00:43Z","receivedAt":"2005-07-04T21:00:43Z","isPatch":false,"sender":{"key":"davem@davemloft.net","avatar":null},"body":"From: Petr Baudis <pasky@suse.cz>\nDate: Mon, 4 Jul 2005 22:42:35 +0200\n\n> Dear diary, on Mon, Jul 04, 2005 at 10:39:09PM CEST, I got a letter\n> where Linus Torvalds <torvalds@osdl.org> told me that...\n> > That said, the pack-file thing I'm working on won't be perfect either, and\n> > the main advantage is that it should work over ssh. The fastest way to do\n> > a clone is really to do a recursive hardlinked tree, so you may well want\n> > to just do\n> > \n> > \t#!/bin/sh\n> > \tmkdir \"$2\" && cp -rl \"$1/.git\" \"$2/.git\"\n> > \n> > and it should be about a million times faster and equally effective.\n> > \n> > Untested, of course.\n> \n> I wouldn't do that on anything but .git/objects. ;-)\n\nAgreed.  When I do it by hand (but I shouldn't have to\ndo this by hand, git-clone-script should do it this way\nif that's the best and most efficient) I usually link the\nobject directory then copy the rest of the stuff non-linked.\n\nI keep hoping git-clone-script is going to be a good way\nto clone two local trees.  Is my hope misguided?  :-)\n"},{"id":"5646","messageId":"7v7jg6i72c.fsf@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"20050704.140043.112609056.davem@davemloft.net","subject":"Re: expensive local git clone","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-04T21:40:11Z","receivedAt":"2005-07-04T21:40:11Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"DSM\" == David S Miller <davem@davemloft.net> writes:\n\nDSM> I keep hoping git-clone-script is going to be a good way\nDSM> to clone two local trees.  Is my hope misguided?  :-)\n\nSomething along these lines?\n------------\nShort-cut \"git fetch\" when cloning locally.\n\nInstead of calling local-pull to \"do the right thing\", just\nhardlink or copy the object files over when we know we are doing\nthe clone locally.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\ncd /opt/packrat/playpen/public/in-place/git/git.junio/\njit-diff\n# - master: git-format-patch: Prepare patches for e-mail submission.\n# + (working tree)\ndiff --git a/git-clone-script b/git-clone-script\n--- a/git-clone-script\n+++ b/git-clone-script\n@@ -1,7 +1,39 @@\n #!/bin/sh\n repo=\"$1\"\n dir=\"$2\"\n-mkdir $dir || exit 1\n-cd $dir\n-git-init-db\n-git fetch \"$repo\" && ( git-rev-parse FETCH_HEAD > .git/HEAD )\n+mkdir \"$dir\" &&\n+D=$(\n+    (cd \"$dir\" && git-init-db && pwd)\n+) || exit 1\n+\n+# See if repo is a local directory.\n+if (\n+\tcd \"$repo/objects\" 2>/dev/null\n+)\n+then\n+\t# See if we can hardlink and drop \"l\" if not.\n+\tsample_file=$(cd \"$repo\" && find objects -type f -print | sed -e 1q)\n+\n+\t# objects directory should not be empty since we are cloning!\n+\ttest -f \"$repo/$sample_file\" || exit \n+\n+\tif ln \"$repo/$sample_file\" \"$D/.git/objects/sample\" 2>/dev/null\n+\tthen\n+\t    l=l\n+\telse\n+\t    l=\n+\tfi &&\n+\trm -f \"$D/.git/objects/sample\" &&\n+\n+\tcd \"$repo\" &&\n+\tfind objects -type f -print |\n+\tcpio -puam$l \"$D/.git\" || exit 1\n+\n+\t# FETCH_HEAD is always HEAD because we do not do the\n+\t# extra parameter to \"git fetch\".\n+\tpwd\n+\tcat \"HEAD\" >\"$D/.git/FETCH_HEAD\"\n+\tcd \"$D\"\n+else\n+\tcd \"$D\" && git fetch \"$repo\"\n+fi && ( git-rev-parse FETCH_HEAD > .git/HEAD )\n\nCompilation finished at Mon Jul  4 14:37:29\n"},{"id":"5648","messageId":"Pine.LNX.4.58.0507041443510.3570@g5.osdl.org","threadId":"1104","inReplyTo":"20050704.140043.112609056.davem@davemloft.net","subject":"Re: expensive local git clone","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-04T21:44:08Z","receivedAt":"2005-07-04T21:44:08Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 4 Jul 2005, David S. Miller wrote:\n> \n> I keep hoping git-clone-script is going to be a good way\n> to clone two local trees.  Is my hope misguided?  :-)\n\nWell, I'm not working on it, but tested patches...\n\n\t\tLinus\n"},{"id":"5652","messageId":"20050704.154933.104033112.davem@davemloft.net","threadId":"1104","inReplyTo":"7v7jg6i72c.fsf@assigned-by-dhcp.cox.net","subject":"Re: expensive local git clone","fromName":"David S. Miller","fromEmail":"davem@davemloft.net","sentAt":"2005-07-04T22:49:33Z","receivedAt":"2005-07-04T22:49:33Z","isPatch":false,"sender":{"key":"davem@davemloft.net","avatar":null},"body":"From: Junio C Hamano <junkio@cox.net>\nDate: Mon, 04 Jul 2005 14:40:11 -0700\n\n> >>>>> \"DSM\" == David S Miller <davem@davemloft.net> writes:\n> \n> DSM> I keep hoping git-clone-script is going to be a good way\n> DSM> to clone two local trees.  Is my hope misguided?  :-)\n> \n> Something along these lines?\n\nLooks interesting.  Any particular reason to use \"cpio\"\ninstead of \"cp\"?\n"},{"id":"5653","messageId":"7virzqgog2.fsf@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"20050704.154933.104033112.davem@davemloft.net","subject":"Re: expensive local git clone","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-04T23:07:41Z","receivedAt":"2005-07-04T23:07:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"DSM\" == David S Miller <davem@davemloft.net> writes:\n\nDSM> Looks interesting.  Any particular reason to use \"cpio\"\nDSM> instead of \"cp\"?\n\nNo particular reason other than I am just used to doing things\nthat way.\n"},{"id":"5674","messageId":"7vekaddn38.fsf_-_@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507041443510.3570@g5.osdl.org","subject":"[PATCH] Short-cut git-fetch-pack while cloning locally.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-05T20:17:31Z","receivedAt":"2005-07-05T20:17:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> Well, I'm not working on it, but tested patches...\n\nProdded by the hint...\n\n------------\nThe git-fetch-pack command used internally by git-fetch-script\nwhich in turn is used by git-clone-script refuses to run if\nthere is no common head.  When cloning locally, just copy/link the\nobjects directory to avoid its use, since we know there will not\nbe any common head (the target is empty).  It also should be\nmore efficient.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n*** This is slightly different from the one I sent as a response\n*** to David's inquiry, in that it uses cp -rl (or just cp -r)\n*** instead of cpio.  Also I added the copyright notices and one\n*** liner description.\n\n git-clone-script |   43 +++++++++++++++++++++++++++++++++++++++----\n rev-list.c       |    5 ++++-\n 2 files changed, 43 insertions(+), 5 deletions(-)\n\nf33df082e175f7fc717a75e528eab3db1d294576\ndiff --git a/git-clone-script b/git-clone-script\n--- a/git-clone-script\n+++ b/git-clone-script\n@@ -1,7 +1,42 @@\n #!/bin/sh\n+#\n+# Copyright (c) 2005, Linus Torvalds\n+# Copyright (c) 2005, Junio C Hamano\n+# \n+# Clone a repository into a different directory that does not yet exist.\n+\n repo=\"$1\"\n dir=\"$2\"\n-mkdir $dir || exit 1\n-cd $dir\n-git-init-db\n-git fetch \"$repo\" && ( git-rev-parse FETCH_HEAD > .git/HEAD )\n+mkdir \"$dir\" &&\n+D=$(\n+\t(cd \"$dir\" && git-init-db && pwd)\n+) || exit 1\n+\n+# See if repo is a local directory.\n+if (\n+\tcd \"$repo/objects\" 2>/dev/null\n+)\n+then\n+\t# See if we can hardlink and drop \"l\" if not.\n+\tsample_file=$(cd \"$repo\" && find objects -type f -print | sed -e 1q)\n+\n+\t# objects directory should not be empty since we are cloning!\n+\ttest -f \"$repo/$sample_file\" || exit\n+\n+\tif ln \"$repo/$sample_file\" \"$D/.git/objects/sample\" 2>/dev/null\n+\tthen\n+\t\tl=l\n+\telse\n+\t\tl=\n+\tfi &&\n+\trm -f \"$D/.git/objects/sample\" &&\n+\n+\tcp -r$l \"$repo/objects\" \"$D/.git/\" || exit 1\n+\n+\t# FETCH_HEAD is always HEAD because we do not do the\n+\t# extra parameter to \"git fetch\".\n+\tcat \"$repo/HEAD\" >\"$D/.git/FETCH_HEAD\"\n+\tcd \"$D\"\n+else\n+\tcd \"$D\" && git fetch \"$repo\"\n+fi && git-rev-parse FETCH_HEAD > .git/HEAD\ndiff --git a/rev-list.c b/rev-list.c\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -482,7 +482,10 @@ int main(int argc, char **argv)\n \t\tcommit = get_commit_reference(arg, flags);\n \t\tif (!commit)\n \t\t\tcontinue;\n-\t\tinsert_by_date(&list, commit);\n+\t\tif (!merge_order)\n+\t\t\tinsert_by_date(&list, commit);\n+\t\telse\n+\t\t\tcommit_list_insert(commit, &list);\n \t}\n \n \tif (!merge_order) {\t\t\n"},{"id":"5683","messageId":"Pine.LNX.4.58.0507051721450.3570@g5.osdl.org","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507041327580.3570@g5.osdl.org","subject":"Re: expensive local git clone","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-06T00:42:00Z","receivedAt":"2005-07-06T00:42:00Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 4 Jul 2005, Linus Torvalds wrote:\n> \n> I'm making something based on pack-files.\n\nOk, as of a few minutes ago there's now a pack-based \"git clone\" there. Of \ncourse, it hasn't percolated out to the mirrors yet, so you'll not see it \nfor a while unless you have a master.kernel.org account like David, but \nbasically you can do\n\n\tgit clone /some/absolute/path new-dir\n\nand it will clone the old project into new-dir using pack-files. The need \nfor an absolute path in the source is just because the \"git clone\" script \nends up \"cd'ing\" to the new directory before the clone, so a relative path \nwould need to be relative to the \"new-dir\" location, which is just \nconfusing. Oh, well.\n\nAnyway, as mentioned, you can certainly do a local clone a lot faster with \n\"cp -rl\" (and yes, I'll apply Junio's patch if he makes it available \nagainst the new version, and adds a flag to make it conditional), but \nusing a pack-file means that the new thing not only will be totally \nindependent of the old one (which you may _want_ to do, especially if they \nare on different filesystems), but it also means that the above works over \nssh too, ie\n\n\tgit clone master.kernel.org:/pub/scm/git/git.git my-git\n\nshould now do the right thing (indeed, I've even tested it - although I've\nnot tried it with things like multiple branches etc, which _should_ all\nwork automatically but.. I'm pulling Jeff's tree as I write this, but \nmaster.kernel.org is slow, so it will be some time..).\n\nBtw, one small note: when doing a \"git clone\", the newly cloned repo will \nnot be checked out, and \"master\" will be the default HEAD regardless of \nwhat the other happened to be at (unless the other side was really screwed \nup and we can't match up any \"master\" at all). So use \"git checkout xxx\" \nto actually set whatever branch you want to use after a clone.\n\n\t\tLinus\n"},{"id":"5701","messageId":"7v8y0kxsfq.fsf_-_@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507051721450.3570@g5.osdl.org","subject":"[PATCH] Short-circuit git-clone-pack while cloning locally.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-06T08:14:01Z","receivedAt":"2005-07-06T08:14:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> Anyway, as mentioned, you can certainly do a local clone a lot faster with \nLT> \"cp -rl\" (and yes, I'll apply Junio's patch if he makes it available \nLT> against the new version, and adds a flag to make it conditional),...\n\nBy invitation.\n\n------------\nWhen we are cloning a repository on a local filesystem, it is\nfaster to just create a hard linkfarm of .git/object hierarchy\nand copy the .git/refs files.  By default, the script uses the\nclone-pack method, but with -l and -c parameters it can be told\nto do the hard linkfarm and recursive file copy to replicate\n.git/object hierarchy.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n git-clone-script |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 79 insertions(+), 1 deletions(-)\n\n1eb81b1791a751ca0fd1c3e7c1d4a4baacdd042a\ndiff --git a/git-clone-script b/git-clone-script\n--- a/git-clone-script\n+++ b/git-clone-script\n@@ -1,4 +1,81 @@\n #!/bin/sh\n+#\n+# Copyright (c) 2005, Linus Torvalds\n+# Copyright (c) 2005, Junio C Hamano\n+# \n+# Clone a repository into a different directory that does not yet exist.\n+\n+usage() {\n+\techo >&2 \"* git clone [-l|-c|-p] <repo> <dir>\"\n+\texit 1\n+}\n+\n+# what to do when running locally\n+local_use=default\n+while\n+\tcase \"$#,$1\" in\n+\t0,*) break ;;\n+\t*,-l) local_use=link ;;\n+\t*,-c) local_use=copy ;;\n+\t*,-p) local_use=pack ;;\n+\t*,-*) usage ;;\n+\t*) break ;;\n+\tesac\n+do\n+\tshift\n+done\n+\n repo=\"$1\"\n dir=\"$2\"\n-mkdir \"$dir\" && cd \"$dir\" && git-init-db && git-clone-pack \"$repo\"\n+mkdir \"$dir\" &&\n+D=$(\n+\t(cd \"$dir\" && git-init-db && pwd)\n+) || exit 1\n+\n+# See if repo is a local directory.\n+is_local=f\n+if (\n+\tcd \"$repo/objects\" 2>/dev/null\n+)\n+then\n+\tis_local=t\n+fi\n+\n+case \"$local_use,$is_local\" in\n+default,f)\n+\t;;\n+*,f)\techo >&2 \"-l|-c|-p flag can be used only when cloning a local repo\"\n+\texit 1\n+\t;;\n+copy,t | link,t)\n+\tl=\n+\tcase \"$local_use\" in\n+\tlink)\n+\t    # See if we can hardlink and drop \"l\" if not.\n+\t    sample_file=$(cd \"$repo\" && \\\n+\t    \t\t  find objects -type f -print | sed -e 1q)\n+\n+\t    # objects directory should not be empty since we are cloning!\n+\t    test -f \"$repo/$sample_file\" || exit\n+\n+\t    if ln \"$repo/$sample_file\" \"$D/.git/objects/sample\" 2>/dev/null\n+\t    then\n+\t\t    l=l\n+\t    fi &&\n+\t    rm -f \"$D/.git/objects/sample\"\n+\t    ;;\n+\tesac &&\n+\tcp -r$l \"$repo/objects\" \"$D/.git/\" || exit 1\n+\n+\t# Make a duplicate of refs and HEAD pointer\n+\tHEAD=\n+\tif test -f \"$repo/HEAD\"\n+\tthen\n+\t\tHEAD=HEAD\n+\tfi\n+\ttar Ccf \"$repo\" - refs $HEAD | tar Cxf \"$D/.git\" - || exit 1\n+\t;;\n+*)\n+\tcd \"$D\" && git clone-pack \"$repo\"\n+\t;;\n+esac\n"},{"id":"5711","messageId":"Pine.LNX.4.58.0507060911510.3570@g5.osdl.org","threadId":"1104","inReplyTo":"7v8y0kxsfq.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Short-circuit git-clone-pack while cloning locally.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-06T16:13:12Z","receivedAt":"2005-07-06T16:13:12Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 6 Jul 2005, Junio C Hamano wrote:\n> \n> By invitation.\n> \n> ------------\n> When we are cloning a repository on a local filesystem [...]\n\nHmm.. Did you test the ssh case?\n\n> +case \"$local_use,$is_local\" in\n> +default,f)\n> +\t;;\n\nIt would seem that you don't do anything at all for the non-local case.\n\n\t\tLinus\n"},{"id":"5728","messageId":"7vy88jx1au.fsf@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507060911510.3570@g5.osdl.org","subject":"Re: [PATCH] Short-circuit git-clone-pack while cloning locally.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-06T18:00:09Z","receivedAt":"2005-07-06T18:00:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> It would seem that you don't do anything at all for the non-local case.\n\nOops.\n"},{"id":"5744","messageId":"7vd5pvwvju.fsf@assigned-by-dhcp.cox.net","threadId":"1104","inReplyTo":"Pine.LNX.4.58.0507060911510.3570@g5.osdl.org","subject":"[PATCH] Short-circuit git-clone-pack while cloning locally (take 2).","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-06T20:04:21Z","receivedAt":"2005-07-06T20:04:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When we are cloning a repository on a local filesystem, it is\nfaster to just create a hard linkfarm of .git/object hierarchy\nand copy the .git/refs files.  By default, the script uses the\nclone-pack method, but it can be told with the -l flag to do the\nhard linkfarm (falling back on recursive file copy) to replicate\nthe .git/object hierarchy.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n git-clone-script |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 67 insertions(+), 1 deletions(-)\n\n2bff57b39b9fd13b1319d0192e2a887eb82fa189\ndiff --git a/git-clone-script b/git-clone-script\n--- a/git-clone-script\n+++ b/git-clone-script\n@@ -1,4 +1,70 @@\n #!/bin/sh\n+#\n+# Copyright (c) 2005, Linus Torvalds\n+# Copyright (c) 2005, Junio C Hamano\n+# \n+# Clone a repository into a different directory that does not yet exist.\n+\n+usage() {\n+\techo >&2 \"* git clone [-l] <repo> <dir>\"\n+\texit 1\n+}\n+\n+use_local=no\n+while\n+\tcase \"$#,$1\" in\n+\t0,*) break ;;\n+        *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;\n+\t*,-*) usage ;;\n+\t*) break ;;\n+\tesac\n+do\n+\tshift\n+done\n+\n repo=\"$1\"\n dir=\"$2\"\n-mkdir \"$dir\" && cd \"$dir\" && git-init-db && git-clone-pack \"$repo\"\n+mkdir \"$dir\" &&\n+D=$(\n+\t(cd \"$dir\" && git-init-db && pwd)\n+) &&\n+test -d \"$D\" || usage\n+\n+# We do local magic only when the user tells us to.\n+case \"$use_local\" in\n+yes)\n+\t( cd \"$repo/objects\" ) || {\n+\t\trepo=\"$repo/.git\"\n+\t\t( cd \"$repo/objects\" ) || {\n+\t\t    echo >&2 \"-l flag seen but $repo is not local.\"\n+\t\t    exit 1\n+\t\t}\n+\t}\n+\n+\t# See if we can hardlink and drop \"l\" if not.\n+\tsample_file=$(cd \"$repo\" && \\\n+\t\t      find objects -type f -print | sed -e 1q)\n+\n+\t# objects directory should not be empty since we are cloning!\n+\ttest -f \"$repo/$sample_file\" || exit\n+\n+\tl=\n+\tif ln \"$repo/$sample_file\" \"$D/.git/objects/sample\" 2>/dev/null\n+\tthen\n+\t\tl=l\n+\tfi &&\n+\trm -f \"$D/.git/objects/sample\" &&\n+\tcp -r$l \"$repo/objects\" \"$D/.git/\" || exit 1\n+\n+\t# Make a duplicate of refs and HEAD pointer\n+\tHEAD=\n+\tif test -f \"$repo/HEAD\"\n+\tthen\n+\t\tHEAD=HEAD\n+\tfi\n+\ttar Ccf \"$repo\" - refs $HEAD | tar Cxf \"$D/.git\" - || exit 1\n+\texit 0\n+\t;;\n+esac\n+\n+cd \"$D\" && git clone-pack \"$repo\"\n"}]}