如何找出当前目录属于哪个 git 子模块
howto find out which git submodule current directory belongs to
设置
我有一个 git
存储库位于 /home/v/git_repo
,其中我有一个子模块位于子目录 ./a/b/c
.
$ cat /home/v/git_repo/.gitmodules
[submodule "foo/bar"]
path = a/b/c
url = git@github.com:username/repo.git
具有完整路径或仅存储库中的子路径(我已在帮助脚本 git-where-in-repo-am-i-currently
中实现)
$ pwd
/home/v/git_repo/a/b/c/something
$ git where-in-repo-am-i-currently
a/b/c/something
问题
我想找出(最好在fish
)这个路径属于哪个子模块:例如
$ git which-submodule (pwd)
foo/bar
稍后使用它来查询子模块状态,例如
$ git -C (git rev-parse --git-dir)/modules/(git which-submodule) status
on branch master
Your branch is up to date with 'origin/master'
并最终在我的提示中显示此信息(该部分已实现)
我试过的
正在解析
的输出
$ git -C (git rev-parse --show-toplevel) config --file=.gitmodules --get-regexp "path"`
submodule.foo/bar.path a/b/c
并将我的子目录路径与子模块的路径进行比较,但它相当混乱,将路径拆分为数组和各种 hack
对于您在此处描述的常规设置,工作树嵌套与子模块嵌套相匹配,您可以
mytoplevel=`git rev-parse --show-toplevel`
abovethat=`git -C "$mytoplevel"/.. rev-parse --show-toplevel`
然后,
echo ${mytoplevel#$abovethat/}
将为您获取超级项目中的子模块路径,或者您也可以
echo ${PWD#$abovethat/}
获取当前目录相对于超级项目的路径。
所以:
me=`git rev-parse --show-toplevel`
up=`git -C "$me"/.. rev-parse --show-toplevel`
subpath=${me#$up/}
git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
从其超级项目的配置条目中获取当前存储库的子模块名称和路径。
不过,Git 在任何可以想象到的构建系统中都是有用的;它不会对其职权范围之外的事物的设置方式施加限制。如果不对文件系统命名空间进行详尽搜索,您无法确定是否找到每个人都使用任何工作树作为子模块检查,Git 没有理由关心存储库的使用方式。
例如,如果多个项目都需要 运行 关闭同一个子模块 rev,您可以让一个 repo 和 worktree 作为它们所有的共享子模块:而不是必须经历每一个其中之一并进行同步结帐,然后相信您没有错过任何一个,只需使用一个存储库和一个工作树,并指出每个使用它的人。
对于有这种需求的工作流,这比通常的设置要好得多,根据定义,所有用户都会看到同步的、当前的子模块修订版,任何需要了解 "what's new" 更新的客户都可以,例如git -C utils diff `git rev-parse :utils` HEAD
,每个子模块用户实际上都有自己的跟踪分支,并且可以使用 Git 的所有工具来帮助保持最新状态或解决冲突。
所以,为了重新创建您的设置,我这样做:
git init git_repo; cd $_
mkdir a/b; git init a/b/c; cd $_
mkdir something; touch something/somefile;
git add .; git commit -m-
cd `git -C .. rev-parse --show-toplevel`
git submodule add --name foo/bar ./a/b/c -- a/b/c
git add .; git commit -m-
然后当我尝试时得到这个:
$ find -print -name .git -prune
.
./a
./a/b
./a/b/c
./a/b/c/something
./a/b/c/something/somefile
./a/b/c/.git
./.gitmodules
./.git
$ git grl
core.repositoryformatversion 0
core.filemode true
core.bare false
core.logallrefupdates true
submodule.foo/bar.url /home/jthill/src/snips/git_repo/a/b/c
submodule.foo/bar.active true
$ cd a/b/c/something
$ me=`git rev-parse --show-toplevel`
$ up=`git -C "$me"/.. rev-parse --show-toplevel`
$ subpath=${me#$up/}
$ git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
submodule.foo/bar.path a/b/c
$ echo $me $up $subpath
/home/jthill/src/snips/git_repo/a/b/c /home/jthill/src/snips/git_repo a/b/c
如果此设置与您所描述的有所不同,我遗漏了它,我有目录结构、子模块名称、起始目录...如果您逐步完成并找出设置或结果与您的不同之处,我认为这会有所帮助。
设置
我有一个 git
存储库位于 /home/v/git_repo
,其中我有一个子模块位于子目录 ./a/b/c
.
$ cat /home/v/git_repo/.gitmodules
[submodule "foo/bar"]
path = a/b/c
url = git@github.com:username/repo.git
具有完整路径或仅存储库中的子路径(我已在帮助脚本 git-where-in-repo-am-i-currently
中实现)
$ pwd
/home/v/git_repo/a/b/c/something
$ git where-in-repo-am-i-currently
a/b/c/something
问题
我想找出(最好在fish
)这个路径属于哪个子模块:例如
$ git which-submodule (pwd)
foo/bar
稍后使用它来查询子模块状态,例如
$ git -C (git rev-parse --git-dir)/modules/(git which-submodule) status
on branch master
Your branch is up to date with 'origin/master'
并最终在我的提示中显示此信息(该部分已实现)
我试过的
正在解析
的输出$ git -C (git rev-parse --show-toplevel) config --file=.gitmodules --get-regexp "path"`
submodule.foo/bar.path a/b/c
并将我的子目录路径与子模块的路径进行比较,但它相当混乱,将路径拆分为数组和各种 hack
对于您在此处描述的常规设置,工作树嵌套与子模块嵌套相匹配,您可以
mytoplevel=`git rev-parse --show-toplevel`
abovethat=`git -C "$mytoplevel"/.. rev-parse --show-toplevel`
然后,
echo ${mytoplevel#$abovethat/}
将为您获取超级项目中的子模块路径,或者您也可以
echo ${PWD#$abovethat/}
获取当前目录相对于超级项目的路径。
所以:
me=`git rev-parse --show-toplevel`
up=`git -C "$me"/.. rev-parse --show-toplevel`
subpath=${me#$up/}
git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
从其超级项目的配置条目中获取当前存储库的子模块名称和路径。
不过,
Git 在任何可以想象到的构建系统中都是有用的;它不会对其职权范围之外的事物的设置方式施加限制。如果不对文件系统命名空间进行详尽搜索,您无法确定是否找到每个人都使用任何工作树作为子模块检查,Git 没有理由关心存储库的使用方式。
例如,如果多个项目都需要 运行 关闭同一个子模块 rev,您可以让一个 repo 和 worktree 作为它们所有的共享子模块:而不是必须经历每一个其中之一并进行同步结帐,然后相信您没有错过任何一个,只需使用一个存储库和一个工作树,并指出每个使用它的人。
对于有这种需求的工作流,这比通常的设置要好得多,根据定义,所有用户都会看到同步的、当前的子模块修订版,任何需要了解 "what's new" 更新的客户都可以,例如git -C utils diff `git rev-parse :utils` HEAD
,每个子模块用户实际上都有自己的跟踪分支,并且可以使用 Git 的所有工具来帮助保持最新状态或解决冲突。
所以,为了重新创建您的设置,我这样做:
git init git_repo; cd $_
mkdir a/b; git init a/b/c; cd $_
mkdir something; touch something/somefile;
git add .; git commit -m-
cd `git -C .. rev-parse --show-toplevel`
git submodule add --name foo/bar ./a/b/c -- a/b/c
git add .; git commit -m-
然后当我尝试时得到这个:
$ find -print -name .git -prune
.
./a
./a/b
./a/b/c
./a/b/c/something
./a/b/c/something/somefile
./a/b/c/.git
./.gitmodules
./.git
$ git grl
core.repositoryformatversion 0
core.filemode true
core.bare false
core.logallrefupdates true
submodule.foo/bar.url /home/jthill/src/snips/git_repo/a/b/c
submodule.foo/bar.active true
$ cd a/b/c/something
$ me=`git rev-parse --show-toplevel`
$ up=`git -C "$me"/.. rev-parse --show-toplevel`
$ subpath=${me#$up/}
$ git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
submodule.foo/bar.path a/b/c
$ echo $me $up $subpath
/home/jthill/src/snips/git_repo/a/b/c /home/jthill/src/snips/git_repo a/b/c
如果此设置与您所描述的有所不同,我遗漏了它,我有目录结构、子模块名称、起始目录...如果您逐步完成并找出设置或结果与您的不同之处,我认为这会有所帮助。