我正在寻找一种具有git结构(可能嵌套子模块)的情况。对于这些子模块中的每个子模块,我想分别指定它们是否应跟踪分支(例如,参见Git子模块:指定一个分支/标签)。
例如,我的项目可能如下所示:
main.tex
|- submod1 @ master
| |-subsubmod1 @qsdf123
|- submod2 @ master
| |-subsubmod2 @shasha12
|- submod3 @ qsdf321
现在,我想要一种更新子模块的方法。
git submodule update --recursive
会将所有子模块更新到其最后记录的sha(即,它将适用于subsubmod1,subsubmod2和submod3,但对其余子模块执行错误的操作。
git submodule update --recursive --remote
会将所有子模块更新到关联的分支(默认情况下为master),即它将对submod1和submod2起作用,但对其余子模块却做错了。
有没有办法很好地做到这一点?
针对第一个答案,我将澄清“做错事情”的意思。
这是一个小例子
bartb@EB-Latitude-E5450 ~/Desktop/test $ git init
Initialized empty Git repository in /home/bartb/Desktop/test/.git/
bartb@EB-Latitude-E5450 ~/Desktop/test $ git submodule add ../remote/ submod1
Cloning into 'submod1'...
done.
bartb@EB-Latitude-E5450 ~/Desktop/test $ git submodule add ../remote/ submod2
Cloning into 'submod2'...
done.
bartb@EB-Latitude-E5450 ~/Desktop/test $ cd submod1
bartb@EB-Latitude-E5450 ~/Desktop/test/submod1 $ git log
commit 42d476962fc4e25c64ff2a807d2bf9b3e2ea31f8
Author: Bart Bogaerts <[email protected]>
Date: Tue Jun 21 08:56:05 2016 +0300
init commit
commit db1ba3bc4b02df4677f1197dc137ff36ddfeeb5f
Author: Bart Bogaerts <[email protected]>
Date: Tue Jun 21 08:55:52 2016 +0300
init commit
bartb@EB-Latitude-E5450 ~/Desktop/test/submod1 $ git checkout db1ba3bc4b02df4677f1197dc137ff36ddfeeb5f
Note: checking out 'db1ba3bc4b02df4677f1197dc137ff36ddfeeb5f'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at db1ba3b... init commit
bartb@EB-Latitude-E5450 ~/Desktop/test/submod1 $ cd ..
bartb@EB-Latitude-E5450 ~/Desktop/test $ git config -f .gitmodules submodule.submod2.branch master
bartb@EB-Latitude-E5450 ~/Desktop/test $ git commit -a -m "modules"
[master (root-commit) ea9e55f] modules
3 files changed, 9 insertions(+)
create mode 100644 .gitmodules
create mode 160000 submod1
create mode 160000 submod2
bartb@EB-Latitude-E5450 ~/Desktop/test $ git status
On branch master
nothing to commit, working directory clean
bartb@EB-Latitude-E5450 ~/Desktop/test $ git submodule update --recursive --remote
Submodule path 'submod1': checked out '42d476962fc4e25c64ff2a807d2bf9b3e2ea31f8'
bartb@EB-Latitude-E5450 ~/Desktop/test $ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: submod1 (new commits)
如您所见,git submodule update --remote
即使我从未为其配置master分支,也可以在master上检出最新的submod1之后。我的意思是“做错事”
子子模块也发生同样的事情:它们都是在主节点而不是在特定的提交时检出的。
这个“问题”实际上是预期的git submodule update --remote
。从git文档中:
This option is only valid for the update command. Instead of using the superproject’s recorded SHA-1 to update the submodule, use the status of the submodule’s remote-tracking branch. The remote used is branch’s remote (branch.<name>.remote), defaulting to origin. The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
https://git-scm.com/docs/git-submodule
特别是部分:
The remote branch used defaults to master
这就是我要避免的。
编辑:另一个请求是:我不想对子模块或子子模块(这些是联合项目)进行任何修改。
2020年更新:
该OP BartBog报告中评论:
当前(2016)的答案在子子模块上不能很好地工作(不再吗?),因为
$top/.gitmodules
它不包含子子模块(和子子子模块)的分支信息。
新解决方案:
export top=$(pwd) git submodule foreach 'b=$(git config -f ${top}/.gitmodules submodule.${path}.branch); \ case "${b}" in \ "") git checkout ${sha1}; git su ;; *) git checkout ${b}; git pull origin ${b}; git su;; esac')
这里
git-su
是我的脚本的名称
2016年原始答案:
会将所有子模块更新到关联的分支(默认情况下为master),即它将对submod1和submod2起作用,但对其余子模块却做错了。
实际上,是的,它将做“其余的事情”。
我将在下面的示例中使用git版本2.9.0.windows.1。来说明该错误(一个parent
带有子模块' sub
'的存储库,本身带有一个子模块' subsub
')。
而且,我将提出一个允许sub
遵循的简单解决方法master
,同时确保subsub
自己不会被检出master
。
让我们subsub
通过两个提交进行回购:
vonc@VONCAVN7 D:\git\tests\subm
> git init subsub1
Initialized empty Git repository in D:/git/tests/subm/subsub1/.git/
> cd subsub1
> git commit --allow-empty -m "subsub c1"
[master (root-commit) f3087a9] subsub c1
> git commit --allow-empty -m "subsub c2"
[master 03d08cc] subsub c2
让我们将该仓库subsub
作为另一个仓库' sub
'的子模块:
vonc@VONCAVN7 D:\git\tests\subm
> git init sub
Initialized empty Git repository in D:/git/tests/subm/sub/.git/
> cd sub
> git submodule add -- ../subsub
Cloning into 'D:/git/tests/subm/sub/subsub'...
done.
默认情况下,该子模块' subsub
'在其自己的master
HEAD处签出(gl
是git log
漂亮格式的别名):
vonc@VONCAVN7 D:\git\tests\subm\sub\subsub
> gl
* 03d08cc - (HEAD -> master, origin/master, origin/HEAD) subsub c2 (4 minutes ago) VonC
* f3087a9 - subsub c1 (4 minutes ago) VonC
让我们确保sub
已在subsub
签出c1
(不是 master HEAD C2
):
vonc@VONCAVN7 D:\git\tests\subm\sub\subsub
> git checkout @~
Note: checking out '@~'.
You are in 'detached HEAD' state.
HEAD is now at f3087a9... subsub c1
> git br -avv
* (HEAD detached at f3087a9) f3087a9 subsub c1
master 03d08cc [origin/master] subsub c2
remotes/origin/HEAD -> origin/master
remotes/origin/master 03d08cc subsub c2
让我们在其父存储库“ ”中添加并提交子模块“ subsub
”(在处检出master~1
c1
)sub
:
vonc@VONCAVN7 D:\git\tests\subm\sub\subsub
> cd ..
vonc@VONCAVN7 D:\git\tests\subm\sub
> git add .
> git commit -m "subsub at HEAD-1"
[master (root-commit) 1b8144b] subsub at HEAD-1
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 subsub
让我们在该仓库' sub
'中添加几个提交:
vonc@VONCAVN7 D:\git\tests\subm\sub
> git commit --allow-empty -m "sub c1"
[master b7d1c40] sub c1
> git commit --allow-empty -m "sub c2"
[master c77f4b2] sub c2
vonc@VONCAVN7 D:\git\tests\subm\sub
> gl
* c77f4b2 - (HEAD -> master) sub c2 (2 seconds ago) VonC
* b7d1c40 - sub c1 (3 seconds ago) VonC
* 1b8144b - subsub at HEAD-1 (77 seconds ago) VonC
的最新提交sub
确实subsub
在正确的提交处引用了其子模块“ ”(c1
一个子子,而不是c2
一个子子)
vonc@VONCAVN7 D:\git\tests\subm\sub
> git ls-tree @
100644 blob 25a0feba7e1c1795be3b8e7869aaa5dba29d33e8 .gitmodules
160000 commit f3087a9bc9b743625e0799f57c017c82c50e35d6 subsub
^^^
That is subsub master~1 commit c1
最后,让我们创建一个主父仓库“ parent
”,并将“ sub
”添加为子模块:
vonc@VONCAVN7 D:\git\tests\subm
> git init parent
Initialized empty Git repository in D:/git/tests/subm/parent/.git/
> cd parent
vonc@VONCAVN7 D:\git\tests\subm\parent
> git submodule add -- ../sub
Cloning into 'D:/git/tests/subm/parent/sub'...
done.
让我们确保sub
是不是在其签出master
HEAD(就像我们之前subsub
)
vonc@VONCAVN7 D:\git\tests\subm\parent
> cd sub
vonc@VONCAVN7 D:\git\tests\subm\parent\sub
> gl
* c77f4b2 - (HEAD -> master, origin/master, origin/HEAD) sub c2 (2 minutes ago) VonC
* b7d1c40 - sub c1 (2 minutes ago) VonC
* 1b8144b - subsub at HEAD-1 (3 minutes ago) VonC
vonc@VONCAVN7 D:\git\tests\subm\parent\sub
> git checkout @~1
Note: checking out '@~1'.
You are in 'detached HEAD' state.
HEAD is now at b7d1c40... sub c1
现在,我们向sub
仓库添加(在c1
提交时签出,而不是在c2 master
HEAD签出)parent
:
vonc@VONCAVN7 D:\git\tests\subm\parent
> git add .
> git st
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitmodules
new file: sub
vonc@VONCAVN7 D:\git\tests\subm\parent
> git commit -m "sub at c1"
[master (root-commit) 27374ec] sub at c1
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 sub
让我们将sub
以下内容master
作为仓库中的子模块parent
:
vonc@VONCAVN7 D:\git\tests\subm\parent
> git config -f .gitmodules submodule.sub.branch master
> git diff
diff --git a/.gitmodules b/.gitmodules
index 8688a8c..97974c1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
[submodule "sub"]
path = sub
url = ../sub
+ branch = master
vonc@VONCAVN7 D:\git\tests\subm\parent
> git add .
> git commit -m "sub follows master"
[master 2310a02] sub follows master
1 file changed, 1 insertion(+)
vonc@VONCAVN7 D:\git\tests\subm\parent
> gl
* 2310a02 - (HEAD -> master) sub follows master (1 second ago) VonC
* 27374ec - sub at c1 (2 minutes ago) VonC
如果我克隆回购parent
,然后要求其任何子模块跟随他们的远程分支检出的,sub
并且subsub
将签出他们的master
分支(而只sub
应签master
,subsub
应保持在c1
)
首先克隆:
vonc@VONCAVN7 D:\git\tests\subm
> git clone --recursive parent p1
Cloning into 'p1'...
done.
Submodule 'sub' (D:/git/tests/subm/sub) registered for path 'sub'
Cloning into 'D:/git/tests/subm/p1/sub'...
done.
Submodule path 'sub': checked out 'b7d1c403edaddf6a4c00bbbaa8e2dfa6ffbd112f'
Submodule 'subsub' (D:/git/tests/subm/subsub) registered for path 'sub/subsub'
Cloning into 'D:/git/tests/subm/p1/sub/subsub'...
done.
Submodule path 'sub/subsub': checked out 'f3087a9bc9b743625e0799f57c017c82c50e35d6'
到目前为止,一切都很好:sub
和subsub
在被检查出来c1
,不是 c2
(即:不是他们的master HEAD c2
)
但:
vonc@VONCAVN7 D:\git\tests\subm\p1
> git submodule update --recursive --remote
Submodule path 'sub': checked out 'c77f4b2590794e030ec68a8cea23ae566701d2de'
Submodule path 'sub/subsub': checked out '03d08cc81e3b9c0734b8f53fad03ea7b1f0373df'
现在,从克隆开始p1
,子模块和子子模块都位于其处master HEAD c2
。
而且,即使这样sub
(master
按预期检查),仍然subsub
位于c2
:
vonc@VONCAVN7 D:\git\tests\subm\p1\sub
> git ls-tree @
100644 blob 25a0feba7e1c1795be3b8e7869aaa5dba29d33e8 .gitmodules
160000 commit f3087a9bc9b743625e0799f57c017c82c50e35d6 subsub
在不修改sub
and的任何内容的情况下subsub
,这是如何确保subsub
保持其预期的c1
提交而不是遵循master
(sub
应该如此)的方式
git submodule update --recursive
从本身具有嵌套子模块的子模块进行调用(因此--remote
此处不存在)
vonc@VONCAVN7 D:\git\tests\subm\p1\sub
> git submodule update --recursive
Submodule path 'subsub': checked out 'f3087a9bc9b743625e0799f57c017c82c50e35d6'
现在,我们有:
sub
保留在master
(由于父.gitmodules
branch
指令及其初始git submodule update --recursive --remote
)subsub
设置回其记录的sha1(c1
,not master c2
)--recursive
应用--remote
到所有没有嵌套时,子模块,默认为主submodule.<path>.<branch>
发现。update --remote
你想要什么.gitmodules
文件中未指定分支的任何子模块重置为其正确的SHA1。只需%PATH%
在git-subupd
脚本中的任意位置创建一个bash脚本,该脚本即使在常规WindowsCMD
会话中也可以运行,因为它将由git bash解释。
git-subupd
:
#!/bin/bash
git submodule update --recursive --remote
export top=$(pwd)
git submodule foreach --recursive 'b=$(git config -f ${top}/.gitmodules submodule.${path}.branch); case "${b}" in "") git checkout ${sha1};; esac'
“ git命令的组合”简化为一个git调用:
cd /path/to/parent/repo
git subupd
这就对了。
(任何调用的脚本git-xxx
都可以由git使用调用git xxx
)
vonc@VONCAVN7 D:\git\tests\subm\p1
> git subupd
Submodule path 'sub/subsub': checked out '03d08cc81e3b9c0734b8f53fad03ea7b1f0373df'
Entering 'sub'
Entering 'sub/subsub'
Previous HEAD position was 03d08cc... subsub c2
HEAD is now at f3087a9... subsub c1
sub
保持设置为master
(commit c2
,未更改),而subsub
重置为c1
(而不是master c2
)。
该OP BartBog声明在评论中使用脚本的一个微小的变化:
export top=$(pwd)
git submodule foreach --recursive \
'b=$(git config -f ${top}/.gitmodules submodule.${path}.branch); \
case "${b}" in \
"") git checkout ${sha1};; \
*) git checkout ${b}; git pull origin ${b};; \
esac'
为了避免调用
submodule update --remote
AND来确保我的子模块没有处于分离的头部状态(遵循您的回答)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句