git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Unable to de-init stubborn submodule

From
Stefan Beller <sbeller@google.com>
Date
Jan 11, 2018, 18:17 UTC
Message-ID
<CAGZ79kajv9Pf4qc_1wgDD=NTimT1Ss7Wz-8fNNbmkgLO40VVGg@mail.gmail.com>
In-Reply-To
<87k1woa3i9.fsf@evledraar.gmail.com>

On Thu, Jan 11, 2018 at 6:12 AM, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:

Show 10 quoted lines
> What if we wanted to drop sha1collisiondetection/ as a submodule and
> replace it with a copy of what's now in sha1dc/? I ran into this with
> another project, but here's a way to reproduce it on git.git:
>
>     (
>         rm -rf /tmp/git &&
>         git clone git@github.com:git/git.git /tmp/git
>         cd /tmp/git &&
>         git tag nuke-before &&
>         git submodule update --init &&
At this point
    $ tail -n 3 .git/config
    [submodule "sha1collisiondetection"]
        active = true
        url = https://github.com/cr-marcstevens/sha1collisiondetection.git
>         git rm -r .gitmodules sha1collisiondetection &&

no need to delete the .gitmodules here. Git detects you're deleting a submodule and adjusts the .gitmodules file (it is empty after just "git rm sha1coll...")

Show 6 quoted lines
>         git commit -m"Nuke sha1dc submodule" &&
>         cp -Rvp sha1dc sha1collisiondetection &&
>         git add sha1collisiondetection &&
>         git commit -m"Now it's not a submodule" &&
>         git tag nuke-after &&
>         git reset --hard nuke-before &&

As bmwill said, you may want to reset with --recurse-submodules here, "git ls-tree HEAD |grep sha1c" will show commit and "git status" thinks everything is fine on disk. I have no suspicion to believe otherwise. But we digress, you chose to not use that flag.

>         git submodule update --init && # skip this and the below won't fail
>         git reset --hard nuke-after && # Emulate someone doing a pull

$ git reset --hard nuke-after warning: unable to rmdir 'sha1collisiondetection': Directory not empty HEAD is now at f683a1b81 Now it's not a submodule $ git reset --hard nuke-after --recurse-submodules HEAD is now at f683a1b81 Now it's not a submodule

Show 13 quoted lines
>         git ls-tree HEAD | grep sha1collisiondetection && # OK, shows "tree" not "commit"
>         test $(git rev-parse HEAD) == $(git -C sha1collisiondetection/ log -1 --pretty=format:%H) && echo OK || echo WTF
>     )
>
> This results in a really bizarre state where according to ls-tree
> sha1collisiondetection is a tree at the current commit:
>
>     040000 tree 81583289d96bdde4b366c243ab524ea28d895ea5    sha1collisiondetection
>
> But git still believes there's a submodule there for some reason, and
> shows the log for the upstream sha1collisiondetection project:
>
>     git -C sha1collisiondetection/ log -1

(A) That is because the reset without flag do touch submodules kept the submodule in place and the -C in this command tells git to cd into that directory, (which is the submodule, an 'independent' repo) and shows the log of said repo.

Show 12 quoted lines
>     commit 19d97bf (HEAD, origin/master, origin/HEAD, master)
>     Merge: 3f14d1b c93f0b4
>     Author: Dan Shumow <shumow@gmail.com>
>     Date:   Sat Jul 1 12:36:15 2017 -0700
>
>         Merge pull request #37 from avar/fixup-pull-request-34
>
>         Fix endian detection logic for Sparc, little endian BSD etc.
>
> Doing:
>
>     git submodule deinit sha1collisiondetection

Doing this after you reset to nuke-after, there are no submodules from the superprojects point of view, hence no submodule is touched/modified. :/ (There just happens to be a stray repository at a place where we'd want to have a tree).

Show 9 quoted lines
> Does nothing to help, then I thought it might be:
>
>     git config -f .git/config -l|grep ^submodule
>     submodule.sha1collisiondetection.active=true
>     submodule.sha1collisiondetection.url=https://github.com/cr-marcstevens/sha1collisiondetection.git
>
> But running:
>
>     git config --remove-section submodule.sha1collisiondetection

This made the submodule not active any more, (note that at the current tree there is no submodule to begin with... so what effect to we want here?)

Show 8 quoted lines
> Doesn't help either, neither does removing the index:
>
>     rm .git/index &&
>     git reset --hard
>
> If you then do:
>
>     rm -rf .git/modules
Getting out the big hammer, eh?
instead of deleting the submodules git repo, remove its worktree:
    rm -rf sha1collisiondetection
(This is best done at time (A) above)
Show 7 quoted lines
>
> You'll get this error:
>
>     git -C sha1collisiondetection/ log -1
>     fatal: Not a git repository: /tmp/git/sha1collisiondetection/../.git/modules/sha1collisiondetection
>
> But I can't see what's still referencing it.

$ls -la /tmp/git/sha1collisiondetection ... -rw-r--r-- 1 sbeller eng 47 Jan 11 10:02 .git ... $ cat sha1collisiondetection/.git gitdir: ../.git/modules/sha1collisiondetection

This is a crucial file, telling you there is a repo with the worktree at the place where .git lives and the git dir is at the location indicated (which you removed)

Show 9 quoted lines
> This problem is avoided if, as noted with a comment I skip:
>
>     git submodule update --init
>
> But I shouldn't need to remember to de-init a submodule before moving to
> a new commit that doesn't have it, least I end up in some seemingly
> unrecoverable state.
>
> Am I missing something obvious here?

The "git submodule update/init/deinit" is a "raw" command, (not to be confused with plumbing, I just made up "raw commands" ;) that is very good to deal with submodules, but that tool has sharp edges. Try this:

  $ git clone --recurse-submodules=. git@github.com:git/git.git testgit
  $ cd testgit/
  $ git config --list |grep submod
submodule.active=.
submodule.sha1collisiondetection.url=https://github.com/cr-marcstevens/sha1collisiondetection.git
  $ git config submodule.recurse true
  $ git tag before-nuke
  $ git rm sha1collisiondetection/
  rm 'sha1collisiondetection'
  $ git commit -a -m delete_sub
  $ git tag after-nuke
  $ git checkout before-nuke
  $ git status # and more checks
  $ git checkout after-nuke
  $ git status # and more checks
Previous: Brandon Williams
Message 3 of 3 in “Unable to de-init stubborn submodule”
  1. Ævar Arnfjörð BjarmasonJan 11, 2018
  2. Brandon WilliamsJan 11, 2018
  3. Stefan BellerJan 11, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.