1. Learn Git
    1. Learn Git with Bitbucket Cloud
      1. Create a Git repository
      2. Copy your Git repository and add files
      3. Pull changes from your Git repository on Bitbucket Cloud
      4. Use a Git branch to merge a file
    2. Learn about code review in Bitbucket Cloud
      1. Fork a teammate's repository
      2. Copy your fork and make a change to the repository
      3. Create a pull request
  2. Getting Started
    1. What is version control
      1. Benefits of version control
    2. What is Git
      1. Performance
      2. Security
      3. Flexibility
      4. Version control with Git
    3. Why Git for your organization
      1. Git for developers
      2. Git for marketing
      3. Git for product management
      4. Git for designers
      5. Git for customer support
      6. Git for human resources
      7. Git for anyone managing a budget
    4. Install Git
      1. Install Git on Mac OS X
      2. Install Git on Windows
      3. Install Git on Linux
    5. Setting up a repository
      1. git init
      2. git clone
      3. git config
    6. Saving changes
      1. git add
      2. git commit
    7. Git Stash
      1. .gitignore
        1. Inspecting a repository
          1. git status
          2. git log
        2. Viewing old commits
          1. Undoing Changes
            1. git checkout
            2. git revert
            3. git reset
            4. git clean
          2. Rewriting history
            1. git commit --amend
            2. git rebase
            3. git rebase -i
            4. git reflog
        3. Collaborating
          1. Syncing
            1. git remote
            2. git fetch
            3. git pull
            4. git push
          2. Making a Pull Request
            1. How it works
            2. Example
            3. Where to go from here
          3. Using Branches
            1. git branch
            2. git checkout
            3. git merge
          4. Comparing Workflows
            1. Centralized Workflow
            2. Feature Branch Workflow
            3. Gitflow Workflow
            4. Forking Workflow
        4. Migrating to Git
          1. SVN to Git - prepping for the migration
            1. For administrators
            2. Basic Git commands
            3. Git Migration Tools
            4. For developers
          2. Migrate to Git from SVN
            1. Prepare
              1. Convert
                1. Synchronize
                  1. Share
                    1. Migrate
                      1. Perforce to Git - why to make the move
                        1. Migrating from Perforce to Git
                        2. Advanced Tips
                          1. Advanced Git Tutorials
                            1. Merging vs. Rebasing
                              1. Conceptual Overview
                              2. The Golden Rule of Rebasing
                              3. Workflow Walkthrough
                              4. Summary
                            2. Reset, Checkout, and Revert
                              1. Commit-level Operation
                              2. File-level Operations
                              3. Summary
                            3. Advanced Git log
                              1. Formatting Log Output
                              2. Filtering the Commit History
                              3. Summary
                            4. Git Hooks
                              1. Conceptual Overview
                              2. Local Hooks
                              3. Server-side Hooks
                              4. Summary
                            5. Refs and the Reflog
                              1. Hashes
                              2. Refs
                              3. Packed Refs
                              4. Special Refs
                              5. Refspecs
                              6. Relative Refs
                              7. The Reflog
                              8. Summary
                            6. Git LFS

                            Core Concept, Workflows And Tips

                            Nicola PaolucciNicola Paolucci
                            Back to list

                            Including submodules as part of your Git development allows you to include other projects in your codebase, keeping their history separate but synchronized with yours. It's a convenient way to solve the vendor library and dependency problems. As usual with everything git, the approach is opinionated and encourages a bit of study before it can be used proficiently. There is already good and detailed information about submodules out and about so I won't rehash things. What I'll do here is share some interesting things that will help you make the most of this feature.

                            Table Of Contents

                            1. Core Concept
                            2. Possible Workflows
                            3. Useful Tips Incoming
                            4. How to swap a git submodule with your own fork
                            5. How do I remove a submodule?
                            6. How do I integrate a submodule back into my project?
                            7. How to ignore changes in submodules
                            8. Danger Zone! Pitfalls Interacting with Remotes
                            9. Conclusions

                            Core Concept

                            First, let me provide a brief explanation on a core concept about submodules that will make them easier to work with.

                            Submodules are tracked by the exact commit specified in the parent project, not a branch, a ref, or any other symbolic reference.

                            They are never automatically updated when the repository specified by the submodule is updated, only when the parent project itself is updated. As very clearly expressed in the Pro Git chapter mentioned earlier:

                            When you make changes and commit in that [submodule] subdirectory, the superproject notices that the HEAD there has changed and records the exact commit you’re currently working off of; that way, when others clone this project, they can re-create the environment exactly.

                            Or in other words :

                            [...] git submodules [...] are static. Very static. You are tracking specific commits with git submodules - not branches, not references, a single commit. If you add commits to a submodule, the parent project won't know. If you have a bunch of forks of a module, git submodules don't care. You have one remote repository, and you point to a single commit. Until you update the parent project, nothing changes.

                            Possible Workflows

                            By remembering this core concept and reflecting on it, you can understand that submodule support some workflows well and less optimally others. There are at least three scenarios where submodules are a fair choice:

                            • When a component or subproject is changing too fast or upcoming changes will break the API, you can lock the code to a specific commit for your own safety.

                            • When you have a component that isn't updated very often and you want to track it as a vendor dependency. I do this for my vim plugins for example.

                            • When you are delegating a piece of the project to a third party and you want to integrate their work at a specific time or release. Again this works when updates are not too frequent.

                            Credit to finch for the well-explained scenarios.

                            Useful Tips Incoming

                            The submodule infrastructure is powerful and allows for useful separation and integration of codebases. There are however simple operations that do not have a streamlined procedure or strong command line user interface support.

                            If you use git submodules in your project you either have run into these or you will. When that happens you will have to look the solution up. Again and again. Let me save you research time: Instapaper, Evernote or old school bookmark this page (:D:D) and you will be set for a while.

                            So, here is what I have for you:

                            How to swap a git submodule with your own fork

                            This is a very common workflow: you start using someone else's project as submodule but then after a while you find the need to customize it and tweak it yourself, so you want to fork the project and replace the submodule with your own fork. How is that done?

                            The submodules are stored in .gitmodules:

                            $ cat .gitmodules
                            [submodule "ext/google-maps"]
                            path = ext/google-maps
                            url = git://git.naquadah.org/google-maps.git

                            You can just edit the url with a text editor and then run the following:

                            $ git submodule sync

                            This updates .git/config which contains a copy of this submodule list (you could also just edit the relevant [submodule] section of .git/config manually).

                            Stack Overflow reference

                            How do I remove a submodule?

                            It is a fairly common need but has a slightly convoluted procedure. To remove a submodule you need to:

                            1. Delete the relevant line from the .gitmodules file.
                            2. Delete the relevant section from .git/config.
                            3. Run git rm --cached path_to_submodule (no trailing slash).
                            4. Commit and delete the now untracked submodule files.

                              Stack Overflow reference

                            How do I integrate a submodule back into my project?

                            Or, in other words, how do I un-submodule a git submodule? If all you want is to put your submodule code into the main repository, you just need to remove the submodule and re-add the files into the main repo:

                            1. Delete the reference to the submodule from the index, but keep the files:

                              git rm --cached submodule_path (no trailing slash)
                            2. Delete the .gitmodules file or if you have more than one submodules edit this file removing the submodule from the list:

                              git rm .gitmodules
                            3. Remove the .git metadata folder (make sure you have backup of this):

                              rm -rf submodule_path/.git
                            4. Add the submodule to the main repository index:

                              git add submodule_path
                              git commit -m "remove submodule"

                            NOTE: The procedure outlined above is destructive for the history of the submodule, in cases where you want to retain a congruent history of your submodules you have to work through a fancy "merge". For more details I defer you to this very complete Stack Overflow reference.

                            How to ignore changes in submodules

                            Sometimes your submodules might become dirty by themselves. For example if you use git submodules to track your vim plugins, they might generate or modify local files like helptags. Unfortunately, git status will start to annoy you about those changes, even though you are not interested in them at all, and you have no intention of committing them.

                            The solution is very simple. Open the file .gitmodules at the root of your repository and for each submodule you want to ignore add ignore = dirty, like in this example:

                            [submodule ".vim/bundle/msanders-snipmate"]
                            path = .vim/bundle/msanders-snipmate
                            url = git://github.com/msanders/snipmate.vim.git
                            ignore = dirty

                            Thanks to Nils for the great explanation.

                            Danger Zone! Pitfalls Interacting with Remotes

                            As the Git Submodule Tutorial on kernel.org reminds us there are a few important things to note when interacting with your remote repositories.

                            The first is to always publish the submodule change before publishing the change to the superproject that references it. This is critical as it may hamper others from cloning the repository.

                            The second is to always remember to commit all your changes before running git submodule update as if there are changes they will be overwritten!


                            Armed with these notes you should be able to tackle many common recurring workflows that come up when using submodules. In a future post I will write about alternatives to git submodule.

                            Follow me @durdn and the awesome @AtlDevtools team for more DVCS rocking.