[git] Git submodule head 'reference is not a tree' error

I have a project with a submodule that is pointing to an invalid commit: the submodule commit remained local and when I try to fetch it from another repo I get:

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

I know what the submodule HEAD should be, is there any way I can change this locally, without pushing from the repo that does have commit 2d7cfbd09fc96c04c4c41148d44ed7778add6b43 ?

I'm not sure if I'm being clear... here's a similar situation I found.

This question is related to git git-submodules

The answer is


This answer is for users of SourceTree with limited terminal git experience.

Open the problematic submodule from within the Git project (super-project).

Fetch and ensure 'Fetch all tags' is checked.

Rebase pull your Git project.

This will solve the 'reference is not a tree' problem 9 out of ten times. That 1 time it won't, is a terminal fix as described by the top answer.


Your submodule history is safely preserved in the submodule git anyway.

So, why not just delete the submodule and add it again?

Otherwise, did you try manually editing the HEAD or the refs/master/head within the submodule .git


Your branch may not be up to date, a simple solution but try git fetch


To sync the git repo with the submodule's head, in case that is really what you want, I found that removing the submodule and then readding it avoids the tinkering with the history. Unfortunately removing a submodule requires hacking rather than being a single git command, but doable.

Steps I followed to remove the submodule, inspired by https://gist.github.com/kyleturner/1563153:

  1. Run git rm --cached
  2. Delete the relevant lines from the .gitmodules file.
  3. Delete the relevant section from .git/config.
  4. Delete the now untracked submodule files.
  5. Remove directory .git/modules/

Again, this can be useful if all you want is to point at the submodule's head again, and you haven't complicated things by needing to keep the local copy of the submodule intact. It assumes you have the submodule "right" as its own repo, wherever the origin of it is, and you just want to get back to properly including it as a submodule.

Note: always make a full copy of your project before engaging in these kinds of manipulation or any git command beyond simple commit or push. I'd advise that with all other answers as well, and as a general git guideline.


Possible cause

This can happens when:

  1. Submodule(s) have been edited in place
  2. Submodule(s) committed, which updates the hash of the submodule being pointed to
  3. Submodule(s) not pushed.

e.g. something like this happened:

$ cd submodule
$ emacs my_source_file  # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"

Should have submodule pushed at this point.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master

As a result, the missing commits could not possibly be found by the remote user because they are still on the local disk.

Solution

Informa the person who modified the submodule to push, i.e.

$ cd submodule
$ git push

This may also happen when you have a submodule pointing to a repository that was rebased and the given commit is "gone". While the commit may still be in the remote repository, it is not in a branch. If you can't create a new branch (e.g. not your repository), you're stuck with having to update the super project to point to a new commit. Alternatively you can push one of your copies of the submodules elsewhere and then update the super-project to point to that repository instead.


Just to be sure, try updating your git binaries.

GitHub for Windows has the version git version 1.8.4.msysgit.0 which in my case was the problem. Updating solved it.


try this:

git submodule sync
git submodule update

Just stumbled upon this problem, and none of these solutions worked for me. What turned out to be the solution for my issue is actually much simpler: upgrade Git. Mine was 1.7.1, and after I upgraded it to 2.16.1 (latest), the problem went away without a trace! Guess I'm leaving it here, hope it helps someone.


This error can mean that a commit is missing in the submodule. That is, the repository (A) has a submodule (B). A wants to load B so that it is pointing to a certain commit (in B). If that commit is somehow missing, you'll get that error. Once possible cause: the reference to the commit was pushed in A, but the actual commit was not pushed from B. So I'd start there.

Less likely, there's a permissions problem, and the commit cannot be pulled (possible if you're using git+ssh).

Make sure the submodule paths look ok in .git/config and .gitmodules.

One last thing to try - inside the submodule directory: git reset HEAD --hard


I got this error when I did:

$ git submodule update --init --depth 1

but the commit in the parent project was pointing at an earlier commit.

Deleting the submodule folder and running:

$ git submodule update --init

did NOT solve the problem. I deleted the repo and tried again without the depth flag and it worked.

This error happens in Ubuntu 16.04 git 2.7.4, but not on Ubuntu 18.04 git 2.17, TODO find exact fixing commit or version.


In my case, none of answer above solve the problem even thoungh they are good answers. So I post my solution (in my case there are two git clients, client A and B):

  1. go to submodule's dir:

    cd sub
    
  2. checkout to master:

    git checkout master
    
  3. rebase to a commit code which both client can see

  4. go back to the parent's dir:

  5. commit to master

  6. change to the other client, do rebase again.

  7. finally it works fine now! Maybe lose a couple of commits but it works.

  8. FYI, don't try to remove your submodule, it will remain .git/modules there and cannot readd this submodule again, unless reactive local one.