使子模块中的文件只读
Making files in submodule read-only
我是一个 git 新手,之前有 svn 经验。我的许多项目都使用我自己的库中的代码,因此我自然想要 git 中的一些 "externals-like" 功能。我目前正在尝试使用子模块。
但是,如果您以错误的方式使用子模块(据我所知),它们会带来很多痛苦(例如,更改子模块中的文件而忘记推送它们,或者忘记提交它们)。
如果我将子模块中的所有文件设置为只读怎么办?这足以防止意外更改。如果我真的想改变一些东西,我应该在原始仓库中进行更改。
那么,我的问题是:
- 这是个好主意还是我正在重新发明轮子?
- 最简单的方法是什么?
编辑:我希望这可以通过 git 钩子来实现,但我不确定具体怎么做。第一次克隆 repo 时我不能使用客户端挂钩,可以吗?
EDIT2:在 SRobertz 的帮助下,我能够想出一个 post-checkout hook:
echo "you just checked out: $*"
echo "submodules:"
for p in `grep path .gitmodules | sed 's/.*= //'`; do # get submodules list
echo "making submodule directory $p read-only"
chmod -R a-w $p;
SAVEIFS=$IFS
IFS=$(echo -en "\n\b") #set delimeter to \n\b to handle whitespaces in filenames
for f in `ls $p`; do #get files in submodule dir
echo "making file $f in directory $p read-only"
chmod -R a-w $p\$f;
done
IFS=$SAVEIFS #restore delimeter to default value
done
现在的问题是,当克隆一个新的 repo 时,这个钩子触发得太早,当子模块目录已经创建但其中的文件尚未被拉出时。
如果您想要类似 svn 的外部组件,您可能需要查看 giternal,https://github.com/patmaddox/giternal ,按原样使用或作为起点。它是用 ruby 编写的,如果 freeze
命令不是您想要的(也许不是),应该很容易适应您想要的。
简短介绍:http://www.rubyinside.com/giternal-easy-git-external-dependency-management-1322.html
一篇较长的文章,末尾有一些备选方案:https://codingkilledthecat.wordpress.com/2012/04/28/why-your-company-shouldnt-use-git-submodules/
编辑:关于客户端挂钩及其部署:
如果您知道 git 子模块的怪癖并想使用它(也许是为了通过引用特定提交而不是 HEAD
获得稳定性)那么这是一种使其成为只读的方法克隆或签出时。
要使用的客户端挂钩是 post-checkout
,并按照(灵感来自
List submodules in a git repository, and git-clone and post-checkout hook。我在 .gitmodules 上使用了 grep,因为它在子模块被初始化之前工作。)
#!/bin/sh
# An example post-checkout hook to make submodules read-only
echo "you just checked out: $*"
git submodule init
git submodule update --recursive
echo "submodules:"
for p in `grep path .gitmodules | sed 's/.*= //'`; do
echo "making submodule directory $p read-only"
chmod -R a-w $p;
done
然后,要部署挂钩,一种选择是为您的开发人员设置模板目录,然后让他们执行 git clone --template=</your/template/dir> url-to-clone...
(e.i。,添加 --template=...
选项到 git clone
,也许通过将其设为别名并以某种方式将其放入每个人的全局配置中。
EDIT2:评论讨论后:
如果子模块已设为只读,则需要在更新前将其设为可写(根据评论,git 在 windows 上会自动执行此操作,但在 linux/macos).要在 git pull
上执行此操作,可以使用如下图所示的 post-merge
挂钩。
#!/bin/sh
# An example post-merge hook to
# 1. make submodules writable,
# 2. init and update submodules, and
# 3. make them read-only
# make all (existing) submodule directories writable
for p in `git submodule status | sed -e "s/^[+\ ][^\ ]*\ //" -e s/\ .*$//`; do
echo "making submodule directory $p writable"
chmod -R u+w $p;
done
echo "updating submodules:"
git submodule init
git submodule update --recursive
# make all submodules read-only
for p in `grep path .gitmodules | sed 's/.*= //'`; do
echo "making submodule directory $p read-only"
chmod -R a-w $p;
done
这可以改进以检查是否有任何子模块在合并中更新并只处理它,而不是总是迭代所有子模块。
警告:如果您打算使用它,需要检查它与 git pull --recurse-submodules
的交互方式。
请注意,这会初始化并更新所有子模块,并在每次合并(拉)后将它们设为只读。
但是,它没有解决在子模块内执行 git pull
等的问题。为此,需要将相应的挂钩添加到 .git/modules/*/hooks
(对于 git 版本 >= 1.7.8)或 <submodule>/.git/hooks
(对于旧的 git 版本)。
我是一个 git 新手,之前有 svn 经验。我的许多项目都使用我自己的库中的代码,因此我自然想要 git 中的一些 "externals-like" 功能。我目前正在尝试使用子模块。
但是,如果您以错误的方式使用子模块(据我所知),它们会带来很多痛苦(例如,更改子模块中的文件而忘记推送它们,或者忘记提交它们)。
如果我将子模块中的所有文件设置为只读怎么办?这足以防止意外更改。如果我真的想改变一些东西,我应该在原始仓库中进行更改。
那么,我的问题是:
- 这是个好主意还是我正在重新发明轮子?
- 最简单的方法是什么?
编辑:我希望这可以通过 git 钩子来实现,但我不确定具体怎么做。第一次克隆 repo 时我不能使用客户端挂钩,可以吗?
EDIT2:在 SRobertz 的帮助下,我能够想出一个 post-checkout hook:
echo "you just checked out: $*"
echo "submodules:"
for p in `grep path .gitmodules | sed 's/.*= //'`; do # get submodules list
echo "making submodule directory $p read-only"
chmod -R a-w $p;
SAVEIFS=$IFS
IFS=$(echo -en "\n\b") #set delimeter to \n\b to handle whitespaces in filenames
for f in `ls $p`; do #get files in submodule dir
echo "making file $f in directory $p read-only"
chmod -R a-w $p\$f;
done
IFS=$SAVEIFS #restore delimeter to default value
done
现在的问题是,当克隆一个新的 repo 时,这个钩子触发得太早,当子模块目录已经创建但其中的文件尚未被拉出时。
如果您想要类似 svn 的外部组件,您可能需要查看 giternal,https://github.com/patmaddox/giternal ,按原样使用或作为起点。它是用 ruby 编写的,如果 freeze
命令不是您想要的(也许不是),应该很容易适应您想要的。
简短介绍:http://www.rubyinside.com/giternal-easy-git-external-dependency-management-1322.html
一篇较长的文章,末尾有一些备选方案:https://codingkilledthecat.wordpress.com/2012/04/28/why-your-company-shouldnt-use-git-submodules/
编辑:关于客户端挂钩及其部署:
如果您知道 git 子模块的怪癖并想使用它(也许是为了通过引用特定提交而不是 HEAD
获得稳定性)那么这是一种使其成为只读的方法克隆或签出时。
要使用的客户端挂钩是 post-checkout
,并按照(灵感来自
List submodules in a git repository, and git-clone and post-checkout hook。我在 .gitmodules 上使用了 grep,因为它在子模块被初始化之前工作。)
#!/bin/sh
# An example post-checkout hook to make submodules read-only
echo "you just checked out: $*"
git submodule init
git submodule update --recursive
echo "submodules:"
for p in `grep path .gitmodules | sed 's/.*= //'`; do
echo "making submodule directory $p read-only"
chmod -R a-w $p;
done
然后,要部署挂钩,一种选择是为您的开发人员设置模板目录,然后让他们执行 git clone --template=</your/template/dir> url-to-clone...
(e.i。,添加 --template=...
选项到 git clone
,也许通过将其设为别名并以某种方式将其放入每个人的全局配置中。
EDIT2:评论讨论后:
如果子模块已设为只读,则需要在更新前将其设为可写(根据评论,git 在 windows 上会自动执行此操作,但在 linux/macos).要在 git pull
上执行此操作,可以使用如下图所示的 post-merge
挂钩。
#!/bin/sh
# An example post-merge hook to
# 1. make submodules writable,
# 2. init and update submodules, and
# 3. make them read-only
# make all (existing) submodule directories writable
for p in `git submodule status | sed -e "s/^[+\ ][^\ ]*\ //" -e s/\ .*$//`; do
echo "making submodule directory $p writable"
chmod -R u+w $p;
done
echo "updating submodules:"
git submodule init
git submodule update --recursive
# make all submodules read-only
for p in `grep path .gitmodules | sed 's/.*= //'`; do
echo "making submodule directory $p read-only"
chmod -R a-w $p;
done
这可以改进以检查是否有任何子模块在合并中更新并只处理它,而不是总是迭代所有子模块。
警告:如果您打算使用它,需要检查它与 git pull --recurse-submodules
的交互方式。
请注意,这会初始化并更新所有子模块,并在每次合并(拉)后将它们设为只读。
但是,它没有解决在子模块内执行 git pull
等的问题。为此,需要将相应的挂钩添加到 .git/modules/*/hooks
(对于 git 版本 >= 1.7.8)或 <submodule>/.git/hooks
(对于旧的 git 版本)。