Search code examples
gitgit-submodulesgit-clone

Cloning local Git repository containing a submodule with local branch


I added a submodule to my local git repository (GUI library for an embedded project.) I needed to add a couple of driver files for my hardware and added them to a local dev branch: these changes are not pushed back to the remote. My plan was to pull in changes to the master branch from the remote occasionally, then rebase my dev branch on top of those changes.

The problem arose when I tried to make a local clone of this local repository, using:

git clone --recursive local_repo local_clone

I get

fatal: reference is not a tree: ca025c09ca2b7b82ca086309eeb0696d674cb1d0
Unable to checkout 'ca025c09ca2b7b82ca086309eeb0696d674cb1d0' in submodule path 'uGFX/ugfx_submodule'

This particular commit is on my local dev branch (and definitely not on the submodule's remote server.)

Is there an easy way to clone the local repository? (other than a cp -r =)


Solution

  • At the risk of committing the faux pas of answering my own question, I did come up with a workable solution very late last night ...

    What I wanted is based somewhat on Triangular Workflow, my requirements being:

    1. I need to get code from the uGFX Bitbucket repository's master branch, and be able to pull in changes from that branch when available, and integrate them into my product after testing
    2. I need to be able to add code to the uGFX tree and keep these additions under source control, but not push them back to the uGFX repository (my code is specific to my project and proprietary h/w, trust me, they don't want it. =)
    3. Other users must be able to clone my repository. They don't have to be able to update the uGFX tree with the Bitbucket changes (I will handle when those changes are integrated), although they could if they made minor modifications to their repository.

    My solution involves a version of Triangular Workflow, using an upstream repository as VonC mentioned. Here are the specifics for my solution: (which you may possibly be able to modify to meet your needs)

    • Create an upstream Git server. I used a Raspberry Pi and put the repos on a USB stick, because it was convenient, starting with this article, although I did some extra steps from the Git book where I added a git user, some authorized public ssh keys, etc...
    • Make two bare repositories on the Git server, for this example call them myproduct.git and myproduct_ugfx.git
    • Push my repository's master branch to the myproduct.git repository. I didn't write this part down, but I think I just added a remote for origin and pushed master:

      git remote add origin git@pi-b:/mnt/git_repos/myproduct.git git push

    • From the top directory of my repository, add the uGFX submodule

      git submodule add https://bitbucket.org/Tectu/ugfx.git ugfx_submodule

    • cd into the submodule's directory, and change the name of the submodule's master branch to updates

      git branch -m master updates

    • Rename the remote origin to bitbucket, which the updates branch (formerly master) tracks

      git remote rename origin bitbucket

    • At this point, run git branch -vv just as a check, and it should show one branch (updates) which tracks remote bitbucket's master branch

    • Now your submodule no longer has a master branch or origin. I wanted the submodule master branch to track my Pi Git server's repository, so I add a remote for origin, create a master branch, and push the master branch to the server (telling it to track that branch):

      git remote add origin git@pi-b:/mnt/git_repos/myproduct_ugfx.git git checkout -b master git push -u origin master

    • Now that I've pushed the submodule to my server, I change the uGFX submodule to point to my server, so when people clone the whole repo with --recursive, they get my updates

      git config remote.origin.url git@pi-b:/mnt/git_repos/myproduct_ugfx.git

    At this point, I wanted to add a few files to the uGFX tree. I add them to the master branch, commit, then push (which goes to the Pi repository.) Remember to also go up a direcotry, outside of the submodule, run 'git submodule sync' (not sure if that's necessary), and then commit+push those changes to the main/outer repo.

    Now, when there are changes on the Bitbucket repository, I can pull them into the updates branch, then when I've tested them and want to integrate them into the my product, I can merge them with master and push them to the Pi repository with a simple git push.

    If someone wants to clone the myproduct repository from the Pi, provided they have access to the Pi (see Git book for adding an ssh key) they can do it with

    git clone --recursive git@pi-b:/mnt/git_repos/myproduct.git