将子模块中的文件设置为只读

Amo*_*mum 6 git git-submodules

我是一个患有先前svn经验的git新手.我的很多项目都使用自己库中的代码,所以很自然地我想从git中获得一些"类似于外部"的功能.我目前正在尝试使用子模块.

但是如果以错误的方式使用子模块(据我所知),子模块可能会带来很大的痛苦(例如,更改子模块中的文件并忘记推送它们,或者忘记提交它们).

如果我将子模块中的所有文件设为只读怎么办?这足以防止意外更改.如果我真的想改变一些东西,我应该去改变原来的回购.

所以,我的问题是:

  1. 这是一个好主意还是我想重新发明轮子?
  2. 最简单的方法是什么?

编辑:我希望可以通过git hook实现,但我不确定如何.我第一次克隆回购时不能使用客户端挂钩,是吗?

EDIT2:在SRobertz的帮助下,我能够拿出一个结账后的钩子:

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 
Run Code Online (Sandbox Code Playgroud)

现在的问题是,当克隆一个新的repo时,当已经创建了子模块目录但是尚未提取其中的文件时,这个钩子会过早触发.

drR*_*rtz 3

如果您想要类似 svn 的外部组件,您可能需要查看 giternal,https://github.com/patmaddox/giternal,可以按原样使用或作为起点。freeze它是用 ruby​​ 编写的,如果命令不完全是您想要的(也许不是),应该很容易适应您想要的。

简短介绍: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,并沿着(受到 git 存储库中的 List submodules的启发,以及git-clone 和 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    
Run Code Online (Sandbox Code Playgroud)

然后,要部署钩子,一种选择是为开发人员设置一个模板目录,然后让他们执行git clone --template=</your/template/dir> url-to-clone...(ei,将--template=...选项添加到git clone,也许通过将其设为别名并以某种方式将其放入每个人的全局配置中)。

EDIT2:在评论中讨论后:

如果子模块已设为只读,则需要在更新之前将其设为可写(根据注释,Windows 上的 git 会自动执行此操作,但在 linux/macos 上是必需的)。要在 上执行此操作git pullpost-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
Run Code Online (Sandbox Code Playgroud)

可以对此进行改进,以检查合并中是否更新了任何子模块,并且仅处理该子模块,而不是始终迭代所有子模块。

警告git pull --recurse-submodules:如果您打算使用它,则需要检查 它如何交互。

请注意,这会在每次合并(拉取)后初始化并更新所有子模块,并使它们只读。

然而,它并没有解决git pull子模块内部的操作等问题。为此,需要添加相应的钩子.git/modules/*/hooks(对于 git 版本 >= 1.7.8)或<submodule>/.git/hooks(对于较旧的 git 版本)。