Git Submodule

新增一個 Git Submodule

例如我有目前本機有一個 josephj.git、在 /home/josephj/www 下,而我須要將 javascript platform 放到 /home/josephj/www/static/ 能夠用如下幾行快速達成。javascript

  • 切換到個人 repository 目錄:
    $ cd /home/josephj/wwwjava

  • 使用 git submodule add [repository 位置] [欲放置的位置] 增長一個新的 submodule:
    $ git submodule add git@github.com:josephj/javascript-platform-yui.git static/platform須要注意 [欲放置的位置] 不能以 / 結尾(會形成修改不生效)、也不能已經是現有的路徑喔(不能順利 Clone)。git

  • 按下去就會看到如下結果:github

    $ git submodule add git://github.com/josephj/javascript-platform-yui.git static/platform
    Initialized empty Git repository in /home/josephj/www/static/platform/.git/
    remote: Counting objects: 31, done.
    remote: Compressing objects: 100% (31/31), done.
    remote: Total 31 (delta 14), reused 0 (delta 0)
    Receiving objects: 100% (31/31), 6.06 KiB, done.
    Resolving deltas: 100% (14/14), done.

    這時在 /home/josephj/www/ 會產生一個 .gitmodules 記錄你的 Submodule 資訊。該 git 的相關檔案也都會在此時被拉下來vim

  • 用 git status 看一下:安全

    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD..." to unstage)
    #
    #       new file:   .gitmodules
    #       new file:   static/platform
    #

    會發現它只列出 submodule 目錄而非全部底下檔案,parent git 實際上也只會記錄 submodule 的 commit id 以供未來作比對用。這裡一個很重要的點是你們必須理解的:parent git 與 submodule git 的關連性(被掛入的目錄、repository 位置)記錄在 .gitmodules 中,而版本控制則是靠 parent git 記住 submodule git 的 commit id。ui

  • 先 commit 一下:spa

    $ git add .gitmodules static/platform
    git commit -m "Add submodule into version control";
  • 可是你還必須作 init 的動做,你的 .git/config 才會有對應 submodule 的資訊。版本控制

    $ git submodule init

更新已安裝的 Submodule

當初我第一次新增一個 Submodule 後,以為未來它都會像 SVN External 一樣、在我 git pull 的時候自動更新。但實際情況是你必須手動處理才能更新 Submodulecode

  1. 進入該目錄 Subomdule 目錄:$ cd static/platform

  2. 向來源的 master branch 作 git pull 的動做(這裡的 git pull 不會更新你 parent git 的檔案)$ git pull origin master

  3. 若 submodule 有更新的檔案,你能夠到 parent git 觀看一下情況:

    $ cd ../../ 
    $ git status
    # Not currently on any branch.
    # Changed but not updated:
    #   (use "git add..." to update what will be committed)
    #   (use "git checkout --..." to discard changes in working directory)
    #
    #       modified:   static/platform (new commits)
    #
    no changes added to commit (use "git add" and/or "git commit -a")

    與第一次 git submodule add 相同,submodule 更新的檔案並不會在 git status 中要求你 commit 喔!

  4. 我們前面提到,submodule 的版本控制在於 submodule git 的 commit id,上面看到 static/platform 有 new commit。表示你既然把新的內容 pull 回來、應該要更新 submodule 的 commit id 到你的 git 中:

    $ git add static/platform
    $ git commit -m "static/platform submodule updated"

    如此一來,新的 submodule commit id 就被你的 repositiory 給記錄下來囉!

團隊使用 Submodule

在一個多人的軟體開發團隊中,一般還是會有 Centralized Git Repositiory,像我們公司就採用了 gitosis 的解決方案。而像上述更新 Submodule 的情形,一般只有一兩個負責架構的人來作(大可能是一開始把東西掛進來的人)、其餘人只是單純使用者的角色,並不須要負責更新的工做

  1. 像上面我增長了一個 Submodule,對於團隊其餘人來說,他們在下一次的 git pull 會看到如下的狀況:

    $ git status
    # On branch develop
    # Changed but not updated:
    #   (use "git add..." to update what will be committed)
    #   (use "git checkout --..." to discard changes in working directory)
    #
    #       modified:   static/platform (new commits)
    #
    no changes added to commit (use "git add" and/or "git commit -a")

    這表示其餘人也會拿到 .gitmodules 的設定,但他必須使用 git submodule init 將新的 Submodule 註冊到本身的 .git/config、未來才能使用。

    $ git submodule init
    Submodule 'static/platform' (http://github.com/josephj/javascript-platform-yui.git) registered for path 'static/platform'
  2. 接著其餘人使用 git submodule update 把該 Submodule 的內容所有拉下來!

    $ git submodule update
    Cloning into static/platform...
    remote: Counting objects: 34, done.
    remote: Compressing objects: 100% (34/34), done.
    remote: Total 34 (delta 15), reused 0 (delta 0)
    Unpacking objects: 100% (34/34), done.
    Submodule path 'static/platform': checked out '117c5b3c5a195deac2e53aa118b78ef3f01ae371'

使用時機

簡單整理一下:

  • git submodule init: 在 .gitmodules 第一次被其餘人創建或有新增內容的時候,用 git submodule init 更新你的 .git/config、設定目錄與增長 submodule 的 remote URL

  • git submodule update: 在 init 完有新的 submodule commit id 後就能夠作了,會把全部相關檔案拉下來。若其餘人更新 submodule 形成你拿到新的 commit id 時,你能夠直接用 git submodule update 作更新便可、不須要作任何 add 或 commit 的動做!

能夠想見,其餘成員使用 git submodule update 的情況會遠比 git submodule init 多不少。

修改 Submodule 的內容

有時本身也是 Submodule 的 Owner,碰到要改 Code 時,要我切回本來的此 Git 開發位置有點麻煩... 不如就直接改被當成 Submodule 掛進來的原始碼吧

  1. 到 submodule 目錄去作些修改:

    $ cd static/platform
    $ vim README # 作些修改
  2. 接著就是常見的 git add , git commit, git push

    $ git add README
    $ git commit -m "Add comments"
    $ git push
  3. push 完回到根目錄git status 看一下!會看到

    $ git status
    # On branch master
    # Changed but not updated:
    #   (use "git add..." to update what will be committed)
    #   (use "git checkout --..." to discard changes in working directory)
    #
    #       modified:   static/platform
    #
    no changes added to commit (use "git add" and/or "git commit -a")
  4. 這裡也須要再作一次 Commit 喔!

    $ git add static/platform
    $ git commit -m 'Submodule updated'
    $ git push

這裡有一點很是須要注意,因為 Submodule 的更新只記錄 commit id,因此你必須先在 submodule 內作 commit、push 後、再到 parent git 作commit, push,否則會出現版本錯亂的問題,別人跟你 submodule 的內容將會不一致。

如何移除 Submodule

這點也很是地不直覺,不是想像中 git submodule remove [欲移除的目錄] 這麼簡單...

  1. 先砍掉目錄:

    $ git rm --cached [欲移除的目錄]
    $ rm -rf [欲移除的目錄]
  2. 再修改 .gitmodules

    $ vim .gitmodules

    將相關內容移除

  3. 再修改 .git/config

    $ vim .git/config

    將相關內容移除

  4. 最後再 commit,改變整個 Repository。

    $ git add .gitmodules
    $ git commit -m "Remove a submodule"
  5. 安全起見再作個 sync:

    $ git submodule sync
相關文章
相關標籤/搜索