{"thread":{"id":"65565","subject":"[Bug] fetch --deepen truncates history in v2.54.0","startedAt":"2026-04-29T11:27:21Z","lastAt":"2026-05-11T19:21:17Z","messageCount":14,"participants":["Owen Stephens","D. Ben Knoble","Mikael Magnusson","René Scharfe","Samo Pogačnik","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"542470","messageId":"CANOh7gEEw+6146NN3JV8EYxQarj0KkyA7r3RZ6v-DxeqQZLrCA@mail.gmail.com","threadId":"65565","inReplyTo":null,"subject":"[Bug] fetch --deepen truncates history in v2.54.0","fromName":"Owen Stephens","fromEmail":"owen@owenstephens.co.uk","sentAt":"2026-04-29T11:27:08Z","receivedAt":"2026-04-29T11:27:21Z","isPatch":false,"body":"> What did you do before the bug happened? (Steps to reproduce your issue)\n\nRepeatedy called `git fetch --deepen 2` inside a shallow repo that was a\nfile:// clone of another repo. Once all commits had been fetched, a subsequent\n`fetch --deepen` appears to \"reset\" the repo back to being shallow with a depth\nof 2. A reproduction script is included below. This issue appears to have been\nintroduced in v2.54.0.\n\n> What did you expect to happen? (Expected behavior)\n\nI expected `git fetch --deepen` in a non-shallow repo with no upstream commits\nto be a no-op.\n\n> What happened instead? (Actual behavior)\n\n`git log` history is truncated to two commits, and repo is considered shallow\nby `git rev-parse --is-shallow-repository`.\n\n> What's different between what you expected and what actually happened?\n\nThe previously-present commits in `git log` are missing, and the repo is again\nconsidered shallow.\n\n> Anything else you want to add:\n\nCommit 3ef68ff seems relevant.\n\nThe following script reproduces the issue in 2.54.0, and does not reproduce the\nissue in 2.53.0:\n\n```\nmkdir repro.git\ncd repro.git\n\ngit init\n\nfor i in $(seq 1 4); do\n  echo \"$i\" >> file.txt\n  git add file.txt\n  git commit -m \"Change $i\"\ndone\n\ncd ..\n\ngit clone --depth 2 \"file://$PWD/repro.git\" repro_clone.git\ncd repro_clone.git\n\necho \"Shallow repo? $(git rev-parse --is-shallow-repository)\"\ngit log --oneline\n\nfor i in $(seq 1 3); do\n  git fetch --deepen 2\n  echo \"Shallow repo? $(git rev-parse --is-shallow-repository)\"\n  git log --oneline\ndone\n```\n\nThe key lines in the output are:\n```\nShallow repo? true\n63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n864e13c (grafted) Change 3\nremote: Enumerating objects: 10, done.\nremote: Counting objects: 100% (10/10), done.\nremote: Compressing objects: 100% (2/2), done.\nremote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)\nUnpacking objects: 100% (6/6), 351 bytes | 175.00 KiB/s, done.\n\nShallow repo? true\n63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n864e13c Change 3\n3e05d14 Change 2\n1d9fe14 (grafted) Change 1\nremote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n\nShallow repo? false\n63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n864e13c Change 3\n3e05d14 Change 2\n1d9fe14 Change 1\nremote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n\nShallow repo? true\n63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n864e13c (grafted) Change 351\n```\n\nN.b. that 1d9fe14 was present after the second iteration but missing after the\nthird, along with `--is-shallow-repository` changing from false back to true.\n\n[System Info]\ngit version:\ngit version 2.54.0\ncpu: arm64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nrust: disabled\nfeature: fsmonitor--daemon\ngettext: enabled\nlibcurl: 8.7.1\nzlib: 1.2.12\nSHA-1: SHA1_DC\nSHA-256: SHA256_BLK\ndefault-ref-format: files\ndefault-hash: sha1\nuname: Darwin 25.4.0 Darwin Kernel Version 25.4.0: Thu Mar 19 19:33:25\nPDT 2026; root:xnu-12377.101.15~1/RELEASE_ARM64_T6041 arm64\ncompiler info: clang: 21.0.0 (clang-2100.0.123.102)\nlibc info: no libc information available\n$SHELL (typically, interactive shell): /bin/zsh\n"},{"id":"542472","messageId":"CANOh7gE6rQ1ya+KusfYhbaG9iSNqNkUtYWbTAPFOs=Ff21YSDw@mail.gmail.com","threadId":"65565","inReplyTo":"CANOh7gEEw+6146NN3JV8EYxQarj0KkyA7r3RZ6v-DxeqQZLrCA@mail.gmail.com","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"Owen Stephens","fromEmail":"owen@owenstephens.co.uk","sentAt":"2026-04-29T13:14:51Z","receivedAt":"2026-04-29T13:15:04Z","isPatch":false,"body":"On Wed, Apr 29, 2026 at 12:27 PM Owen Stephens <owen@owenstephens.co.uk> wrote:\n> The key lines in the output are:\n> ```\n> Shallow repo? true\n> 63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n> 864e13c (grafted) Change 3\n> remote: Enumerating objects: 10, done.\n> remote: Counting objects: 100% (10/10), done.\n> remote: Compressing objects: 100% (2/2), done.\n> remote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)\n> Unpacking objects: 100% (6/6), 351 bytes | 175.00 KiB/s, done.\n>\n> Shallow repo? true\n> 63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n> 864e13c Change 3\n> 3e05d14 Change 2\n> 1d9fe14 (grafted) Change 1\n> remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n>\n> Shallow repo? false\n> 63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n> 864e13c Change 3\n> 3e05d14 Change 2\n> 1d9fe14 Change 1\n> remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n>\n> Shallow repo? true\n> 63d1ebe (HEAD -> master, origin/master, origin/HEAD) Change 4\n> 864e13c (grafted) Change 351\n> ```\n\nApologies, I just noticed that I had inadvertently munged the final\nline - it should read \"864e13c (grafted) Change 3\"\n\nOwen.\n"},{"id":"542473","messageId":"CALnO6CBzd0coeyJ9B+EkGWsSNEVTdVLvcVmEraGNxnUm5wXy=g@mail.gmail.com","threadId":"65565","inReplyTo":"CANOh7gEEw+6146NN3JV8EYxQarj0KkyA7r3RZ6v-DxeqQZLrCA@mail.gmail.com","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-04-29T13:16:00Z","receivedAt":"2026-04-29T13:16:12Z","isPatch":false,"body":"On Wed, Apr 29, 2026 at 7:27 AM Owen Stephens <owen@owenstephens.co.uk> wrote:\n>\n> > What did you do before the bug happened? (Steps to reproduce your issue)\n>\n> Repeatedy called `git fetch --deepen 2` inside a shallow repo that was a\n> file:// clone of another repo. Once all commits had been fetched, a subsequent\n> `fetch --deepen` appears to \"reset\" the repo back to being shallow with a depth\n> of 2. A reproduction script is included below. This issue appears to have been\n> introduced in v2.54.0.\n>\n> > What did you expect to happen? (Expected behavior)\n>\n> I expected `git fetch --deepen` in a non-shallow repo with no upstream commits\n> to be a no-op.\n\nHere's the relevant part of git-fetch(1):\n\n       --depth=<depth>\n           Limit fetching to the specified number of commits from the tip of\n           each remote branch history. If fetching to a shallow repository\n           created by git clone with --depth=<depth> option (see git-clone(1)),\n           deepen or shorten the history to the specified number of commits.\n           Tags for the deepened commits are not fetched.\n\n       --deepen=<depth>\n           Similar to --depth, except it specifies the number of commits from\n           the current shallow boundary instead of from the tip of each remote\n           branch history.\n\nI can see how one might read this as implying that when fetching in a\nnon-shallow repository, there's no effect, but I don't think the text\nexplicitly says that. In fact, the first sentence under \"--depth\"\n(which is of course relevant for \"--deepen\") is unconditional.\n\nSo I'm not sure it should be a no-op.\n\nThat said, it is possible the behavior changed between 2.53 and 2.54?\nI haven't tried to reproduce or bisect yet.\n\nBest,\nD. Ben Knoble\n"},{"id":"542519","messageId":"CAHYJk3QZDYv+393ptB9FGuYwSmYKmqw6mWd+fn1bgost-5Ayqg@mail.gmail.com","threadId":"65565","inReplyTo":"CALnO6CBzd0coeyJ9B+EkGWsSNEVTdVLvcVmEraGNxnUm5wXy=g@mail.gmail.com","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"Mikael Magnusson","fromEmail":"mikachu@gmail.com","sentAt":"2026-04-30T09:10:05Z","receivedAt":"2026-04-30T09:10:19Z","isPatch":false,"body":"On Wed, Apr 29, 2026 at 3:23 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:\n>\n> On Wed, Apr 29, 2026 at 7:27 AM Owen Stephens <owen@owenstephens.co.uk> wrote:\n> >\n> > > What did you do before the bug happened? (Steps to reproduce your issue)\n> >\n> > Repeatedy called `git fetch --deepen 2` inside a shallow repo that was a\n> > file:// clone of another repo. Once all commits had been fetched, a subsequent\n> > `fetch --deepen` appears to \"reset\" the repo back to being shallow with a depth\n> > of 2. A reproduction script is included below. This issue appears to have been\n> > introduced in v2.54.0.\n> >\n> > > What did you expect to happen? (Expected behavior)\n> >\n> > I expected `git fetch --deepen` in a non-shallow repo with no upstream commits\n> > to be a no-op.\n>\n> Here's the relevant part of git-fetch(1):\n>\n>        --depth=<depth>\n>            Limit fetching to the specified number of commits from the tip of\n>            each remote branch history. If fetching to a shallow repository\n>            created by git clone with --depth=<depth> option (see git-clone(1)),\n>            deepen or shorten the history to the specified number of commits.\n>            Tags for the deepened commits are not fetched.\n>\n>        --deepen=<depth>\n>            Similar to --depth, except it specifies the number of commits from\n>            the current shallow boundary instead of from the tip of each remote\n>            branch history.\n>\n> I can see how one might read this as implying that when fetching in a\n> non-shallow repository, there's no effect, but I don't think the text\n> explicitly says that. In fact, the first sentence under \"--depth\"\n> (which is of course relevant for \"--deepen\") is unconditional.\n\nOne would assume that this 'shallow boundary' on a non-shallow\nrepository would be the *start* of the history, not the current tip,\nand thus it would be a no-op. Especially if you consider the position\nof this 'shallow boundary' throughout the process.\nconsider the repo\nA-B-C-D-E\nyou have a shallow repo with\nA-B*\nwhere * marks the shallow boundary, after another fetch --deepen=2 we get\nA-B-C-D*\nand then\nA-B-C-D-E*\nyou're proposing that it's reasonable that this should instead be\n*A-B-C-D-E\nsuch that another fetch gives us\nA-B*\n\n> So I'm not sure it should be a no-op.\n\nI think it's pretty obvious that it should be.\n\n> That said, it is possible the behavior changed between 2.53 and 2.54?\n> I haven't tried to reproduce or bisect yet.\n\nThe mail you're replying to already answers this question.\n\n-- \nMikael Magnusson\n"},{"id":"542581","messageId":"a5fd970d-fd78-41bc-98f8-a6a87a7f39cc@web.de","threadId":"65565","inReplyTo":"CANOh7gEEw+6146NN3JV8EYxQarj0KkyA7r3RZ6v-DxeqQZLrCA@mail.gmail.com","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-05-02T09:22:49Z","receivedAt":"2026-05-02T09:22:59Z","isPatch":false,"body":"On 4/29/26 1:27 PM, Owen Stephens wrote:\n>> What did you do before the bug happened? (Steps to reproduce your issue)\n> \n> Repeatedy called `git fetch --deepen 2` inside a shallow repo that was a\n> file:// clone of another repo. Once all commits had been fetched, a subsequent\n> `fetch --deepen` appears to \"reset\" the repo back to being shallow with a depth\n> of 2. A reproduction script is included below. This issue appears to have been\n> introduced in v2.54.0.\n> \n>> What did you expect to happen? (Expected behavior)\n> \n> I expected `git fetch --deepen` in a non-shallow repo with no upstream commits\n> to be a no-op.\n> \n>> What happened instead? (Actual behavior)\n> \n> `git log` history is truncated to two commits, and repo is considered shallow\n> by `git rev-parse --is-shallow-repository`.\n> \n>> What's different between what you expected and what actually happened?\n> \n> The previously-present commits in `git log` are missing, and the repo is again\n> considered shallow.\n> \n>> Anything else you want to add:\n> \n> Commit 3ef68ff seems relevant.\n\nIndeed, bisect identifies 3ef68ff40e (shallow: handling fetch relative-deepen,\n2026-02-15) and reverting it fixes the issue.  Copying its author.\n> The following script reproduces the issue in 2.54.0, and does not reproduce the\n> issue in 2.53.0:\n> \n> ```\n> mkdir repro.git\n> cd repro.git\n> \n> git init\n> \n> for i in $(seq 1 4); do\n>   echo \"$i\" >> file.txt\n>   git add file.txt\n>   git commit -m \"Change $i\"\n> done\n> \n> cd ..\n> \n> git clone --depth 2 \"file://$PWD/repro.git\" repro_clone.git\n> cd repro_clone.git\n> \n> echo \"Shallow repo? $(git rev-parse --is-shallow-repository)\"\n> git log --oneline\n> \n> for i in $(seq 1 3); do\n>   git fetch --deepen 2\n>   echo \"Shallow repo? $(git rev-parse --is-shallow-repository)\"\n>   git log --oneline\n> done\n> ```\n\nNice!  Here's a test for that:\n\n\ndiff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh\nindex 6588ce6226..fdb1dd9823 100755\n--- a/t/t5537-fetch-shallow.sh\n+++ b/t/t5537-fetch-shallow.sh\n@@ -251,6 +251,16 @@ test_expect_success '.git/shallow is edited by repack' '\n \t\torigin \"+refs/heads/*:refs/remotes/origin/*\"\n '\n \n+test_expect_success 'fetch --deepen does not truncate' '\n+\tgit clone --no-local .git full-clone &&\n+\tgit rev-parse --is-shallow-repository >expect &&\n+\tgit log --oneline >>expect &&\n+\tgit -C full-clone fetch --deepen=1 &&\n+\tgit -C full-clone rev-parse --is-shallow-repository >actual &&\n+\tgit -C full-clone log --oneline >>actual &&\n+\ttest_cmp expect actual\n+'\n+\n . \"$TEST_DIRECTORY\"/lib-httpd.sh\n start_httpd\n \n\n \n\n"},{"id":"542594","messageId":"e39f6770-fcc4-49a2-b3ba-5ac2ec9e047b@web.de","threadId":"65565","inReplyTo":"a5fd970d-fd78-41bc-98f8-a6a87a7f39cc@web.de","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-05-02T20:26:34Z","receivedAt":"2026-05-02T20:26:46Z","isPatch":false,"body":"On 5/2/26 11:22 AM, RenÃ© Scharfe wrote:\n> On 4/29/26 1:27 PM, Owen Stephens wrote:\n>>> What did you do before the bug happened? (Steps to reproduce your issue)\n>>\n>> Repeatedy called `git fetch --deepen 2` inside a shallow repo that was a\n>> file:// clone of another repo. Once all commits had been fetched, a subsequent\n>> `fetch --deepen` appears to \"reset\" the repo back to being shallow with a depth\n>> of 2. A reproduction script is included below. This issue appears to have been\n>> introduced in v2.54.0.\n>>\n>>> What did you expect to happen? (Expected behavior)\n>>\n>> I expected `git fetch --deepen` in a non-shallow repo with no upstream commits\n>> to be a no-op.\n>>\n>>> What happened instead? (Actual behavior)\n>>\n>> `git log` history is truncated to two commits, and repo is considered shallow\n>> by `git rev-parse --is-shallow-repository`.\n>>\n>>> What's different between what you expected and what actually happened?\n>>\n>> The previously-present commits in `git log` are missing, and the repo is again\n>> considered shallow.\n>>\n>>> Anything else you want to add:\n>>\n>> Commit 3ef68ff seems relevant.\n> \n> Indeed, bisect identifies 3ef68ff40e (shallow: handling fetch relative-deepen,\n> 2026-02-15) and reverting it fixes the issue.  Copying its author.\n\nHere's a simple fix, but it feels like cheating.  A proper one should\nlive in shallow.c, no?\n\n\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex a22c319467..310099b96d 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -2664,7 +2664,8 @@ int cmd_fetch(int argc,\n \t\t\tdie(_(\"negative depth in --deepen is not supported\"));\n \t\tif (depth)\n \t\t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--deepen\", \"--depth\");\n-\t\tdepth = xstrfmt(\"%d\", deepen_relative);\n+\t\tif (is_repository_shallow(the_repository))\n+\t\t\tdepth = xstrfmt(\"%d\", deepen_relative);\n \t}\n \tif (unshallow) {\n \t\tif (depth)\n\n"},{"id":"542779","messageId":"2afd4a28a9a542f8baeab488cb0801d6b98adb0a.camel@t-2.net","threadId":"65565","inReplyTo":"e39f6770-fcc4-49a2-b3ba-5ac2ec9e047b@web.de","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"Samo Pogačnik","fromEmail":"samo_pogacnik@t-2.net","sentAt":"2026-05-05T19:27:52Z","receivedAt":"2026-05-05T19:36:14Z","isPatch":false,"body":"On Sat, 2026-05-02 at 22:26 +0200, René Scharfe wrote:\n> On 5/2/26 11:22 AM, RenÃ© Scharfe wrote:\n> > On 4/29/26 1:27 PM, Owen Stephens wrote:\n> > > > What did you do before the bug happened? (Steps to reproduce your issue)\n> > > \n> > > Repeatedy called `git fetch --deepen 2` inside a shallow repo that was a\n> > > file:// clone of another repo. Once all commits had been fetched, a\n> > > subsequent\n> > > `fetch --deepen` appears to \"reset\" the repo back to being shallow with a\n> > > depth\n> > > of 2. A reproduction script is included below. This issue appears to have\n> > > been\n> > > introduced in v2.54.0.\n> > > \n> > > > What did you expect to happen? (Expected behavior)\n> > > \n> > > I expected `git fetch --deepen` in a non-shallow repo with no upstream\n> > > commits\n> > > to be a no-op.\n> > > \n> > > > What happened instead? (Actual behavior)\n> > > \n> > > `git log` history is truncated to two commits, and repo is considered\n> > > shallow\n> > > by `git rev-parse --is-shallow-repository`.\n> > > \n> > > > What's different between what you expected and what actually happened?\n> > > \n> > > The previously-present commits in `git log` are missing, and the repo is\n> > > again\n> > > considered shallow.\n> > > \n> > > > Anything else you want to add:\n> > > \n> > > Commit 3ef68ff seems relevant.\n> > \n> > Indeed, bisect identifies 3ef68ff40e (shallow: handling fetch relative-\n> > deepen,\n> > 2026-02-15) and reverting it fixes the issue.  Copying its author.\n> \n> Here's a simple fix, but it feels like cheating.  A proper one should\n> live in shallow.c, no?\n> \n> \n> diff --git a/builtin/fetch.c b/builtin/fetch.c\n> index a22c319467..310099b96d 100644\n> --- a/builtin/fetch.c\n> +++ b/builtin/fetch.c\n> @@ -2664,7 +2664,8 @@ int cmd_fetch(int argc,\n>  \t\t\tdie(_(\"negative depth in --deepen is not\n> supported\"));\n>  \t\tif (depth)\n>  \t\t\tdie(_(\"options '%s' and '%s' cannot be used\n> together\"), \"--deepen\", \"--depth\");\n> -\t\tdepth = xstrfmt(\"%d\", deepen_relative);\n> +\t\tif (is_repository_shallow(the_repository))\n> +\t\t\tdepth = xstrfmt(\"%d\", deepen_relative);\n>  \t}\n>  \tif (unshallow) {\n>  \t\tif (depth)\n> \n\nHi, thanks for pointing out this edge case. Would you care to check the\nfollowing change (the provided test is also a bit modified):\n\ndiff --git a/shallow.c b/shallow.c\nindex a156006d88..ec95653132 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -245,7 +245,11 @@ struct commit_list *get_shallow_commits(struct object_array\n*heads,\n                                        int depth, int shallow_flag, int\nnot_shallow_flag)\n {\n        if (shallows && deepen_relative) {\n-               depth += get_shallows_depth(heads, shallows);\n+               int cur_shallow_depth = get_shallows_depth(heads, shallows);\n+               if (cur_shallow_depth)\n+                       depth += cur_shallow_depth;\n+               else\n+                       return NULL;\n        }\n        return get_shallows_or_depth(heads, NULL, NULL,\n                                     depth, shallow_flag, not_shallow_flag);\ndiff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh\nindex 6588ce6226..9982dd2aa6 100755\n--- a/t/t5537-fetch-shallow.sh\n+++ b/t/t5537-fetch-shallow.sh\n@@ -251,6 +251,16 @@ test_expect_success '.git/shallow is edited by repack' '\n                origin \"+refs/heads/*:refs/remotes/origin/*\"\n '\n \n+test_expect_success 'fetch --deepen does not truncate' '\n+       git clone --no-local .git full-clone &&\n+       git -C full-clone rev-parse --is-shallow-repository >expect &&\n+       git -C full-clone log --oneline >>expect &&\n+       git -C full-clone fetch --deepen=1 &&\n+       git -C full-clone rev-parse --is-shallow-repository >actual &&\n+       git -C full-clone log --oneline >>actual &&\n+       test_cmp expect actual\n+'\n+\n . \"$TEST_DIRECTORY\"/lib-httpd.sh\n start_httpd\n\n"},{"id":"542783","messageId":"e8257951-4ea7-40ba-8043-f4f2a080b70b@web.de","threadId":"65565","inReplyTo":"2afd4a28a9a542f8baeab488cb0801d6b98adb0a.camel@t-2.net","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-05-05T20:34:37Z","receivedAt":"2026-05-05T20:34:46Z","isPatch":false,"body":"On 5/5/26 9:27 PM, Samo Pogačnik wrote:\n> \n> Hi, thanks for pointing out this edge case. Would you care to check the\n> following change (the provided test is also a bit modified):\n\nThere's spurious wrapping in the patch, but the changes look good to me.\n\nCare to send them with a commit message and sign-off?\n\nRené\n\n\n> diff --git a/shallow.c b/shallow.c\n> index a156006d88..ec95653132 100644\n> --- a/shallow.c\n> +++ b/shallow.c\n> @@ -245,7 +245,11 @@ struct commit_list *get_shallow_commits(struct object_array\n> *heads,\n>                                         int depth, int shallow_flag, int\n> not_shallow_flag)\n>  {\n>         if (shallows && deepen_relative) {\n> -               depth += get_shallows_depth(heads, shallows);\n> +               int cur_shallow_depth = get_shallows_depth(heads, shallows);\n> +               if (cur_shallow_depth)\n> +                       depth += cur_shallow_depth;\n> +               else\n> +                       return NULL;\n\nNice.  get_shallows_depth() returns 0 on full clones; translating it to\nan empty list of shallow commits makes sense.\n\n>         }\n>         return get_shallows_or_depth(heads, NULL, NULL,\n>                                      depth, shallow_flag, not_shallow_flag);\n> diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh\n> index 6588ce6226..9982dd2aa6 100755\n> --- a/t/t5537-fetch-shallow.sh\n> +++ b/t/t5537-fetch-shallow.sh\n> @@ -251,6 +251,16 @@ test_expect_success '.git/shallow is edited by repack' '\n>                 origin \"+refs/heads/*:refs/remotes/origin/*\"\n>  '\n>  \n> +test_expect_success 'fetch --deepen does not truncate' '\n> +       git clone --no-local .git full-clone &&\n> +       git -C full-clone rev-parse --is-shallow-repository >expect &&\n> +       git -C full-clone log --oneline >>expect &&\n> +       git -C full-clone fetch --deepen=1 &&\n> +       git -C full-clone rev-parse --is-shallow-repository >actual &&\n> +       git -C full-clone log --oneline >>actual &&\n\nUsing the exact same commands to prepare expect and actual creates a\npleasant symmetry.\n\n> +       test_cmp expect actual\n> +'\n> +\n>  . \"$TEST_DIRECTORY\"/lib-httpd.sh\n>  start_httpd\n> \n\n"},{"id":"542788","messageId":"b8cbdc24c871d96c85da590853a036263b90f92f.camel@t-2.net","threadId":"65565","inReplyTo":"e8257951-4ea7-40ba-8043-f4f2a080b70b@web.de","subject":"Re: [Bug] fetch --deepen truncates history in v2.54.0","fromName":"Samo Pogačnik","fromEmail":"samo_pogacnik@t-2.net","sentAt":"2026-05-05T21:26:39Z","receivedAt":"2026-05-05T21:26:55Z","isPatch":false,"body":"On Tue, 2026-05-05 at 22:34 +0200, René Scharfe wrote:\n> On 5/5/26 9:27 PM, Samo Pogačnik wrote:\n> > \n> > Hi, thanks for pointing out this edge case. Would you care to check the\n> > following change (the provided test is also a bit modified):\n> \n> There's spurious wrapping in the patch, but the changes look good to me.\n> \n> Care to send them with a commit message and sign-off?\n> \nI will, but it may take a while.\n\nthanks, Samo\n"},{"id":"542819","messageId":"20260506215647.3011769-1-samo_pogacnik@t-2.net","threadId":"65565","inReplyTo":"e8257951-4ea7-40ba-8043-f4f2a080b70b@web.de","subject":"[PATCH 1/1] shallow: fix relative deepen on non-shallow repositories","fromName":"Samo Pogačnik","fromEmail":"samo_pogacnik@t-2.net","sentAt":"2026-05-06T21:56:45Z","receivedAt":"2026-05-06T22:00:28Z","isPatch":true,"body":"The previous patch \"shallow: handling fetch relative-deepen\"\nintroduced a bug where using --deepen=<n> on a non-shallow\nrepository incorrectly treated the value as an absolute depth,\nresulting in a shallow fetch and truncated history.\n\nThis patch prevents any modification when a relative deepen is\nrequested on a non-shallow repository.\n\nA test is added to ensure that history is not changed when\n--deepen is used on a non-shallow repository.\n\nReported-by: Owen Stephens <owen@owenstephens.co.uk>\nSigned-off-by: Samo Pogačnik <samo_pogacnik@t-2.net>\n---\n shallow.c                |  6 +++++-\n t/t5537-fetch-shallow.sh | 10 ++++++++++\n 2 files changed, 15 insertions(+), 1 deletion(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex a8ad92e303..610ff3d13b 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -245,7 +245,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads,\n \t\t\t\t\tint depth, int shallow_flag, int not_shallow_flag)\n {\n \tif (shallows && deepen_relative) {\n-\t\tdepth += get_shallows_depth(heads, shallows);\n+\t\tint cur_shallow_depth = get_shallows_depth(heads, shallows);\n+\t\tif (cur_shallow_depth)\n+\t\t\tdepth += cur_shallow_depth;\n+\t\telse\n+\t\t\treturn NULL;\n \t}\n \treturn get_shallows_or_depth(heads, NULL, NULL,\n \t\t\t\t     depth, shallow_flag, not_shallow_flag);\ndiff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh\nindex 6588ce6226..9982dd2aa6 100755\n--- a/t/t5537-fetch-shallow.sh\n+++ b/t/t5537-fetch-shallow.sh\n@@ -251,6 +251,16 @@ test_expect_success '.git/shallow is edited by repack' '\n \t\torigin \"+refs/heads/*:refs/remotes/origin/*\"\n '\n \n+test_expect_success 'fetch --deepen does not truncate' '\n+\tgit clone --no-local .git full-clone &&\n+\tgit -C full-clone rev-parse --is-shallow-repository >expect &&\n+\tgit -C full-clone log --oneline >>expect &&\n+\tgit -C full-clone fetch --deepen=1 &&\n+\tgit -C full-clone rev-parse --is-shallow-repository >actual &&\n+\tgit -C full-clone log --oneline >>actual &&\n+\ttest_cmp expect actual\n+'\n+\n . \"$TEST_DIRECTORY\"/lib-httpd.sh\n start_httpd\n \n-- \n2.43.0\n\n"},{"id":"542987","messageId":"xmqqzf26x0vi.fsf@gitster.g","threadId":"65565","inReplyTo":"20260506215647.3011769-1-samo_pogacnik@t-2.net","subject":"Re: [PATCH 1/1] shallow: fix relative deepen on non-shallow repositories","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-11T00:09:53Z","receivedAt":"2026-05-11T00:09:57Z","isPatch":true,"body":"Samo Pogačnik <samo_pogacnik@t-2.net> writes:\n\n> The previous patch \"shallow: handling fetch relative-deepen\"\n\nWhose \"previous patch\" are we talking about in [PATCH 1/1]?\n\nPlease refer to the commit with \"git show -s --format=reference\", if\nyou are talking about a public commit etched in the history.\n\n> introduced a bug where using --deepen=<n> on a non-shallow\n> repository incorrectly treated the value as an absolute depth,\n> resulting in a shallow fetch and truncated history.\n\nThat's unfortunate.\n\nWe obviously should not truncate when asked to \"deepen\" (i.e., the\nuser asked to get more history, not reset the number of commits we\nhave to a specific depth), and making the operation in this\nsituation a no-op may be a good first step, but should we just do so\nsilently, instead of giving a warning/diagnosis?\n\n> This patch prevents any modification when a relative deepen is\n> requested on a non-shallow repository.\n>\n> A test is added to ensure that history is not changed when\n> --deepen is used on a non-shallow repository.\n>\n> Reported-by: Owen Stephens <owen@owenstephens.co.uk>\n> Signed-off-by: Samo Pogačnik <samo_pogacnik@t-2.net>\n"},{"id":"543027","messageId":"ac1aac76-17bc-469b-8dc1-d3a384f5c6af@web.de","threadId":"65565","inReplyTo":"xmqqzf26x0vi.fsf@gitster.g","subject":"Re: [PATCH 1/1] shallow: fix relative deepen on non-shallow repositories","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2026-05-11T07:45:58Z","receivedAt":"2026-05-11T07:46:05Z","isPatch":true,"body":"On 5/11/26 2:09 AM, Junio C Hamano wrote:\n> \n> We obviously should not truncate when asked to \"deepen\" (i.e., the\n> user asked to get more history, not reset the number of commits we\n> have to a specific depth), and making the operation in this\n> situation a no-op may be a good first step, but should we just do so\n> silently, instead of giving a warning/diagnosis?\nPerhaps, but no warning has been given for deepening a non-shallow repo\nsince the introduction of this option by cccf74e2da (fetch, upload-pack:\n--deepen=N extends shallow boundary by N commits, 2016-06-12).\n\nThe best place for such a warning would be close to the user, in fetch,\nno?  And in its own patch.\n\nRené\n\n"},{"id":"543032","messageId":"xmqqy0hqqreq.fsf@gitster.g","threadId":"65565","inReplyTo":"ac1aac76-17bc-469b-8dc1-d3a384f5c6af@web.de","subject":"Re: [PATCH 1/1] shallow: fix relative deepen on non-shallow repositories","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-11T08:30:53Z","receivedAt":"2026-05-11T08:30:59Z","isPatch":true,"body":"René Scharfe <l.s.r@web.de> writes:\n\n> Perhaps, but no warning has been given for deepening a non-shallow repo\n> since the introduction of this option by cccf74e2da (fetch, upload-pack:\n> --deepen=N extends shallow boundary by N commits, 2016-06-12).\n>\n> The best place for such a warning would be close to the user, in fetch,\n> no?  And in its own patch.\n\nYeah, the lack of warning may or may not be considered a bug, but I\nagree that it is totally orthogonal to the problem the patch is\ntrying to address.\n\nThanks.\n"},{"id":"543084","messageId":"20260511192044.169557-1-samo_pogacnik@t-2.net","threadId":"65565","inReplyTo":"xmqqy0hqqreq.fsf@gitster.g","subject":"[PATCH v2] shallow: fix relative deepen on non-shallow repositories","fromName":"Samo Pogačnik","fromEmail":"samo_pogacnik@t-2.net","sentAt":"2026-05-11T19:20:42Z","receivedAt":"2026-05-11T19:21:17Z","isPatch":true,"body":"The commit \"3ef68ff40e (shallow: handling fetch relative-deepen,\n2026-02-15)\" introduced a bug where using --deepen=<n> on a non-\nshallow repository incorrectly treated the value as an absolute\ndepth, resulting in a shallow fetch and truncated history.\n\nThis patch prevents any modification when a relative deepen is\nrequested on a non-shallow repository.\n\nA test is added to ensure that history is not changed when\n--deepen is used on a non-shallow repository.\n\nReported-by: Owen Stephens <owen@owenstephens.co.uk>\nSigned-off-by: Samo Pogačnik <samo_pogacnik@t-2.net>\n---\nChanges since v1:\n- Fixed commit reference in the commit message.\n\n shallow.c                |  6 +++++-\n t/t5537-fetch-shallow.sh | 10 ++++++++++\n 2 files changed, 15 insertions(+), 1 deletion(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex a8ad92e303..610ff3d13b 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -245,7 +245,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads,\n \t\t\t\t\tint depth, int shallow_flag, int not_shallow_flag)\n {\n \tif (shallows && deepen_relative) {\n-\t\tdepth += get_shallows_depth(heads, shallows);\n+\t\tint cur_shallow_depth = get_shallows_depth(heads, shallows);\n+\t\tif (cur_shallow_depth)\n+\t\t\tdepth += cur_shallow_depth;\n+\t\telse\n+\t\t\treturn NULL;\n \t}\n \treturn get_shallows_or_depth(heads, NULL, NULL,\n \t\t\t\t     depth, shallow_flag, not_shallow_flag);\ndiff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh\nindex 6588ce6226..9982dd2aa6 100755\n--- a/t/t5537-fetch-shallow.sh\n+++ b/t/t5537-fetch-shallow.sh\n@@ -251,6 +251,16 @@ test_expect_success '.git/shallow is edited by repack' '\n \t\torigin \"+refs/heads/*:refs/remotes/origin/*\"\n '\n \n+test_expect_success 'fetch --deepen does not truncate' '\n+\tgit clone --no-local .git full-clone &&\n+\tgit -C full-clone rev-parse --is-shallow-repository >expect &&\n+\tgit -C full-clone log --oneline >>expect &&\n+\tgit -C full-clone fetch --deepen=1 &&\n+\tgit -C full-clone rev-parse --is-shallow-repository >actual &&\n+\tgit -C full-clone log --oneline >>actual &&\n+\ttest_cmp expect actual\n+'\n+\n . \"$TEST_DIRECTORY\"/lib-httpd.sh\n start_httpd\n \n-- \n2.43.0\n\n"}]}