{"thread":{"id":"65157","subject":"[PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","startedAt":"2026-03-06T22:14:41Z","lastAt":"2026-03-09T09:36:26Z","messageCount":5,"participants":["Mike Banon","brian m. carlson","Richard Kerry"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"538122","messageId":"CAK7947msLiGgrYTcg1m3ew+bP0F+VNbRaTy=ZW7zkkHh69bN0Q@mail.gmail.com","threadId":"65157","inReplyTo":null,"subject":"[PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","fromName":"Mike Banon","fromEmail":"mikebdp2@gmail.com","sentAt":"2026-03-06T22:14:28Z","receivedAt":"2026-03-06T22:14:41Z","isPatch":true,"sender":{"key":"mikebdp2@gmail.com","avatar":null},"body":"When cloning large repositories from a website with multiple Git servers,\nthe client may be directed to a \"turtle-slow\" server, causing the transfer\nto proceed at an unusably slow speed. This can lead to stalled downloads,\nparticularly problematic for automated scripts that clone many\nrepositories. This option makes Git abort the clone if the download rate\nfalls below 128 KiB/s while receiving objects, typically catching slow\nservers early in the transfer, enabling scripts to retry the clone until\nthey obtain a fast connection.\n\nSigned-off-by: Mike Banon <mikebdp2@gmail.com>\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex fba3c9c508..a9ed2c193d 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -94,6 +94,13 @@ static int recurse_submodules_cb(const struct option *opt,\n     return 0;\n }\n\n+static int set_turtle_speed_env(const struct option *opt UNUSED,\n+                const char *arg UNUSED, int unset UNUSED)\n+{\n+    setenv(NO_TURTLE_SPEED_ENVIRONMENT, \"1\", 1);\n+    return 0;\n+}\n+\n static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)\n {\n     static const char *suffix[] = { \"/.git\", \"\", \".git/.git\", \".git\" };\n@@ -946,6 +953,16 @@ int cmd_clone(int argc,\n             .callback = recurse_submodules_cb,\n             .defval = (intptr_t)\".\",\n         },\n+        {\n+            .type = OPTION_CALLBACK,\n+            .long_name = \"no-turtle-speed\",\n+            .value = NULL,\n+            .argh = NULL,\n+            .help = N_(\"abort clone if speed drops below 128 KiB/s\"),\n+            .flags = PARSE_OPT_NOARG,\n+            .callback = set_turtle_speed_env,\n+            .defval = 0,\n+        },\n         OPT_ALIAS(0, \"recursive\", \"recurse-submodules\"),\n         OPT_INTEGER('j', \"jobs\", &max_jobs,\n                 N_(\"number of submodules cloned in parallel\")),\ndiff --git a/environment.h b/environment.h\nindex 123a71cdc8..cb316cf321 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -24,6 +24,7 @@\n #define NO_REPLACE_OBJECTS_ENVIRONMENT \"GIT_NO_REPLACE_OBJECTS\"\n #define GIT_REPLACE_REF_BASE_ENVIRONMENT \"GIT_REPLACE_REF_BASE\"\n #define NO_LAZY_FETCH_ENVIRONMENT \"GIT_NO_LAZY_FETCH\"\n+#define NO_TURTLE_SPEED_ENVIRONMENT \"GIT_NO_TURTLE_SPEED\"\n #define GITATTRIBUTES_FILE \".gitattributes\"\n #define INFOATTRIBUTES_FILE \"info/attributes\"\n #define ATTRIBUTE_MACRO_PREFIX \"[attr]\"\ndiff --git a/git.c b/git.c\nindex 744cb6527e..d0c4909fef 100644\n--- a/git.c\n+++ b/git.c\n@@ -40,9 +40,9 @@ const char git_usage_string[] =\n     N_(\"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\\n\"\n        \"           [--exec-path[=<path>]] [--html-path] [--man-path]\n[--info-path]\\n\"\n        \"           [-p | --paginate | -P | --no-pager]\n[--no-replace-objects] [--no-lazy-fetch]\\n\"\n-       \"           [--no-optional-locks] [--no-advice] [--bare]\n[--git-dir=<path>]\\n\"\n-       \"           [--work-tree=<path>] [--namespace=<name>]\n[--config-env=<name>=<envvar>]\\n\"\n-       \"           <command> [<args>]\");\n+       \"           [--no-turtle-speed] [--no-optional-locks]\n[--no-advice] [--bare]\\n\"\n+       \"           [--git-dir=<path>] [--work-tree=<path>]\n[--namespace=<name>]\\n\"\n+       \"           [--config-env=<name>=<envvar>] <command> [<args>]\");\n\n const char git_more_info_string[] =\n     N_(\"'git help -a' and 'git help -g' list available subcommands and some\\n\"\n@@ -206,6 +206,10 @@ static int handle_options(const char ***argv, int\n*argc, int *envchanged)\n             setenv(NO_LAZY_FETCH_ENVIRONMENT, \"1\", 1);\n             if (envchanged)\n                 *envchanged = 1;\n+        } else if (!strcmp(cmd, \"--no-turtle-speed\")) {\n+            setenv(NO_TURTLE_SPEED_ENVIRONMENT, \"1\", 1);\n+            if (envchanged)\n+                *envchanged = 1;\n         } else if (!strcmp(cmd, \"--no-replace-objects\")) {\n             disable_replace_refs();\n             setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, \"1\", 1);\ndiff --git a/progress.c b/progress.c\nindex 8315bdc3d4..b30c9f11d3 100644\n--- a/progress.c\n+++ b/progress.c\n@@ -195,6 +195,7 @@ void display_throughput(struct progress *progress,\nuint64_t total)\n     struct throughput *tp;\n     uint64_t now_ns;\n     unsigned int misecs, count, rate;\n+    const char *turtle_env = getenv(NO_TURTLE_SPEED_ENVIRONMENT);\n\n     if (!progress)\n         return;\n@@ -245,6 +246,13 @@ void display_throughput(struct progress\n*progress, uint64_t total)\n     tp->last_misecs[tp->idx] = misecs;\n     tp->idx = (tp->idx + 1) % TP_IDX_MAX;\n\n+    if (turtle_env &&\n+        *turtle_env == '1' &&\n+        rate < 128 &&\n+        progress->title &&\n+        strstr(progress->title, \"Receiving objects\"))\n+        die(_(\"stopping due to a <128 KiB/s turtle speed: %u KiB/s\"), rate);\n+\n     throughput_string(&tp->display, total, rate);\n     if (progress->last_value != -1 && progress_update)\n         display(progress, progress->last_value, NULL);\n"},{"id":"538138","messageId":"aatjasMiPIeT0s27@fruit.crustytoothpaste.net","threadId":"65157","inReplyTo":"CAK7947msLiGgrYTcg1m3ew+bP0F+VNbRaTy=ZW7zkkHh69bN0Q@mail.gmail.com","subject":"Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-03-06T23:29:46Z","receivedAt":"2026-03-06T23:29:48Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2026-03-06 at 22:14:28, Mike Banon wrote:\n> When cloning large repositories from a website with multiple Git servers,\n> the client may be directed to a \"turtle-slow\" server, causing the transfer\n> to proceed at an unusably slow speed. This can lead to stalled downloads,\n> particularly problematic for automated scripts that clone many\n> repositories. This option makes Git abort the clone if the download rate\n> falls below 128 KiB/s while receiving objects, typically catching slow\n> servers early in the transfer, enabling scripts to retry the clone until\n> they obtain a fast connection.\n\nI'm not aware of any servers that this option would be useful for, but\nI'm willing to assume for the sake of argument that some exist with this\ndesign.  I don't think it's a very good design, but I admit that there\nare many things on the Internet that are poorly designed.\n\nI think it would be more helpful to provide an option\n`--min-speed=128KiB` or something.  Assuming Git is still around in a\ndecade, we might consider 10 MiB/s to be absurdly slow then and an\noption that hard-coded the slow speed would be decidedly less useful.\nMany users might have different speeds that would be more tailored to\ntheir environment even now.\n\nI also think that the word \"turtle\" in this context might be poorly\nunderstood by people who are not native English speakers.  I agree that\nturtles are typically thought of as slow creatures, but they may\nepitomize other traits in other languages or cultures (such as wisdom or\nlongevity[0]) that might not bring to mind slowness.\n\nIn addition, I would think we'd want to update the manual page as well.\nMy guess is that CI would have caught the fact that the option was not\npresent in the manual page.\n\nI didn't give extensive review to the design, but I would think passing\nan option to the child process or using some sort of option message\n(such as in the HTTP helper) would be better than passing an environment\nvariable if that's possible.  If it's not, perhaps the commit message\ncould explain why that wouldn't work.\n\n[0] https://en.wikipedia.org/wiki/Cultural_depictions_of_turtles\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"538145","messageId":"CAK7947n9gqhRoykNUR4NvPFiaCB4nuotxQTT=eftSF8O9ZO2rg@mail.gmail.com","threadId":"65157","inReplyTo":"aatjasMiPIeT0s27@fruit.crustytoothpaste.net","subject":"Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","fromName":"Mike Banon","fromEmail":"mikebdp2@gmail.com","sentAt":"2026-03-07T00:29:18Z","receivedAt":"2026-03-07T00:29:30Z","isPatch":true,"sender":{"key":"mikebdp2@gmail.com","avatar":null},"body":"Brian, thank you very much for your code review!\n\nThis problem has been happening to me for a couple of weeks while\nusing GitHub: as a part of my \"floppinux-amd64net\" pet project (2.88\nMB Linux floppy image with Ethernet/WiFi – for putting into a coreboot\nBIOS image), I wrote a large [1] script that clones a lot of GitHub\nrepositories and builds everything from scratch. With some non-zero\nprobability (floating between 5%–30% depending on day/location and\nother unknown factors), my git clone operation gets directed to a\nreally slow Git server with around ~70 KiB/s download speed, which is\nespecially painful if it tries to clone some large repo like a\nlinux-firmware. But if I terminate that git clone and start it again,\nthere is a good chance that my next connection will be fast (at least\na few MiB/s). So with the bash code like [2] below – in case of a slow\nconnection, it will simply restart until it gets a fast server and\nclones successfully.\n\nI agree that more customization ability would be useful and support\nyour opinion about the turtles, so your \"--min-speed=128KiB\"\nsuggestion sounds great and I may try to implement it in the near\nfuture. At the moment I simply wanted to know if such a feature,\ninitially created for my personal needs, would be welcome upstream. It\nis unknown how many people are affected by such problems, i.e. I've\nnever had this annoying problem until recently.\n\nMy reason for using the environmental variable is simple: not being\nfamiliar with the git codebase, this \"variable solution\" is the most\nminimalistic diff I've been able to come up with (just 40 non-dense\nlines) that is still working in practice. Another way was adding some\n\"speed_check\" flag variable (either to a \"progress\" data structure or\nas some \"extern\"ally-exposed variable), but I ran into some problems\nwith this approach and just did what was more reachable to me as a\nnewbie here.\n\nBest regards, Mike Banon\nOpen Source Community Manager of 3mdeb - https://3mdeb.com/\n\n[1] https://github.com/mikebdp2/floppinux-amd64net/blob/main/floppinux-amd64net.sh\n\n[2]\n# Formatting\n   bold=\"\\033[1m\"\n   bred=\"\\033[1;31m\"\n bgreen=\"\\033[1;32m\"\nbyellow=\"\\033[1;33m\"\n   bend=\"\\033[0m\"\n# Prints the status message in '$1: $2' format with a green color\nhighlighting of a '$1'.\nprintgr () {\n    printf \"${bgreen}$1${bend}: $2\\n\"\n    return 0\n}\n# Git clones a '$1' repository from a '$2' URL, with a '$3' branch if specified.\ngit_cloner () {\n    if git clone --no-turtle-speed --depth=1 ${3:+--branch $3} \"$2\" &&\n[ -d \"$1/.git/\" ] ; then\n        return 0\n    else\n        rm -rf \"$1\"\n        printf \"\\n${byellow}WARNING${bend}: cannot download a\n${byellow}$1${bend} repository !\"\n        printf \"\\n         Please check your Internet connection and\ntry again.\\n\"\n        sleep 1\n        return 1\n    fi\n}\n# linux-firmware needed for some Ethernet/WiFi network adapters\nfirmware_get () {\n    printgr \"LINUX-FIRMWARE\" \"remove the old directory if it exists\"\n    rm -rf ./linux-firmware/\n    printgr \"LINUX-FIRMWARE\" \"git clone a repository\"\n    while true; do\n        git_cloner \"./linux-firmware\"\n\"https://github.com/mikebdp2/linux-firmware.git\" && break\n    done\n    return 0\n}\n"},{"id":"538156","messageId":"aauAjQhhh7pxIxjD@fruit.crustytoothpaste.net","threadId":"65157","inReplyTo":"CAK7947n9gqhRoykNUR4NvPFiaCB4nuotxQTT=eftSF8O9ZO2rg@mail.gmail.com","subject":"Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-03-07T01:34:05Z","receivedAt":"2026-03-07T01:34:07Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2026-03-07 at 00:29:18, Mike Banon wrote:\n> Brian, thank you very much for your code review!\n> \n> This problem has been happening to me for a couple of weeks while\n> using GitHub: as a part of my \"floppinux-amd64net\" pet project (2.88\n> MB Linux floppy image with Ethernet/WiFi – for putting into a coreboot\n> BIOS image), I wrote a large [1] script that clones a lot of GitHub\n> repositories and builds everything from scratch. With some non-zero\n> probability (floating between 5%–30% depending on day/location and\n> other unknown factors), my git clone operation gets directed to a\n> really slow Git server with around ~70 KiB/s download speed, which is\n> especially painful if it tries to clone some large repo like a\n> linux-firmware. But if I terminate that git clone and start it again,\n> there is a good chance that my next connection will be fast (at least\n> a few MiB/s). So with the bash code like [2] below – in case of a slow\n> connection, it will simply restart until it gets a fast server and\n> clones successfully.\n\nGitHub doesn't throttle speeds once the operation starts, although it\nsometimes does delay the _start_ of an operation if there's excessive\nuse (for example, if you're cloning the same repository too many times,\nas in some automated systems).  GitHub wants the operation to complete\nas quickly as possible once it starts because a clone or fetch will take\nthe same CPU and memory resources no matter how long it's running and\nobviously freeing those resources faster is better than consuming them\nfor longer periods (since then they can be used for other users).\n\nIf you're seeing this, I'd recommend opening a ticket at GitHub and\nincluding the output at https://github-debug.com/, since that will be\nhelpful in troubleshooting the problem.  For instance, it may be that\nthere's a bad connection between your ISP and GitHub and that can be\naddressed.  Or, if there is an overloaded server impacting things, that\nwould be a thing that GitHub would want to look into.\n\nIf you can capture the problem with `GIT_TRACE=1 GIT_TRANSFER_TRACE=1\nGIT_CURL_VERBOSE=1` before your Git command and you include that output\nand the repository you're having problems with, then that will allow\nGitHub to look up the request by its ID and find what's going on.\n\nMy participation in the list from this email address is in my personal\ncapacity and my personal capacity alone, but I do work on the Git\nservices at GitHub and obviously we want everyone to have a good\nexperience provided they're using a reasonable amount of resources and\notherwise behaving appropriately.\n\nOf course, I think people would still find the `--min-speed` patch\nuseful, but my hope is that it's not a feature you'll need to make use\nof.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"538255","messageId":"GV2PPF54105D074FFCB458CC64E663AD54F9C79A@GV2PPF54105D074.eurprd02.prod.outlook.com","threadId":"65157","inReplyTo":"aatjasMiPIeT0s27@fruit.crustytoothpaste.net","subject":"RE: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones","fromName":"Richard Kerry","fromEmail":"richard.kerry@atos.net","sentAt":"2026-03-09T09:31:13Z","receivedAt":"2026-03-09T09:36:26Z","isPatch":true,"sender":{"key":"richard.kerry@atos.net","avatar":null},"body":"\n> -----Original Message-----\n> From: brian m. carlson <sandals@crustytoothpaste.net>\n> Sent: 06 March 2026 23:30\n> To: Mike Banon <mikebdp2@gmail.com>\n> Cc: git@vger.kernel.org\n> Subject: Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow\n> clones\n \n> I also think that the word \"turtle\" in this context might be poorly understood by\n> people who are not native English speakers.  I agree that turtles are typically\n> thought of as slow creatures, but they may epitomize other traits in other\n> languages or cultures (such as wisdom or\n> longevity[0]) that might not bring to mind slowness.\n\nI believe American usage tends to lose the distinction between turtle, tortoise and terrapin, where British (and other?) usage distinguishes them.\nI think tortoises are land-based, and are the slow-moving ones.  Turtles and terrapins are swimmers and whenever I've seen them in documentaries they seem to move quite quickly.\n\nJust my two-penn'orth (not US, or anywhere else that uses cents, so not inclined to say two cents)\n\nRegards,\nRichard.\n\n"}]}