Volume XXII, number 280Wednesday, October 7, 2026Latest message 34 minutes ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

patchclone, progress: add --no-turtle-speed option to abort slow clones

5 messages between Mar 6, 2026 and Mar 9, 2026, from Mike Banon, brian m. carlson, Richard Kerry.

Plain Markdown or JSON for tools and agents. Diffs are folded; open one to read it.

Mike BanonMar 6, 2026, 22:14 UTC on lore

When cloning large repositories from a website with multiple Git servers, the client may be directed to a "turtle-slow" server, causing the transfer to proceed at an unusably slow speed. This can lead to stalled downloads, particularly problematic for automated scripts that clone many repositories. This option makes Git abort the clone if the download rate falls below 128 KiB/s while receiving objects, typically catching slow servers early in the transfer, enabling scripts to retry the clone until they obtain a fast connection.

Signed-off-by: Mike Banon <mikebdp2@gmail.com>
Show changes to 4 files +33 −3

builtin/clone.c, environment.h, git.c, progress.c

diff --git a/builtin/clone.c b/builtin/clone.c
index fba3c9c508..a9ed2c193d 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -94,6 +94,13 @@ static int recurse_submodules_cb(const struct option *opt,
     return 0;
 }

+static int set_turtle_speed_env(const struct option *opt UNUSED,
+                const char *arg UNUSED, int unset UNUSED)
+{
+    setenv(NO_TURTLE_SPEED_ENVIRONMENT, "1", 1);
+    return 0;
+}
+
 static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
 {
     static const char *suffix[] = { "/.git", "", ".git/.git", ".git" };
@@ -946,6 +953,16 @@ int cmd_clone(int argc,
             .callback = recurse_submodules_cb,
             .defval = (intptr_t)".",
         },
+        {
+            .type = OPTION_CALLBACK,
+            .long_name = "no-turtle-speed",
+            .value = NULL,
+            .argh = NULL,
+            .help = N_("abort clone if speed drops below 128 KiB/s"),
+            .flags = PARSE_OPT_NOARG,
+            .callback = set_turtle_speed_env,
+            .defval = 0,
+        },
         OPT_ALIAS(0, "recursive", "recurse-submodules"),
         OPT_INTEGER('j', "jobs", &max_jobs,
                 N_("number of submodules cloned in parallel")),
diff --git a/environment.h b/environment.h
index 123a71cdc8..cb316cf321 100644
--- a/environment.h
+++ b/environment.h
@@ -24,6 +24,7 @@
 #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
 #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
 #define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
+#define NO_TURTLE_SPEED_ENVIRONMENT "GIT_NO_TURTLE_SPEED"
 #define GITATTRIBUTES_FILE ".gitattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
diff --git a/git.c b/git.c
index 744cb6527e..d0c4909fef 100644
--- a/git.c
+++ b/git.c
@@ -40,9 +40,9 @@ const char git_usage_string[] =
     N_("git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
        "           [--exec-path[=<path>]] [--html-path] [--man-path]
[--info-path]\n"
        "           [-p | --paginate | -P | --no-pager]
[--no-replace-objects] [--no-lazy-fetch]\n"
-       "           [--no-optional-locks] [--no-advice] [--bare]
[--git-dir=<path>]\n"
-       "           [--work-tree=<path>] [--namespace=<name>]
[--config-env=<name>=<envvar>]\n"
-       "           <command> [<args>]");
+       "           [--no-turtle-speed] [--no-optional-locks]
[--no-advice] [--bare]\n"
+       "           [--git-dir=<path>] [--work-tree=<path>]
[--namespace=<name>]\n"
+       "           [--config-env=<name>=<envvar>] <command> [<args>]");

 const char git_more_info_string[] =
     N_("'git help -a' and 'git help -g' list available subcommands and some\n"
@@ -206,6 +206,10 @@ static int handle_options(const char ***argv, int
*argc, int *envchanged)
             setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
             if (envchanged)
                 *envchanged = 1;
+        } else if (!strcmp(cmd, "--no-turtle-speed")) {
+            setenv(NO_TURTLE_SPEED_ENVIRONMENT, "1", 1);
+            if (envchanged)
+                *envchanged = 1;
         } else if (!strcmp(cmd, "--no-replace-objects")) {
             disable_replace_refs();
             setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
diff --git a/progress.c b/progress.c
index 8315bdc3d4..b30c9f11d3 100644
--- a/progress.c
+++ b/progress.c
@@ -195,6 +195,7 @@ void display_throughput(struct progress *progress,
uint64_t total)
     struct throughput *tp;
     uint64_t now_ns;
     unsigned int misecs, count, rate;
+    const char *turtle_env = getenv(NO_TURTLE_SPEED_ENVIRONMENT);

     if (!progress)
         return;
@@ -245,6 +246,13 @@ void display_throughput(struct progress
*progress, uint64_t total)
     tp->last_misecs[tp->idx] = misecs;
     tp->idx = (tp->idx + 1) % TP_IDX_MAX;

+    if (turtle_env &&
+        *turtle_env == '1' &&
+        rate < 128 &&
+        progress->title &&
+        strstr(progress->title, "Receiving objects"))
+        die(_("stopping due to a <128 KiB/s turtle speed: %u KiB/s"), rate);
+
     throughput_string(&tp->display, total, rate);
     if (progress->last_value != -1 && progress_update)
         display(progress, progress->last_value, NULL);
brian m. carlsonMar 6, 2026, 23:29 UTC in reply to Mike Banon on lore

Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones

On 2026-03-06 at 22:14:28, Mike Banon wrote:
Show 8 quoted lines
> When cloning large repositories from a website with multiple Git servers,
> the client may be directed to a "turtle-slow" server, causing the transfer
> to proceed at an unusably slow speed. This can lead to stalled downloads,
> particularly problematic for automated scripts that clone many
> repositories. This option makes Git abort the clone if the download rate
> falls below 128 KiB/s while receiving objects, typically catching slow
> servers early in the transfer, enabling scripts to retry the clone until
> they obtain a fast connection.

I'm not aware of any servers that this option would be useful for, but I'm willing to assume for the sake of argument that some exist with this design. I don't think it's a very good design, but I admit that there are many things on the Internet that are poorly designed.

I think it would be more helpful to provide an option `--min-speed=128KiB` or something. Assuming Git is still around in a decade, we might consider 10 MiB/s to be absurdly slow then and an option that hard-coded the slow speed would be decidedly less useful. Many users might have different speeds that would be more tailored to their environment even now.

I also think that the word "turtle" in this context might be poorly understood by people who are not native English speakers. I agree that turtles are typically thought of as slow creatures, but they may epitomize other traits in other languages or cultures (such as wisdom or longevity[0]) that might not bring to mind slowness.

In addition, I would think we'd want to update the manual page as well. My guess is that CI would have caught the fact that the option was not present in the manual page.

I didn't give extensive review to the design, but I would think passing an option to the child process or using some sort of option message (such as in the HTTP helper) would be better than passing an environment variable if that's possible. If it's not, perhaps the commit message could explain why that wouldn't work.

[0] https://en.wikipedia.org/wiki/Cultural_depictions_of_turtles
-- 
brian m. carlson (they/them)
Toronto, Ontario, CA
Mike BanonMar 7, 2026, 00:29 UTC in reply to brian m. carlson on lore

Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones

Brian, thank you very much for your code review!

This problem has been happening to me for a couple of weeks while using GitHub: as a part of my "floppinux-amd64net" pet project (2.88 MB Linux floppy image with Ethernet/WiFi – for putting into a coreboot BIOS image), I wrote a large [1] script that clones a lot of GitHub repositories and builds everything from scratch. With some non-zero probability (floating between 5%–30% depending on day/location and other unknown factors), my git clone operation gets directed to a really slow Git server with around ~70 KiB/s download speed, which is especially painful if it tries to clone some large repo like a linux-firmware. But if I terminate that git clone and start it again, there is a good chance that my next connection will be fast (at least a few MiB/s). So with the bash code like [2] below – in case of a slow connection, it will simply restart until it gets a fast server and clones successfully.

I agree that more customization ability would be useful and support your opinion about the turtles, so your "--min-speed=128KiB" suggestion sounds great and I may try to implement it in the near future. At the moment I simply wanted to know if such a feature, initially created for my personal needs, would be welcome upstream. It is unknown how many people are affected by such problems, i.e. I've never had this annoying problem until recently.

My reason for using the environmental variable is simple: not being familiar with the git codebase, this "variable solution" is the most minimalistic diff I've been able to come up with (just 40 non-dense lines) that is still working in practice. Another way was adding some "speed_check" flag variable (either to a "progress" data structure or as some "extern"ally-exposed variable), but I ran into some problems with this approach and just did what was more reachable to me as a newbie here.

Best regards, Mike Banon Open Source Community Manager of 3mdeb - https://3mdeb.com/

[1] https://github.com/mikebdp2/floppinux-amd64net/blob/main/floppinux-amd64net.sh
[2]
# Formatting
   bold="\033[1m"
   bred="\033[1;31m"
 bgreen="\033[1;32m"
byellow="\033[1;33m"
   bend="\033[0m"
# Prints the status message in '$1: $2' format with a green color
highlighting of a '$1'.
printgr () {
    printf "${bgreen}$1${bend}: $2\n"
    return 0
}
# Git clones a '$1' repository from a '$2' URL, with a '$3' branch if specified.
git_cloner () {
    if git clone --no-turtle-speed --depth=1 ${3:+--branch $3} "$2" &&
[ -d "$1/.git/" ] ; then
        return 0
    else
        rm -rf "$1"
        printf "\n${byellow}WARNING${bend}: cannot download a
${byellow}$1${bend} repository !"
        printf "\n         Please check your Internet connection and
try again.\n"
        sleep 1
        return 1
    fi
}
# linux-firmware needed for some Ethernet/WiFi network adapters
firmware_get () {
    printgr "LINUX-FIRMWARE" "remove the old directory if it exists"
    rm -rf ./linux-firmware/
    printgr "LINUX-FIRMWARE" "git clone a repository"
    while true; do
        git_cloner "./linux-firmware"
"https://github.com/mikebdp2/linux-firmware.git" && break
    done
    return 0
}
brian m. carlsonMar 7, 2026, 01:34 UTC in reply to Mike Banon on lore

Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones

On 2026-03-07 at 00:29:18, Mike Banon wrote:
Show 16 quoted lines
> Brian, thank you very much for your code review!
> 
> This problem has been happening to me for a couple of weeks while
> using GitHub: as a part of my "floppinux-amd64net" pet project (2.88
> MB Linux floppy image with Ethernet/WiFi – for putting into a coreboot
> BIOS image), I wrote a large [1] script that clones a lot of GitHub
> repositories and builds everything from scratch. With some non-zero
> probability (floating between 5%–30% depending on day/location and
> other unknown factors), my git clone operation gets directed to a
> really slow Git server with around ~70 KiB/s download speed, which is
> especially painful if it tries to clone some large repo like a
> linux-firmware. But if I terminate that git clone and start it again,
> there is a good chance that my next connection will be fast (at least
> a few MiB/s). So with the bash code like [2] below – in case of a slow
> connection, it will simply restart until it gets a fast server and
> clones successfully.

GitHub doesn't throttle speeds once the operation starts, although it sometimes does delay the _start_ of an operation if there's excessive use (for example, if you're cloning the same repository too many times, as in some automated systems). GitHub wants the operation to complete as quickly as possible once it starts because a clone or fetch will take the same CPU and memory resources no matter how long it's running and obviously freeing those resources faster is better than consuming them for longer periods (since then they can be used for other users).

If you're seeing this, I'd recommend opening a ticket at GitHub and including the output at https://github-debug.com/, since that will be helpful in troubleshooting the problem. For instance, it may be that there's a bad connection between your ISP and GitHub and that can be addressed. Or, if there is an overloaded server impacting things, that would be a thing that GitHub would want to look into.

If you can capture the problem with `GIT_TRACE=1 GIT_TRANSFER_TRACE=1 GIT_CURL_VERBOSE=1` before your Git command and you include that output and the repository you're having problems with, then that will allow GitHub to look up the request by its ID and find what's going on.

My participation in the list from this email address is in my personal capacity and my personal capacity alone, but I do work on the Git services at GitHub and obviously we want everyone to have a good experience provided they're using a reasonable amount of resources and otherwise behaving appropriately.

Of course, I think people would still find the `--min-speed` patch useful, but my hope is that it's not a feature you'll need to make use of.

-- 
brian m. carlson (they/them)
Toronto, Ontario, CA
Richard KerryMar 9, 2026, 09:31 UTC in reply to brian m. carlson on lore

RE: [PATCH] clone, progress: add --no-turtle-speed option to abort slow clones

Show 7 quoted lines
> -----Original Message-----
> From: brian m. carlson <sandals@crustytoothpaste.net>
> Sent: 06 March 2026 23:30
> To: Mike Banon <mikebdp2@gmail.com>
> Cc: git@vger.kernel.org
> Subject: Re: [PATCH] clone, progress: add --no-turtle-speed option to abort slow
> clones
Show 5 quoted lines
> I also think that the word "turtle" in this context might be poorly understood by
> people who are not native English speakers.  I agree that turtles are typically
> thought of as slow creatures, but they may epitomize other traits in other
> languages or cultures (such as wisdom or
> longevity[0]) that might not bring to mind slowness.

I believe American usage tends to lose the distinction between turtle, tortoise and terrapin, where British (and other?) usage distinguishes them. I 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.

Just my two-penn'orth (not US, or anywhere else that uses cents, so not inclined to say two cents)

Regards, Richard.

Back to recent threads