mrbone / mrbone.github.io

0 stars 0 forks source link

git submodules #103

Closed mrbone closed 6 years ago

mrbone commented 6 years ago

创建此卡的目的

深入了解 git submodules

简单的描述

验收点

mrbone commented 6 years ago

Git Submodule

Git submodule 的功能是允许通过在一个 repo 中引入其他 repo 的方式,算是一种比较独特的让 repo 管理依赖的方式。

示例

使用 git submodule add 添加 一个 repo 为当前 repo 的依赖。

git submodule add https://github.com/chaconinc/DbConnector

默认情况下, submodules 会在当前目录下添加一个和 submodule repo 同名的文件夹。在上面那个例子是 DbConnector。如果你想自定义文件目录则可以在后面接自定义的 path

这个时候使用 git status,我们会发现:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   .gitmodules
    new file:   DbConnector

.gitmodules 是一个保存 submodules 配置的文件,它保存了 subdirectory 到 git url 的 map。

[submodule "DbConnector"]
    path = DbConnector
    url = https://github.com/chaconinc/DbConnector

而当我们在外面使用 git status 的时候,会发现 DbConnector 的 contnent 并不会被 track。

当我们重新 clone 整个 repo 的时候,我们会发现 DbConnector 文件夹是空的,只有我们使用 git submodule init && git submodule update 之后才会把远程 repo 的代码拉下来。或者我们需要在 clone 命令后面加 --recurse-submodule

远程 repo 更新 submodule

如果远程 repo 更新了,那么直接进入 submodule 使用 git fetch && git merge origin/master 则可以完成更新。

我们也可以在当前工程使用 git submodule update 更新 sbumodule,但是 submodule 的 branch 会切换到一个 deteched HEAD。这样做的意义是表示本地不会有一个 工作分支 来追踪变化。也就是说如果你在这个分支上做了任何修改,那么你下次执行 git submodule update 的时候这些更改同样会丢失,如果你想保存这些更改则需要做额外两个步骤:

  1. 进入每一个 submodule 为其切换到一个工作分支。
  2. 显示告知 git 当本地和远端 submodule 同时有修改的时候如何处理本地变更,是使用 mrege 还是 rebase。
$ git checkout stable
Switched to branch 'stable'

$ git submodule update --remote --merge/rebase

如果没有使用 --merge 或者 --rebase,那么 git 会直接更新 submodule 和远端一致,并且再一次把 submodule 分支切换到 detached HEAD

如果发生了这样的情况,不用着急,只需要将 submodule 分支切回到之前的工作分支,然后做一次 merge/rebase origin/stable 即可把本地修改和远端更新同时保存到当前工作分支,因为每次 git submodule update --remote 的时候都是将更新放到了 detached HEAD 分支。

在当前工程更新 submodule

当本地工程有 submodule 有更新,我们这个时候如果直接退回到工程目录直接添加变更并且 push 的话,其他人员拉取 project 的时候会出现问题,因为 submodule 的变更只有我们本地才有。

为了让这种情况不发生,我们可以配置 git 在 push 主 project 之前先检查所有的 submodule 是否已经正确 push 了。

git push 接受 --recurse-submodules 参数,这个参数的值有如下:

$ git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
  DbConnector

Please try

    git push --recurse-submodules=on-demand

or cd to the path and use

    git push

to push them to a remote.
$ git push --recurse-submodules=on-demand
Pushing submodule 'DbConnector'
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 3), reused 0 (delta 0)
To https://github.com/chaconinc/DbConnector
   c75e92a..82d2ad3  stable -> stable
Counting objects: 2, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 266 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To https://github.com/chaconinc/MainProject
   3d6d338..9a377d1  master -> master