{"thread":{"id":"32554","subject":"[PATCH] add warning for depth=0 in git clone.","startedAt":"2013-01-08T08:07:02Z","lastAt":"2013-01-11T09:05:48Z","messageCount":18,"participants":["Stefan Beller","Jonathan Nieder","Duy Nguyen","Junio C Hamano","Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"206275","messageId":"1357632422-5686-1-git-send-email-stefanbeller@googlemail.com","threadId":"32554","inReplyTo":null,"subject":"[PATCH] add warning for depth=0 in git clone.","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-01-08T08:07:02Z","receivedAt":"2013-01-08T08:07:02Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"---\n builtin/clone.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex ec2f75b..5e91c1e 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -818,6 +818,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tremote = remote_get(option_origin);\n \ttransport = transport_get(remote, remote->url[0]);\n \n+\tif (option_depth && transport->smart_options->depth < 1)\n+\t\tdie(_(\"--depth less or equal 0 makes no sense; read manpage.\"));\n+\n \tif (!is_local) {\n \t\tif (!transport->get_refs_list || !transport->fetch)\n \t\t\tdie(_(\"Don't know how to clone %s\"), transport->url);\n-- \n1.8.1.166.g27cbb96\n"},{"id":"206276","messageId":"50EBD453.9050101@googlemail.com","threadId":"32554","inReplyTo":"1357632422-5686-1-git-send-email-stefanbeller@googlemail.com","subject":"Re: [PATCH] add warning for depth=0 in git clone.","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-01-08T08:09:55Z","receivedAt":"2013-01-08T08:09:55Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Hi,\n\nI am struggling a little with the development process,\nis a sign-off strictly required for git as it is for kernel development?\nIf so here would be my sign-off:\n\nSigned-off-by: Stefan Beller <stefanbeller@googlemail.com>\n\nThis adds a warning and the previous patch adds the documentation.\n\nHowever I agree to Junio, that the meaning should actually\ndepth=0 -> just the tip and no (0) other commits before.\n\ndepth=n -> the tip and n other commits before.\n\n\nOn 01/08/2013 09:07 AM, Stefan Beller wrote:\n> ---\n>  builtin/clone.c | 3 +++\n>  1 file changed, 3 insertions(+)\n> \n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index ec2f75b..5e91c1e 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -818,6 +818,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n>  \tremote = remote_get(option_origin);\n>  \ttransport = transport_get(remote, remote->url[0]);\n>  \n> +\tif (option_depth && transport->smart_options->depth < 1)\n> +\t\tdie(_(\"--depth less or equal 0 makes no sense; read manpage.\"));\n> +\n>  \tif (!is_local) {\n>  \t\tif (!transport->get_refs_list || !transport->fetch)\n>  \t\t\tdie(_(\"Don't know how to clone %s\"), transport->url);\n> \n"},{"id":"206277","messageId":"20130108081221.GA5722@elie.Belkin","threadId":"32554","inReplyTo":"1357632422-5686-1-git-send-email-stefanbeller@googlemail.com","subject":"Re: [PATCH] add warning for depth=0 in git clone.","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-01-08T08:12:21Z","receivedAt":"2013-01-08T08:12:21Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Stefan Beller wrote:\n\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -818,6 +818,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n>  \tremote = remote_get(option_origin);\n>  \ttransport = transport_get(remote, remote->url[0]);\n>  \n> +\tif (option_depth && transport->smart_options->depth < 1)\n> +\t\tdie(_(\"--depth less or equal 0 makes no sense; read manpage.\"));\n\n\"Makes no sense\" is a little harsh.  Presumably it made sense to the\nuser, or she wouldn't have passed that option.  The relevant point is\nthat git was not able to make sense of it.\n\nHow about something like\n\n\tfatal: shallow clone must have positive depth\n\n?  The \"see manpage\" is always implied by die(), and I don't see any\nparticular reason to point to a specific section here.\n\nHope that helps,\nJonathan\n"},{"id":"206278","messageId":"20130108081401.GB5722@elie.Belkin","threadId":"32554","inReplyTo":"50EBD453.9050101@googlemail.com","subject":"Re: [PATCH] add warning for depth=0 in git clone.","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-01-08T08:14:01Z","receivedAt":"2013-01-08T08:14:01Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Stefan Beller wrote:\n\n> I am struggling a little with the development process,\n> is a sign-off strictly required for git as it is for kernel development?\n\nYes.  Documentation/SubmittingPatches has more hints.\n\n> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>\n>\n> This adds a warning and the previous patch adds the documentation.\n\nThanks for your work on this.\n"},{"id":"206347","messageId":"CACsJy8BLLTWd+cTBj1jNW=ODPy7=Kg4-TPUdZ82YCE-0RQpMZA@mail.gmail.com","threadId":"32554","inReplyTo":"1357632422-5686-1-git-send-email-stefanbeller@googlemail.com","subject":"Re: [PATCH] add warning for depth=0 in git clone.","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-09T00:57:43Z","receivedAt":"2013-01-09T00:57:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Jan 8, 2013 at 3:07 PM, Stefan Beller\n<stefanbeller@googlemail.com> wrote:\n> ---\n>  builtin/clone.c | 3 +++\n>  1 file changed, 3 insertions(+)\n>\n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index ec2f75b..5e91c1e 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -818,6 +818,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n>         remote = remote_get(option_origin);\n>         transport = transport_get(remote, remote->url[0]);\n>\n> +       if (option_depth && transport->smart_options->depth < 1)\n> +               die(_(\"--depth less or equal 0 makes no sense; read manpage.\"));\n> +\n\nIsn't this too early for the check? The following code is\n\n>         if (!is_local) {\n>                 if (!transport->get_refs_list || !transport->fetch)\n>                         die(_(\"Don't know how to clone %s\"), transport->url);\n\n\t\ttransport_set_option(transport, TRANS_OPT_KEEP, \"yes\");\n\n\t\tif (option_depth)\n\t\t\ttransport_set_option(transport, TRANS_OPT_DEPTH,\n\t\t\t\t\t     option_depth);\n\n\nwhere transport_set_option() calls set_git_option() to initialize\ntransport->smart_options->depth. A check should be done after this\npoint.\n-- \nDuy\n"},{"id":"206350","messageId":"7vy5g383sy.fsf_-_@alter.siamese.dyndns.org","threadId":"32554","inReplyTo":"CACsJy8BLLTWd+cTBj1jNW=ODPy7=Kg4-TPUdZ82YCE-0RQpMZA@mail.gmail.com","subject":"On --depth=funny value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-09T02:53:49Z","receivedAt":"2013-01-09T02:53:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Here to outline my current thinking.  Note that this is unrelated to\nthe \"git clone --bottom=v1.2.3\" to say \"I do not care about anything\nthat happened before that version\".\n\n * First, let's *not* do \"git fetch --depth=inf\"; if you want to\n   unplug the bottom of your shallow clone, be more explicit and\n   introduce a new option, e.g. \"git fetch --unshallow\", or\n   something.\n\n * Make \"git fetch\" and \"git clone\" die() when zero or negative\n   number is given with --depth=$N, for the following reasons:\n\n   - The --depth option is describe as:\n\n         (\"git clone\") ... a 'shallow' clone with a history\n         truncated to the specified number of revisions.\n\n         (\"git fetch\") Limit fetching to ancestor-chains not longer\n         than n.\n\n     It is fairly clear from the above that negative $N does not\n     make any sense.\n\n     Technically, fetching the commits that were explicitly asked\n     for and not there parents is the only possible ancestor-chain\n     that is not longer than -4, so \"git fetch --depth=-4\" ought to\n     behave just like \"git fetch --depth=0\", but you have to be very\n     sick to read the documentation and expect things to work that\n     way.  Also there is no way to misread the \"git clone\"\n     documentation and expect \"git clone --depth=-4\" to create a\n     history truncated to negative number of revisions.\n\n     Which means that it is the right thing to do to die() when a\n     negative number is given to --depth for these commands.\n\n   - As people count from one, the natural way to ask for the tip\n     commit without any history ought to be \"--depth=1\".  Let's\n     declare the current behaviour of \"--depth=1\" that gives the tip\n     and one commit behind it a bug.\n\n     Which means that these commands should be updated to die() when\n     zero is given to their --depth option.  \"Do not give me any\n     history\" is inherenty incompatibe with \"clone\" or \"fetch\".\n\n     Because there is no configuration variable \"fetch.depth\" (or\n     \"clone.depth\") that forces all your cloned repositories to be\n     shallow, \"git clone --depth=0\" or \"git fetch --depth=0\"\n     couldn't have been ways for existing users to ask to defeat any\n     funny configured depth value and clone or fetch everything.\n     When they wanted to clone or fetch everything, they would have\n     just used the command without any \"--depth\" option instead.\n\n     Which means that nobody gets hurt if we change these commands\n     to die() when zero is given to their --depth option.\n\n * We would like to update \"clone --depth=1\" to end up with a tip\n   only repository, but let's not to touch \"git fetch\" (and \"git\n   clone\") and make them send 0 over the wire when the command line\n   tells them to use \"--depth=1\" (i.e. let's not do the \"off-by-one\"\n   thing).\n\n   Instead, fix \"upload-pack\" (the bug is in get_shallow_commits()\n   in shallow.c, I think), so that it counts correctly.  When the\n   other end asks for a history with 1-commit deep, it should return\n   a history that is 1-commit deep, and tell the other end about the\n   parents of the returned history, instead of returning a history\n   that is 2 commmits deep.  So when talking with a newer server,\n   clients will get correct number of commits; when talkng with an\n   older server, clients will get a bit more than they asked, but\n   nothing will break.\n\nCan people sanity check the reasoning outlined here?  Anything I\nmissed?\n\nThe above outline identifies three concrete tasks that different\npeople can tackle more or less independently, each with updated\ncode, documentation and test:\n\n 1. \"git fetch --unshallow\" that gives a pretty surface on Duy's\n    \"--depth=inf\";\n\n 2. Making \"git fetch\" and \"git clone\" die on \"--depth=0\" or\n    \"--depth=-4\";\n\n 3 Updating \"upload-pack\" to count correctly.\n\nI'll refrain from saying \"Any takers?\" for now.\n"},{"id":"206351","messageId":"CACsJy8CA-a0=HqTY9heJBhPO4M5jyLk=tf253rRKCRuTWz5teg@mail.gmail.com","threadId":"32554","inReplyTo":"7vy5g383sy.fsf_-_@alter.siamese.dyndns.org","subject":"Re: On --depth=funny value","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-09T04:18:30Z","receivedAt":"2013-01-09T04:18:30Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jan 9, 2013 at 9:53 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>  * First, let's *not* do \"git fetch --depth=inf\"; if you want to\n>    unplug the bottom of your shallow clone, be more explicit and\n>    introduce a new option, e.g. \"git fetch --unshallow\", or\n>    something.\n\nNo problem. \"Something\" could be --no-depth or --no-shallow. I think\nany of them is better than --unshallow.\n\n>  * We would like to update \"clone --depth=1\" to end up with a tip\n>    only repository, but let's not to touch \"git fetch\" (and \"git\n>    clone\") and make them send 0 over the wire when the command line\n>    tells them to use \"--depth=1\" (i.e. let's not do the \"off-by-one\"\n>    thing).\n\nYou can't anyway. Depth 0 on the wire is considered invalid by upload-pack.\n\n>    Instead, fix \"upload-pack\" (the bug is in get_shallow_commits()\n>    in shallow.c, I think), so that it counts correctly.  When the\n>    other end asks for a history with 1-commit deep, it should return\n>    a history that is 1-commit deep, and tell the other end about the\n>    parents of the returned history, instead of returning a history\n>    that is 2 commmits deep.  So when talking with a newer server,\n>    clients will get correct number of commits; when talkng with an\n>    older server, clients will get a bit more than they asked, but\n>    nothing will break.\n\nI'll need to look at get_shallow_commits() anyway for the unshallow\npatch. I'll probably do this too.\n-- \nDuy\n"},{"id":"206352","messageId":"7vr4lv7x2u.fsf@alter.siamese.dyndns.org","threadId":"32554","inReplyTo":"CACsJy8CA-a0=HqTY9heJBhPO4M5jyLk=tf253rRKCRuTWz5teg@mail.gmail.com","subject":"Re: On --depth=funny value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-09T05:19:05Z","receivedAt":"2013-01-09T05:19:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Wed, Jan 9, 2013 at 9:53 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> ...\n>>  * We would like to update \"clone --depth=1\" to end up with a tip\n>>    only repository, but let's not to touch \"git fetch\" (and \"git\n>>    clone\") and make them send 0 over the wire when the command line\n>>    tells them to use \"--depth=1\" (i.e. let's not do the \"off-by-one\"\n>>    thing).\n>\n> You can't anyway. Depth 0 on the wire is considered invalid by upload-pack.\n\nYes, that is a good point that we say \"if (0 < opt->depth) do the\nshallow thing\" everywhere, so 0 is spcial in that sense.\n\nWhich suggests that if we wanted to, we could update the fetch side\nto do the off-by-one thing against the current upload-pack when the\ngiven depth is two or more, and still send 1 when depth=1.  When\ntalking with an updated upload-pack that advertises exact-shallow\nprotocol extension, it can disable that off-by-one for all values of\ndepth.  That way, the updated client gets history of wrong depth\nonly for --depth=1 when talking with the current upload-pack; all\nother cases, it will get history of correct depth.\n\nHmm?\n"},{"id":"206380","messageId":"CACsJy8B4SFs5gbrD6vKvpcrv-tyUo+aZAvq=VmVFM1Bsiggu4w@mail.gmail.com","threadId":"32554","inReplyTo":"7vr4lv7x2u.fsf@alter.siamese.dyndns.org","subject":"Re: On --depth=funny value","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-09T14:12:01Z","receivedAt":"2013-01-09T14:12:01Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jan 9, 2013 at 12:19 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> On Wed, Jan 9, 2013 at 9:53 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> ...\n>>>  * We would like to update \"clone --depth=1\" to end up with a tip\n>>>    only repository, but let's not to touch \"git fetch\" (and \"git\n>>>    clone\") and make them send 0 over the wire when the command line\n>>>    tells them to use \"--depth=1\" (i.e. let's not do the \"off-by-one\"\n>>>    thing).\n>>\n>> You can't anyway. Depth 0 on the wire is considered invalid by upload-pack.\n>\n> Yes, that is a good point that we say \"if (0 < opt->depth) do the\n> shallow thing\" everywhere, so 0 is spcial in that sense.\n>\n> Which suggests that if we wanted to, we could update the fetch side\n> to do the off-by-one thing against the current upload-pack when the\n> given depth is two or more, and still send 1 when depth=1.  When\n> talking with an updated upload-pack that advertises exact-shallow\n> protocol extension, it can disable that off-by-one for all values of\n> depth.  That way, the updated client gets history of wrong depth\n> only for --depth=1 when talking with the current upload-pack; all\n> other cases, it will get history of correct depth.\n>\n> Hmm?\n\nI haven't checked because frankly I have never run JGit, but are we\nsure this off-by-one thing applies to JGit server as well? So far I'm\nonly aware of three sever implementations: C Git, JGit and Dulwich.\nThe last one does not support shallow extension so it's out of\nquestion.\n-- \nDuy\n"},{"id":"206381","messageId":"CACsJy8Cp-2gRhdU+V8H7+FeWZXfptJLbzw1swxdks61fO+73NQ@mail.gmail.com","threadId":"32554","inReplyTo":"7vy5g383sy.fsf_-_@alter.siamese.dyndns.org","subject":"Re: On --depth=funny value","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-09T14:59:56Z","receivedAt":"2013-01-09T14:59:56Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jan 9, 2013 at 9:53 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>  * Make \"git fetch\" and \"git clone\" die() when zero or negative\n>    number is given with --depth=$N, for the following reasons:\n>    ...\n\nFor Stefan when you update the patch. If \"git fetch --depth=0\" is\nconsidered invalid too as Junio outlined, then the proper place for\nthe check is transport.c:set_git_option(), not clone.c. It already\ncatches --depth=random-string. Adding \"depth < 1\" check should be\ntrivial. You may want to update builtin/fetch-pack.c too because it\ndoes not share this code.\n-- \nDuy\n"},{"id":"206428","messageId":"50EDE36E.8030700@googlemail.com","threadId":"32554","inReplyTo":"7vy5g383sy.fsf_-_@alter.siamese.dyndns.org","subject":"Re: On --depth=funny value","fromName":"Stefan Beller","fromEmail":"stefanbeller@googlemail.com","sentAt":"2013-01-09T21:38:54Z","receivedAt":"2013-01-09T21:38:54Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On 01/09/2013 03:53 AM, Junio C Hamano wrote:\n> Can people sanity check the reasoning outlined here?  Anything I\n> missed?\n> \n> The above outline identifies three concrete tasks that different\n> people can tackle more or less independently, each with updated\n> code, documentation and test:\n> \n>  1. \"git fetch --unshallow\" that gives a pretty surface on Duy's\n>     \"--depth=inf\";\n> \n>  2. Making \"git fetch\" and \"git clone\" die on \"--depth=0\" or\n>     \"--depth=-4\";\n> \n>  3 Updating \"upload-pack\" to count correctly.\n> \n> I'll refrain from saying \"Any takers?\" for now.\n\nSorry for answering with delay, I am just contributing to git in my\nspare time.\nSo if I understood Duy correctly, he is going to solve 1. and 3 by his\npatches.\nI'll try to come up with a solution for 2. within the next days.\n"},{"id":"206484","messageId":"1357875005-21956-1-git-send-email-pclouds@gmail.com","threadId":"32554","inReplyTo":"7vy5g383sy.fsf_-_@alter.siamese.dyndns.org","subject":"[PATCH 1/2] fetch, upload-pack: add --no-shallow for infinite depth","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-11T03:30:04Z","receivedAt":"2013-01-11T03:30:04Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The user can do --depth=2147483647 (*) for infinite depth now. But\nit's hard to remember. Any other numbers larger than the longest\ncommit chain in the repository would also do, but some guessing may\nbe involved. Make easy-to-remember --no-shallow an alias for\n--depth=2147483647.\n\nMake upload-pack recognize this special number as infinite depth. The\neffect is essentially the same as before, except that upload-pack is\nmore efficient because it does not have to traverse to the bottom\nany more. The chance of a user actually wanting exactly 2147483647\ncommits depth, not infinite, on a repository with a history that long,\nis probably too small to consider.\n\n(*) This is the largest positive number a 32-bit signed integer can\n    contain. JGit and older C Git store depth as \"int\" so both are OK\n    with this number. Dulwich does not support shallow clone.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/fetch-options.txt     |  4 ++++\n Documentation/git-fetch-pack.txt    |  2 ++\n Documentation/technical/shallow.txt |  3 +++\n builtin/fetch.c                     | 15 ++++++++++++++-\n commit.h                            |  3 +++\n t/t5500-fetch-pack.sh               | 16 ++++++++++++++++\n upload-pack.c                       | 13 ++++++++++---\n 7 files changed, 52 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt\nindex 6e98bdf..012d1b2 100644\n--- a/Documentation/fetch-options.txt\n+++ b/Documentation/fetch-options.txt\n@@ -13,6 +13,10 @@\n \tto the specified number of commits from the tip of each remote\n \tbranch history. Tags for the deepened commits are not fetched.\n \n+--no-shallow::\n+\tDeepen to the roots of the repository's history (i.e. the\n+\tresult repository is no longer shallow).\n+\n ifndef::git-pull[]\n --dry-run::\n \tShow what would be done, without making any changes.\ndiff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt\nindex 8c75120..b81e90d 100644\n--- a/Documentation/git-fetch-pack.txt\n+++ b/Documentation/git-fetch-pack.txt\n@@ -84,6 +84,8 @@ be in a separate packet, and the list must end with a flush packet.\n \n --depth=<n>::\n \tLimit fetching to ancestor-chains not longer than n.\n+\t'git-upload-pack' treats the special depth 2147483647 as\n+\tinfinite even if there is an ancestor-chain that long.\n \n --no-progress::\n \tDo not show the progress.\ndiff --git a/Documentation/technical/shallow.txt b/Documentation/technical/shallow.txt\nindex 0502a54..ea2f69f 100644\n--- a/Documentation/technical/shallow.txt\n+++ b/Documentation/technical/shallow.txt\n@@ -53,3 +53,6 @@ It also writes an appropriate $GIT_DIR/shallow.\n You can deepen a shallow repository with \"git-fetch --depth 20\n repo branch\", which will fetch branch from repo, but stop at depth\n 20, updating $GIT_DIR/shallow.\n+\n+The special depth 2147483647 (or 0x7fffffff, the largest positive\n+number a signed 32-bit integer can contain) means infinite depth.\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex 4b5a898..bf7b5c5 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -32,7 +32,7 @@ enum {\n \n static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;\n static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;\n-static int tags = TAGS_DEFAULT;\n+static int tags = TAGS_DEFAULT, no_shallow;\n static const char *depth;\n static const char *upload_pack;\n static struct strbuf default_rla = STRBUF_INIT;\n@@ -82,6 +82,9 @@ static struct option builtin_fetch_options[] = {\n \tOPT_BOOL(0, \"progress\", &progress, N_(\"force progress reporting\")),\n \tOPT_STRING(0, \"depth\", &depth, N_(\"depth\"),\n \t\t   N_(\"deepen history of shallow clone\")),\n+\t{ OPTION_SET_INT, 0, \"no-shallow\", &no_shallow, NULL,\n+\t\t   N_(\"deepen history to the bottom\"),\n+\t\t   PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },\n \t{ OPTION_STRING, 0, \"submodule-prefix\", &submodule_prefix, N_(\"dir\"),\n \t\t   N_(\"prepend this to submodule path output\"), PARSE_OPT_HIDDEN },\n \t{ OPTION_STRING, 0, \"recurse-submodules-default\",\n@@ -970,6 +973,16 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix,\n \t\t\t     builtin_fetch_options, builtin_fetch_usage, 0);\n \n+\tif (no_shallow) {\n+\t\tif (depth)\n+\t\t\tdie(_(\"--depth and --no-shallow cannot be used together\"));\n+\t\telse {\n+\t\t\tstatic char inf_depth[12];\n+\t\t\tsprintf(inf_depth, \"%d\", INFINITE_DEPTH);\n+\t\t\tdepth = inf_depth;\n+\t\t}\n+\t}\n+\n \tif (recurse_submodules != RECURSE_SUBMODULES_OFF) {\n \t\tif (recurse_submodules_default) {\n \t\t\tint arg = parse_fetch_recurse_submodules_arg(\"--recurse-submodules-default\", recurse_submodules_default);\ndiff --git a/commit.h b/commit.h\nindex 0f469e5..fbde106 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -162,6 +162,9 @@ extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *r\n extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);\n extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);\n \n+/* largest postive number a signed 32-bit integer can contain */\n+#define INFINITE_DEPTH 0x7fffffff\n+\n extern int register_shallow(const unsigned char *sha1);\n extern int unregister_shallow(const unsigned char *sha1);\n extern int for_each_commit_graft(each_commit_graft_fn, void *);\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 6322e8a..6a6e672 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -264,6 +264,22 @@ test_expect_success 'clone shallow object count' '\n \tgrep \"^count: 52\" count.shallow\n '\n \n+test_expect_success 'fetch --depth --no-shallow' '\n+\t(\n+\t\tcd shallow &&\n+\t\ttest_must_fail git fetch --depth=1 --no-shallow\n+\t)\n+'\n+\n+test_expect_success 'infinite deepening (full repo)' '\n+\t(\n+\t\tcd shallow &&\n+\t\tgit fetch --no-shallow &&\n+\t\tgit fsck --full &&\n+\t\t! test -f .git/shallow\n+\t)\n+'\n+\n test_expect_success 'clone shallow without --no-single-branch' '\n \tgit clone --depth 1 \"file://$(pwd)/.\" shallow2\n '\ndiff --git a/upload-pack.c b/upload-pack.c\nindex 6142421..88f0029 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -670,10 +670,17 @@ static void receive_needs(void)\n \tif (depth == 0 && shallows.nr == 0)\n \t\treturn;\n \tif (depth > 0) {\n-\t\tstruct commit_list *result, *backup;\n+\t\tstruct commit_list *result = NULL, *backup = NULL;\n \t\tint i;\n-\t\tbackup = result = get_shallow_commits(&want_obj, depth,\n-\t\t\tSHALLOW, NOT_SHALLOW);\n+\t\tif (depth == INFINITE_DEPTH)\n+\t\t\tfor (i = 0; i < shallows.nr; i++) {\n+\t\t\t\tstruct object *object = shallows.objects[i].item;\n+\t\t\t\tobject->flags |= NOT_SHALLOW;\n+\t\t\t}\n+\t\telse\n+\t\t\tbackup = result =\n+\t\t\t\tget_shallow_commits(&want_obj, depth,\n+\t\t\t\t\t\t    SHALLOW, NOT_SHALLOW);\n \t\twhile (result) {\n \t\t\tstruct object *object = &result->item->object;\n \t\t\tif (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206485","messageId":"1357875005-21956-2-git-send-email-pclouds@gmail.com","threadId":"32554","inReplyTo":"1357875005-21956-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/2] upload-pack: fix off-by-one depth calculation in shallow clone","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-11T03:30:05Z","receivedAt":"2013-01-11T03:30:05Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"get_shallow_commits() is used to determine the cut points at a given\ndepth (i.e. the number of commits in a chain that the user likes to\nget). However we count current depth up to the commit \"commit\" but we\ndo the cutting at its parents (i.e. current depth + 1). This makes\nupload-pack always return one commit more than requested. This patch\nfixes it.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n shallow.c             |  8 +++++++-\n t/t5500-fetch-pack.sh | 25 +++++++++++++++++++------\n 2 files changed, 26 insertions(+), 7 deletions(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex a0363de..6be915f 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -72,8 +72,14 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,\n \t\t}\n \t\tif (parse_commit(commit))\n \t\t\tdie(\"invalid commit\");\n-\t\tcommit->object.flags |= not_shallow_flag;\n \t\tcur_depth++;\n+\t\tif (cur_depth >= depth) {\n+\t\t\tcommit_list_insert(commit, &result);\n+\t\t\tcommit->object.flags |= shallow_flag;\n+\t\t\tcommit = NULL;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tcommit->object.flags |= not_shallow_flag;\n \t\tfor (p = commit->parents, commit = NULL; p; p = p->next) {\n \t\t\tif (!p->item->util) {\n \t\t\t\tint *pointer = xmalloc(sizeof(int));\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 6a6e672..58d3bdf 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -130,16 +130,25 @@ test_expect_success 'single given branch clone' '\n \ttest_must_fail git --git-dir=branch-a/.git rev-parse origin/B\n '\n \n+test_expect_success 'clone shallow depth 1' '\n+\tgit clone --no-single-branch --depth 1 \"file://$(pwd)/.\" shallow0\n+\ttest \"`git --git-dir=shallow0/.git rev-list --count HEAD`\" = 1\n+'\n+\n test_expect_success 'clone shallow' '\n \tgit clone --no-single-branch --depth 2 \"file://$(pwd)/.\" shallow\n '\n \n+test_expect_success 'clone shallow depth count' '\n+\ttest \"`git --git-dir=shallow/.git rev-list --count HEAD`\" = 2\n+'\n+\n test_expect_success 'clone shallow object count' '\n \t(\n \t\tcd shallow &&\n \t\tgit count-objects -v\n \t) > count.shallow &&\n-\tgrep \"^in-pack: 18\" count.shallow\n+\tgrep \"^in-pack: 12\" count.shallow\n '\n \n test_expect_success 'clone shallow object count (part 2)' '\n@@ -256,12 +265,16 @@ test_expect_success 'additional simple shallow deepenings' '\n \t)\n '\n \n+test_expect_success 'clone shallow depth count' '\n+\ttest \"`git --git-dir=shallow/.git rev-list --count HEAD`\" = 11\n+'\n+\n test_expect_success 'clone shallow object count' '\n \t(\n \t\tcd shallow &&\n \t\tgit count-objects -v\n \t) > count.shallow &&\n-\tgrep \"^count: 52\" count.shallow\n+\tgrep \"^count: 55\" count.shallow\n '\n \n test_expect_success 'fetch --depth --no-shallow' '\n@@ -289,7 +302,7 @@ test_expect_success 'clone shallow object count' '\n \t\tcd shallow2 &&\n \t\tgit count-objects -v\n \t) > count.shallow2 &&\n-\tgrep \"^in-pack: 6\" count.shallow2\n+\tgrep \"^in-pack: 3\" count.shallow2\n '\n \n test_expect_success 'clone shallow with --branch' '\n@@ -297,7 +310,7 @@ test_expect_success 'clone shallow with --branch' '\n '\n \n test_expect_success 'clone shallow object count' '\n-\techo \"in-pack: 6\" > count3.expected &&\n+\techo \"in-pack: 3\" > count3.expected &&\n \tGIT_DIR=shallow3/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count3.actual &&\n \ttest_cmp count3.expected count3.actual\n@@ -326,7 +339,7 @@ EOF\n \tGIT_DIR=shallow6/.git git tag -l >taglist.actual &&\n \ttest_cmp taglist.expected taglist.actual &&\n \n-\techo \"in-pack: 7\" > count6.expected &&\n+\techo \"in-pack: 4\" > count6.expected &&\n \tGIT_DIR=shallow6/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count6.actual &&\n \ttest_cmp count6.expected count6.actual\n@@ -341,7 +354,7 @@ EOF\n \tGIT_DIR=shallow7/.git git tag -l >taglist.actual &&\n \ttest_cmp taglist.expected taglist.actual &&\n \n-\techo \"in-pack: 7\" > count7.expected &&\n+\techo \"in-pack: 4\" > count7.expected &&\n \tGIT_DIR=shallow7/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count7.actual &&\n \ttest_cmp count7.expected count7.actual\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206488","messageId":"7vtxqocr0u.fsf@alter.siamese.dyndns.org","threadId":"32554","inReplyTo":"1357875005-21956-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/2] fetch, upload-pack: add --no-shallow for infinite depth","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-11T03:55:29Z","receivedAt":"2013-01-11T03:55:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> The user can do --depth=2147483647 (*) for infinite depth now. But\n> it's hard to remember. Any other numbers larger than the longest\n> commit chain in the repository would also do, but some guessing may\n> be involved. Make easy-to-remember --no-shallow an alias for\n> --depth=2147483647.\n\nI think \"no shallow\" makes sense in a much more important way than\n\"infinite depth\", and this patch is a good idea for a reason\nentirely different from the justification your log message makes ;-)\n\nWe explain that \"clone --depth=<number>\" is a way to end up with a\npartial repository that contains only the recent history, and while\nthis may give users a smaller repository, in return the result will\nbe a \"shallow repository\" with certain limitations (i.e. fetching or\ncloning from such a repository will be refused).\n\nWe also explain that the reason to use --depth=<number> is to grab\nsome history behind what you originally acquired into your \"shallow\nrepository\" so that you have deeper history than your original\n\"shallow repository\".\n\nA reader who does not know how this shallowness is implemented\ncannot be blamed if she thinks the shallowness is a permanent\nattribute of a repository, and once a repository is tainted by\nshallowness, it cannot be wiped away by deepening it, because\nnowhere in the documentation we say the \"shallowness\" will go away\nonce you grabbed enough number of older commits with it.\n\nCalling the option \"--no-shallow\" (or even better, \"--unshallow\",\nmeaning \"make it a repository that is no longer shallow\") makes it\ncrystal clear that the option is about wiping away the shallowness.\nOf course, the result has to contain an untruncted history, but that\nis a mere side effect and an implementation detail from the end\nuser's point of view.\n\n> Make upload-pack recognize this special number as infinite depth. The\n> effect is essentially the same as before, except that upload-pack is\n> more efficient because it does not have to traverse to the bottom\n> any more. The chance of a user actually wanting exactly 2147483647\n> commits depth, not infinite, on a repository with a history that long,\n> is probably too small to consider.\n>\n> (*) This is the largest positive number a 32-bit signed integer can\n>     contain. JGit and older C Git store depth as \"int\" so both are OK\n>     with this number. Dulwich does not support shallow clone.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  Documentation/fetch-options.txt     |  4 ++++\n>  Documentation/git-fetch-pack.txt    |  2 ++\n>  Documentation/technical/shallow.txt |  3 +++\n>  builtin/fetch.c                     | 15 ++++++++++++++-\n>  commit.h                            |  3 +++\n>  t/t5500-fetch-pack.sh               | 16 ++++++++++++++++\n>  upload-pack.c                       | 13 ++++++++++---\n>  7 files changed, 52 insertions(+), 4 deletions(-)\n>\n> diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt\n> index 6e98bdf..012d1b2 100644\n> --- a/Documentation/fetch-options.txt\n> +++ b/Documentation/fetch-options.txt\n> @@ -13,6 +13,10 @@\n>  \tto the specified number of commits from the tip of each remote\n>  \tbranch history. Tags for the deepened commits are not fetched.\n>  \n> +--no-shallow::\n> +\tDeepen to the roots of the repository's history (i.e. the\n> +\tresult repository is no longer shallow).\n> +\n\nMentioning both is a good thing, but I think \"no longer shallow\" is\nmore important aspect of this operation than \"deepen to the roots\".\n\n> diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\n> index 6322e8a..6a6e672 100755\n> --- a/t/t5500-fetch-pack.sh\n> +++ b/t/t5500-fetch-pack.sh\n> @@ -264,6 +264,22 @@ test_expect_success 'clone shallow object count' '\n>  \tgrep \"^count: 52\" count.shallow\n>  '\n>  \n> +test_expect_success 'fetch --depth --no-shallow' '\n> +\t(\n> +\t\tcd shallow &&\n> +\t\ttest_must_fail git fetch --depth=1 --no-shallow\n> +\t)\n> +'\n> +\n> +test_expect_success 'infinite deepening (full repo)' '\n> +\t(\n> +\t\tcd shallow &&\n> +\t\tgit fetch --no-shallow &&\n> +\t\tgit fsck --full &&\n> +\t\t! test -f .git/shallow\n\nThis looks as if fsck is what removes .git/shallow but I do not\nthink that is what is being tested...\n\n> diff --git a/upload-pack.c b/upload-pack.c\n> index 6142421..88f0029 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -670,10 +670,17 @@ static void receive_needs(void)\n>  \tif (depth == 0 && shallows.nr == 0)\n>  \t\treturn;\n>  \tif (depth > 0) {\n> -\t\tstruct commit_list *result, *backup;\n> +\t\tstruct commit_list *result = NULL, *backup = NULL;\n>  \t\tint i;\n> -\t\tbackup = result = get_shallow_commits(&want_obj, depth,\n> -\t\t\tSHALLOW, NOT_SHALLOW);\n> +\t\tif (depth == INFINITE_DEPTH)\n> +\t\t\tfor (i = 0; i < shallows.nr; i++) {\n> +\t\t\t\tstruct object *object = shallows.objects[i].item;\n> +\t\t\t\tobject->flags |= NOT_SHALLOW;\n> +\t\t\t}\n> +\t\telse\n> +\t\t\tbackup = result =\n> +\t\t\t\tget_shallow_commits(&want_obj, depth,\n> +\t\t\t\t\t\t    SHALLOW, NOT_SHALLOW);\n\nNice.  Thanks.\n"},{"id":"206490","messageId":"7vpq1ccpl8.fsf@alter.siamese.dyndns.org","threadId":"32554","inReplyTo":"1357875005-21956-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 2/2] upload-pack: fix off-by-one depth calculation in shallow clone","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-11T04:26:27Z","receivedAt":"2013-01-11T04:26:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> get_shallow_commits() is used to determine the cut points at a given\n> depth (i.e. the number of commits in a chain that the user likes to\n> get). However we count current depth up to the commit \"commit\" but we\n> do the cutting at its parents (i.e. current depth + 1). This makes\n> upload-pack always return one commit more than requested. This patch\n> fixes it.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  shallow.c             |  8 +++++++-\n>  t/t5500-fetch-pack.sh | 25 +++++++++++++++++++------\n>  2 files changed, 26 insertions(+), 7 deletions(-)\n>\n> diff --git a/shallow.c b/shallow.c\n> index a0363de..6be915f 100644\n> --- a/shallow.c\n> +++ b/shallow.c\n> @@ -72,8 +72,14 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,\n>  \t\t}\n>  \t\tif (parse_commit(commit))\n>  \t\t\tdie(\"invalid commit\");\n> -\t\tcommit->object.flags |= not_shallow_flag;\n>  \t\tcur_depth++;\n> +\t\tif (cur_depth >= depth) {\n> +\t\t\tcommit_list_insert(commit, &result);\n> +\t\t\tcommit->object.flags |= shallow_flag;\n> +\t\t\tcommit = NULL;\n> +\t\t\tcontinue;\n> +\t\t}\n> +\t\tcommit->object.flags |= not_shallow_flag;\n>  \t\tfor (p = commit->parents, commit = NULL; p; p = p->next) {\n>  \t\t\tif (!p->item->util) {\n>  \t\t\t\tint *pointer = xmalloc(sizeof(int));\n\nNice.  No protocol extensions, you update the server side, and an\nold client starts getting the right number of generations.\n\n> diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\n> index 6a6e672..58d3bdf 100755\n> --- a/t/t5500-fetch-pack.sh\n> +++ b/t/t5500-fetch-pack.sh\n> @@ -130,16 +130,25 @@ test_expect_success 'single given branch clone' '\n>  \ttest_must_fail git --git-dir=branch-a/.git rev-parse origin/B\n>  '\n>  \n> +test_expect_success 'clone shallow depth 1' '\n> +\tgit clone --no-single-branch --depth 1 \"file://$(pwd)/.\" shallow0\n> +\ttest \"`git --git-dir=shallow0/.git rev-list --count HEAD`\" = 1\n> +'\n\nNo &&-chaining?\n\nThanks.\n"},{"id":"206502","messageId":"1357895148-30909-1-git-send-email-pclouds@gmail.com","threadId":"32554","inReplyTo":"1357875005-21956-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v2 1/3] fetch: add --unshallow for turning shallow repo into complete one","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-11T09:05:46Z","receivedAt":"2013-01-11T09:05:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The user can do --depth=2147483647 (*) for restoring complete repo\nnow. But it's hard to remember. Any other numbers larger than the\nlongest commit chain in the repository would also do, but some\nguessing may be involved. Make easy-to-remember --unshallow an alias\nfor --depth=2147483647.\n\nMake upload-pack recognize this special number as infinite depth. The\neffect is essentially the same as before, except that upload-pack is\nmore efficient because it does not have to traverse to the bottom\nanymore.\n\nThe chance of a user actually wanting exactly 2147483647 commits\ndepth, not infinite, on a repository with a history that long, is\nprobably too small to consider. The client can learn to add or\nsubtract one commit to avoid the special treatment when that actually\nhappens.\n\n(*) This is the largest positive number a 32-bit signed integer can\n    contain. JGit and older C Git store depth as \"int\" so both are OK\n    with this number. Dulwich does not support shallow clone.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n On Fri, Jan 11, 2013 at 10:55 AM, Junio C Hamano <gitster@pobox.com> wrote:\n > I think \"no shallow\" makes sense in a much more important way than\n > \"infinite depth\", and this patch is a good idea for a reason\n > entirely different from the justification your log message makes ;-)\n > [snip]\n > Calling the option \"--no-shallow\" (or even better, \"--unshallow\",\n > meaning \"make it a repository that is no longer shallow\") makes it\n > crystal clear that the option is about wiping away the shallowness.\n > Of course, the result has to contain an untruncted history, but that\n > is a mere side effect and an implementation detail from the end\n > user's point of view.\n\n Very well said. --unshallow it is.\n\n Documentation/fetch-options.txt     |  4 ++++\n Documentation/git-fetch-pack.txt    |  2 ++\n Documentation/technical/shallow.txt |  3 +++\n builtin/fetch.c                     | 17 ++++++++++++++++-\n commit.h                            |  3 +++\n t/t5500-fetch-pack.sh               | 20 ++++++++++++++++++++\n upload-pack.c                       | 13 ++++++++++---\n 7 files changed, 58 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt\nindex 6e98bdf..8a0449c 100644\n--- a/Documentation/fetch-options.txt\n+++ b/Documentation/fetch-options.txt\n@@ -13,6 +13,10 @@\n \tto the specified number of commits from the tip of each remote\n \tbranch history. Tags for the deepened commits are not fetched.\n \n+--unshallow::\n+\tConvert a shallow repository to a complete one, removing all\n+\tthe limitations imposed by shallow repositories.\n+\n ifndef::git-pull[]\n --dry-run::\n \tShow what would be done, without making any changes.\ndiff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt\nindex 8c75120..b81e90d 100644\n--- a/Documentation/git-fetch-pack.txt\n+++ b/Documentation/git-fetch-pack.txt\n@@ -84,6 +84,8 @@ be in a separate packet, and the list must end with a flush packet.\n \n --depth=<n>::\n \tLimit fetching to ancestor-chains not longer than n.\n+\t'git-upload-pack' treats the special depth 2147483647 as\n+\tinfinite even if there is an ancestor-chain that long.\n \n --no-progress::\n \tDo not show the progress.\ndiff --git a/Documentation/technical/shallow.txt b/Documentation/technical/shallow.txt\nindex 0502a54..ea2f69f 100644\n--- a/Documentation/technical/shallow.txt\n+++ b/Documentation/technical/shallow.txt\n@@ -53,3 +53,6 @@ It also writes an appropriate $GIT_DIR/shallow.\n You can deepen a shallow repository with \"git-fetch --depth 20\n repo branch\", which will fetch branch from repo, but stop at depth\n 20, updating $GIT_DIR/shallow.\n+\n+The special depth 2147483647 (or 0x7fffffff, the largest positive\n+number a signed 32-bit integer can contain) means infinite depth.\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex 4b5a898..2b15ced 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -32,7 +32,7 @@ enum {\n \n static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;\n static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;\n-static int tags = TAGS_DEFAULT;\n+static int tags = TAGS_DEFAULT, unshallow;\n static const char *depth;\n static const char *upload_pack;\n static struct strbuf default_rla = STRBUF_INIT;\n@@ -82,6 +82,9 @@ static struct option builtin_fetch_options[] = {\n \tOPT_BOOL(0, \"progress\", &progress, N_(\"force progress reporting\")),\n \tOPT_STRING(0, \"depth\", &depth, N_(\"depth\"),\n \t\t   N_(\"deepen history of shallow clone\")),\n+\t{ OPTION_SET_INT, 0, \"unshallow\", &unshallow, NULL,\n+\t\t   N_(\"convert to a complete repository\"),\n+\t\t   PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },\n \t{ OPTION_STRING, 0, \"submodule-prefix\", &submodule_prefix, N_(\"dir\"),\n \t\t   N_(\"prepend this to submodule path output\"), PARSE_OPT_HIDDEN },\n \t{ OPTION_STRING, 0, \"recurse-submodules-default\",\n@@ -970,6 +973,18 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix,\n \t\t\t     builtin_fetch_options, builtin_fetch_usage, 0);\n \n+\tif (unshallow) {\n+\t\tif (depth)\n+\t\t\tdie(_(\"--depth and --unshallow cannot be used together\"));\n+\t\telse if (!is_repository_shallow())\n+\t\t\tdie(_(\"--unshallow on a complete repository does not make sense\"));\n+\t\telse {\n+\t\t\tstatic char inf_depth[12];\n+\t\t\tsprintf(inf_depth, \"%d\", INFINITE_DEPTH);\n+\t\t\tdepth = inf_depth;\n+\t\t}\n+\t}\n+\n \tif (recurse_submodules != RECURSE_SUBMODULES_OFF) {\n \t\tif (recurse_submodules_default) {\n \t\t\tint arg = parse_fetch_recurse_submodules_arg(\"--recurse-submodules-default\", recurse_submodules_default);\ndiff --git a/commit.h b/commit.h\nindex 0f469e5..fbde106 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -162,6 +162,9 @@ extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *r\n extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);\n extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);\n \n+/* largest postive number a signed 32-bit integer can contain */\n+#define INFINITE_DEPTH 0x7fffffff\n+\n extern int register_shallow(const unsigned char *sha1);\n extern int unregister_shallow(const unsigned char *sha1);\n extern int for_each_commit_graft(each_commit_graft_fn, void *);\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 6322e8a..426027e 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -264,6 +264,26 @@ test_expect_success 'clone shallow object count' '\n \tgrep \"^count: 52\" count.shallow\n '\n \n+test_expect_success 'fetch --no-shallow on full repo' '\n+\ttest_must_fail git fetch --noshallow\n+'\n+\n+test_expect_success 'fetch --depth --no-shallow' '\n+\t(\n+\t\tcd shallow &&\n+\t\ttest_must_fail git fetch --depth=1 --noshallow\n+\t)\n+'\n+\n+test_expect_success 'turn shallow to complete repository' '\n+\t(\n+\t\tcd shallow &&\n+\t\tgit fetch --unshallow &&\n+\t\t! test -f .git/shallow &&\n+\t\tgit fsck --full\n+\t)\n+'\n+\n test_expect_success 'clone shallow without --no-single-branch' '\n \tgit clone --depth 1 \"file://$(pwd)/.\" shallow2\n '\ndiff --git a/upload-pack.c b/upload-pack.c\nindex 6142421..88f0029 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -670,10 +670,17 @@ static void receive_needs(void)\n \tif (depth == 0 && shallows.nr == 0)\n \t\treturn;\n \tif (depth > 0) {\n-\t\tstruct commit_list *result, *backup;\n+\t\tstruct commit_list *result = NULL, *backup = NULL;\n \t\tint i;\n-\t\tbackup = result = get_shallow_commits(&want_obj, depth,\n-\t\t\tSHALLOW, NOT_SHALLOW);\n+\t\tif (depth == INFINITE_DEPTH)\n+\t\t\tfor (i = 0; i < shallows.nr; i++) {\n+\t\t\t\tstruct object *object = shallows.objects[i].item;\n+\t\t\t\tobject->flags |= NOT_SHALLOW;\n+\t\t\t}\n+\t\telse\n+\t\t\tbackup = result =\n+\t\t\t\tget_shallow_commits(&want_obj, depth,\n+\t\t\t\t\t\t    SHALLOW, NOT_SHALLOW);\n \t\twhile (result) {\n \t\t\tstruct object *object = &result->item->object;\n \t\t\tif (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206501","messageId":"1357895148-30909-2-git-send-email-pclouds@gmail.com","threadId":"32554","inReplyTo":"1357895148-30909-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v2 2/3] upload-pack: fix off-by-one depth calculation in shallow clone","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-11T09:05:47Z","receivedAt":"2013-01-11T09:05:47Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"get_shallow_commits() is used to determine the cut points at a given\ndepth (i.e. the number of commits in a chain that the user likes to\nget). However we count current depth up to the commit \"commit\" but we\ndo the cutting at its parents (i.e. current depth + 1). This makes\nupload-pack always return one commit more than requested. This patch\nfixes it.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Fixed the && command chain in t5500.\n\n shallow.c             |  8 +++++++-\n t/t5500-fetch-pack.sh | 25 +++++++++++++++++++------\n 2 files changed, 26 insertions(+), 7 deletions(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex a0363de..6be915f 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -72,8 +72,14 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,\n \t\t}\n \t\tif (parse_commit(commit))\n \t\t\tdie(\"invalid commit\");\n-\t\tcommit->object.flags |= not_shallow_flag;\n \t\tcur_depth++;\n+\t\tif (cur_depth >= depth) {\n+\t\t\tcommit_list_insert(commit, &result);\n+\t\t\tcommit->object.flags |= shallow_flag;\n+\t\t\tcommit = NULL;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tcommit->object.flags |= not_shallow_flag;\n \t\tfor (p = commit->parents, commit = NULL; p; p = p->next) {\n \t\t\tif (!p->item->util) {\n \t\t\t\tint *pointer = xmalloc(sizeof(int));\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 426027e..354d32c 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -130,16 +130,25 @@ test_expect_success 'single given branch clone' '\n \ttest_must_fail git --git-dir=branch-a/.git rev-parse origin/B\n '\n \n+test_expect_success 'clone shallow depth 1' '\n+\tgit clone --no-single-branch --depth 1 \"file://$(pwd)/.\" shallow0 &&\n+\ttest \"`git --git-dir=shallow0/.git rev-list --count HEAD`\" = 1\n+'\n+\n test_expect_success 'clone shallow' '\n \tgit clone --no-single-branch --depth 2 \"file://$(pwd)/.\" shallow\n '\n \n+test_expect_success 'clone shallow depth count' '\n+\ttest \"`git --git-dir=shallow/.git rev-list --count HEAD`\" = 2\n+'\n+\n test_expect_success 'clone shallow object count' '\n \t(\n \t\tcd shallow &&\n \t\tgit count-objects -v\n \t) > count.shallow &&\n-\tgrep \"^in-pack: 18\" count.shallow\n+\tgrep \"^in-pack: 12\" count.shallow\n '\n \n test_expect_success 'clone shallow object count (part 2)' '\n@@ -256,12 +265,16 @@ test_expect_success 'additional simple shallow deepenings' '\n \t)\n '\n \n+test_expect_success 'clone shallow depth count' '\n+\ttest \"`git --git-dir=shallow/.git rev-list --count HEAD`\" = 11\n+'\n+\n test_expect_success 'clone shallow object count' '\n \t(\n \t\tcd shallow &&\n \t\tgit count-objects -v\n \t) > count.shallow &&\n-\tgrep \"^count: 52\" count.shallow\n+\tgrep \"^count: 55\" count.shallow\n '\n \n test_expect_success 'fetch --no-shallow on full repo' '\n@@ -293,7 +306,7 @@ test_expect_success 'clone shallow object count' '\n \t\tcd shallow2 &&\n \t\tgit count-objects -v\n \t) > count.shallow2 &&\n-\tgrep \"^in-pack: 6\" count.shallow2\n+\tgrep \"^in-pack: 3\" count.shallow2\n '\n \n test_expect_success 'clone shallow with --branch' '\n@@ -301,7 +314,7 @@ test_expect_success 'clone shallow with --branch' '\n '\n \n test_expect_success 'clone shallow object count' '\n-\techo \"in-pack: 6\" > count3.expected &&\n+\techo \"in-pack: 3\" > count3.expected &&\n \tGIT_DIR=shallow3/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count3.actual &&\n \ttest_cmp count3.expected count3.actual\n@@ -330,7 +343,7 @@ EOF\n \tGIT_DIR=shallow6/.git git tag -l >taglist.actual &&\n \ttest_cmp taglist.expected taglist.actual &&\n \n-\techo \"in-pack: 7\" > count6.expected &&\n+\techo \"in-pack: 4\" > count6.expected &&\n \tGIT_DIR=shallow6/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count6.actual &&\n \ttest_cmp count6.expected count6.actual\n@@ -345,7 +358,7 @@ EOF\n \tGIT_DIR=shallow7/.git git tag -l >taglist.actual &&\n \ttest_cmp taglist.expected taglist.actual &&\n \n-\techo \"in-pack: 7\" > count7.expected &&\n+\techo \"in-pack: 4\" > count7.expected &&\n \tGIT_DIR=shallow7/.git git count-objects -v |\n \t\tgrep \"^in-pack\" > count7.actual &&\n \ttest_cmp count7.expected count7.actual\n-- \n1.8.0.rc2.23.g1fb49df\n"},{"id":"206503","messageId":"1357895148-30909-3-git-send-email-pclouds@gmail.com","threadId":"32554","inReplyTo":"1357895148-30909-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v2 3/3] fetch: elaborate --depth action","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-01-11T09:05:48Z","receivedAt":"2013-01-11T09:05:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"--depth is explained as deepen, but the way it's applied, it can\nshorten the history as well. Keen users may have noticed the\nimplication by the phrase \"the specified number of commits from the\ntip of each remote branch\". Put \"shorten\" in the description to make\nit clearer.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/fetch-options.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt\nindex 8a0449c..fb92b02 100644\n--- a/Documentation/fetch-options.txt\n+++ b/Documentation/fetch-options.txt\n@@ -8,7 +8,7 @@\n \toption old data in `.git/FETCH_HEAD` will be overwritten.\n \n --depth=<depth>::\n-\tDeepen the history of a 'shallow' repository created by\n+\tDeepen or shorten the history of a 'shallow' repository created by\n \t`git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])\n \tto the specified number of commits from the tip of each remote\n \tbranch history. Tags for the deepened commits are not fetched.\n-- \n1.8.0.rc2.23.g1fb49df\n"}]}