• Using Git Submodules


    NOTE:

    Following content is directly reprinted from http://patrickward.com/2013/01/09/using-git-submodules/, please go to the original website for more details.

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Using Git Submodules

    Author: Patrick Ward

    09 Jan 2013

    I've had mixed feelings about Git submodules for a long time now. But, I haven't found an alternative that I liked very much.

    So, I decided to give submodules another chance the other day and write down some notes on how I've been working with them. I'm using a non-existentexample project here to illustrate the basic process.

    Most of these notes are taken from the Git Submodule Tutorial, and just reordered and reiterated for my own brain here.

    Initializing a Submodule

    Add the submodule from the root of the host repository.

    cd hostproject
    git submodule add git://github.com/bitanical/example.git ./example
    ( comment: git submodule tracking branch
    git submodule add -b branchName
    git://github.com/bitanical/example.git example/
    )
    • clones the submodule repository into the current directory
    • by default checks out the master branch of the submodule repository
    • adds the submodule's clone path to the ".gitmodules" file
    • adds the ".gitmodules" file to the index, ready to be committed
    • adds the submodules' current commit ID to the index, ready to be committed

    At this point, the submodule has been added as a regular checkout within the host repository. As soon as you commit the changes to the host repository and push those changes to the origin repository, the submodule becomes available to other clones of that project.

    git commit -m "Add submodule example"
    git push
    git submodule init

    It's also important to realize that a submodule reference within the host repository is not a reference to a specific branch of that submodule's project, it points directly to a specific commit (or SHA1 reference), it is not a symbolic reference such as a branch or tag. In technical terms, it's a detached HEADpointing directly to the latest commit as of the submodule add. This will be important to understand when updating a submodule and pushing any changes made to it back up the chain.

    Cloning a Project With a Submodule

    Now that the project has the submodule reference, other users can clone that project into their distributed copies of the host repository.

    git clone git://gihub.com/bitanical/hostproject.git
    cd hostproject
    ls -la
    .
    ..
    .git
    .gitsubmodules
    example
    readme.md

    When you check out the host project, the submodule directory is created as well, but you will immediately notice that the submodule directory is empty. Even though the submodule reference is known, cloned projects must still initialize and clone the submodule repository.

    First initialize the submodule, to add the submodule URLs to .git/config.

    git submodule init

    Next, update the submodule, essentially cloning it's contents into the submodule directory.

    git submodule update

    One major difference between "submodule update" and "submodule add" is that "update" checks out a specific commit, rather than the tip of a branch. It's like checking out a tag: the head is detached, so you're not working on a branch.

    A shortcut to the preceding steps is to clone the project with the --recursive option, essentially initializing and updating any submodules after the host repository has been cloned.

    git clone git://gihub.com/bitanical/hostproject.git --recursive

    At this point, the project has full use of it's own files along with the cloned submodule files.

    Making Changes Within a Submodule and Checking Them In

    Making a change within a submodule can be a bit tricky, but if you're careful with the order of the steps you take, it can be relatively painless.

    The first, and most important, step when making a change within a submodule is to check out a branch within the submodule first. For example, git checkouot master. Remember, normal submodule references are in a detached HEAD state and not associated with an branches, so checking out a branch first gives you a true reference point to work with.

    git branch
    * (no branch)
      master

    So, checkout a branch (e.g. master):

    git checkout master

    Make your changes within this checked out state. Then, commit those changes to the submodule and push them to the submodule's origin repository before doing anything further with your host repository.

    git commit -a -m "Updated submodule from within hostproject"
    git push

    Now, you can update the host repository, commit the changes and push those updates to the host repositories origin. Remember, in this case, we're using example as the name of the submodule directory.

    cd ..
    git add example # Make sure you don't add a forward slash
                    # after the name of the submodule folder
    git commit -m "Updated submodule example"
    git show        # to show the changes
    git push

    Updating Cloned Projects

    If you've made a change to the submodule and have updated the host project's submodule reference, other cloned versions of the host repository will need to update their own submodule references. Simply pull the changes from the origin and run the submodule update command to retrieve the latest versions.

    cd hostproject
    git pull
    git submodule update

    Working With Git Submodules Recursively

    There are times when you need to apply a particular command to each submodule individually. For that, git-submodule provides the foreachcommand, which can be useful for updating and initializing multiple submodules at once.

    git submodule foreach submodule update --init

    Pulling Submodule Changes

    Sometimes you need to pull in the changes to a submodule and make sure the host repository points to the updated code.

    cd hostproject
    cd example           # cd into the submodule directory
    git checkout master  # make sure you in a valid branch
    git pull
    cd ../               # get back into the host repository
    git add example      # add the changes (essentially changes the SHA1 that the host repo points to)
    git commit -m "Updating submodule example"
    git push

    Change the Remote URL for a Submodule

    I've found that I need to sometimes change a submodule from within a host repository so that I can push updates back to the submodule project. For example, public submodules on GitHub use thegit://github.com/bitanical/example.git url format, but GitHub doesn't support pushing changes back to the origin via the git:// url regardless of your commit privileges. In these cases, I find I have to delete the origin and add it back with a URL I can push to:

    cd example
    git remote rm origin
    git remote add origin git@github.com:bitanical/example.git
    git remote -v

    Next, add the branch information back to the config:

    git config branch.master.remote origin
    git config branch.master.merge refs/heads/master

    Initialize a Submodule With a Different URL

    You can bypass the steps in the preceding tip, by intializing the submodule with a different URL. This lets you start with a submodule that you can, for example, push changes back to.

    So, rather than doing the usual git submodule init && git submodule update flow, you substitute the init step by explicitly stating the remote url in a config command.

    The following steps illustrate the steps used in cloning a host repository with a submodule, and then initializing the remote url with one that differs from the one set in host repository's .gitmodules file.

    git clone https://github.com/bitanical/hostproject.git
    cd hostproject
    git config submodule.example.url git@github.com:patrickward/example.git
    git submodule update
    cd example
    git remote show origin

    Removing a Submodule

    As of this writing, there is no built-in method for removing a submodule within Git. So, it takes a few steps to complete, but they are relatively painless. The following steps illustrate the process (in the context of our example repo).

    Delete the relevant section from the .gitmodules file

    # Remove the submodule section pertaining to example.git
    [submodule "example"]
            path = example
            url  = git://github.com/bitanical/example.git

    Delete the relevant section from the .git/config file

    # Remove the submodule seciton pertaining to example.git
    [submodule "example"]
            url  = git://github.com/bitanical/example.git

    Remove any cached directory information (do not add a trailing slash in the directory name)

    git rm --cached example

    Commit the host repository:

    git commit -m "Removing submodule example"

    Now, delete any untracked submodule files

    rm -Rf example/

    References

    Here are some useful references regarding git submodules that I used to understand how they work:

  • 相关阅读:
    2020-10-24;我对机器学习实现的理解
    2020软件工程作业03
    友链
    导航页
    POJ3694 Network (板子题)
    洛谷 P1084 [NOIP2012 提高组] 疫情控制
    AcWing 355. 异象石
    洛谷P4556 雨天的尾巴
    POJ1639 Picnic Planning (K度限制最小生成树)
    POJ2728 Desert King
  • 原文地址:https://www.cnblogs.com/cindy-hu-23/p/5102027.html
Copyright © 2020-2023  润新知