{"thread":{"id":"61437","subject":"[BUG] fetch error when arbitrary branch changes a submodule url","startedAt":"2024-05-08T23:53:15Z","lastAt":"2024-05-08T23:53:15Z","messageCount":1,"participants":["Martin Veilleux"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"494337","messageId":"8c53a956-13e9-4c7e-9359-2c86c9dd9908@gameloft.com","threadId":"61437","inReplyTo":null,"subject":"[BUG] fetch error when arbitrary branch changes a submodule url","fromName":"Martin Veilleux","fromEmail":"martin.veilleux@gameloft.com","sentAt":"2024-05-08T23:45:03Z","receivedAt":"2024-05-08T23:53:15Z","isPatch":false,"sender":{"key":"martin.veilleux@gameloft.com","avatar":null},"body":"issue: fetch will give a fatal error once when a new arbitrary branch on \nthe remote contains a submodule url change with updated sha\n\nThis was an issue I originally opened on git-for-windows a while back. \n(https://github.com/git-for-windows/git/issues/3404)\n\nBut it's actually reproducible on Linux\n\nSeems to be a regression since I could not repro on version 1.9\n\nIssue still present on version 2.45.0.31.gd4cc1ec35f\n\nLocal repro steps (complete test script attached)\n- create repo A with a commit on master\n- create repo B with a commit on master\n- create repo X and add a submodule S1 pointing to A, commit to master.\n- clone repo X with submodules to repo Z\n- in repo X, create branch X1 from master. Change submodule S1 url to \nrepo B and commit on X1.\n- in repo Z, fetch and notice the fatal error \"upload-pack: not our ref SHA\"\n\n From there, you can then quickly repro the error like so:\n- in repo Z , delete branch origin/X1 and then fetch again.\n\nCurrent workaround is to set submodule.recurse to false\n\n-- \n\nMartin\n\n\n#!/bin/bash\n\ndie()\n{\n    echo \"FATAL program error\"\n    exit 1\n}\n\ngitTry()\n{\n    echo \"git $*\"\n    git $*\n}\n\ngitNoFail()\n{\n    echo \"git $*\"\n    git $* || die\n}\n\ncreateRepo()\n{\n    local name=$1\n    [[ -n \"$name\" ]] || die\n    mkdir $name || die\n    pushd $name >/dev/null\n    pwd\n    gitNoFail init\n    echo line1>readme.txt\n    gitNoFail add readme.txt\n    gitNoFail commit -m first\n    popd >/dev/null\n    echo \"created git repo '$name'\"\n}\n\nprintHeader()\n{\n    echo \"==============================================================\"\n    if [[ -n \"$1\" ]]; then\n        echo \"$1\"\n        echo \"==============================================================\"\n    fi\n}\n\nsetupEnv()\n{\n    if [[ -n \"$GIT_PATH\" ]]; then\n        [[ -e \"$GIT_PATH/git\" ]] || die\n        echo \"user provided custom git in ${GIT_PATH}\"\n        export PATH=\"${GIT_PATH}:${PATH}\"\n        gitNoFail --version\n    fi\n}\n\nmain()\n{\n    setupEnv\n    local root=$(pwd)\n    rm -rf child{1,2} user1 server1\n    local gitArgs=\"-c protocol.file.allow=always\"\n    #create submodule repos\n    printHeader \"create submodule repo 1\"\n    createRepo child1\n    printHeader \"create submodule repo 2\"\n    createRepo child2\n    #workaround for identical initial SHA (is this a bug?)\n    pushd child2 >/dev/null\n    touch foobar\n    gitNoFail add foobar\n    gitNoFail commit -m second\n    popd >/dev/null\n\n    #create a repo intended as the server repo that all users clone from\n    printHeader \"setup server repo\"\n    createRepo server1\n    #add submodule\n    pushd server1 >/dev/null\n    gitNoFail ${gitArgs} submodule add -b master \"${root}/child1\" sub1\n    gitNoFail commit -m added_submodule\n    popd >/dev/null\n    \n    #a user clones from server\n    printHeader \"setup user repo\"\n    gitNoFail ${gitArgs} clone --recurse-submodules server1 user1\n\n    #change a submodule url in an arbitrary branch. This branch would have been pushed to the server by another user.\n    printHeader \"switch submodule url\"\n    pushd server1 >/dev/null\n    pwd\n    gitNoFail checkout -b exper\n    gitNoFail config --file=.gitmodules submodule.sub1.url \"${root}/child2\"\n    gitNoFail ${gitArgs} submodule sync -- sub1\n    gitNoFail ${gitArgs} submodule update --remote -- sub1\n    gitNoFail add --all\n    gitNoFail commit -m switch_submodule_url\n    popd >/dev/null\n\n    #now user will update\n    pushd user1 >/dev/null\n    printHeader \"user updates\"\n    pwd\n    #this will give an error, but shouldn't\n    gitTry fetch\n\n    #test again\n    printHeader \"try again\"\n    gitNoFail branch -r -D origin/exper\n    gitTry fetch\n\n    #test workaround\n    printHeader \"workaround\"\n    gitNoFail branch -r -D origin/exper\n    gitNoFail config submodule.recurse false\n    gitNoFail fetch\n\n    popd >/dev/null\n}\n\nmain $@\n\n"}]}