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

时间:2015-02-14 21:19:57

标签: git git-submodules

我是一个患有先前svn经历的git新手。我的很多项目都在使用我自己的库中的代码,所以我自然而然地想要一些像外部类似的#34;来自git的功能。我目前正在尝试使用子模块。

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

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

所以,我的问题是:

  1. 这是一个好主意还是我试图重新发明轮子?
  2. 最简单的方法是什么?
  3. 编辑:我希望用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 
    

    现在的问题是,当克隆一个新的repo时,这个钩子会过早触发,因为已经创建了子模块目录但是它们中的文件还没有被拉出。

1 个答案:

答案 0 :(得分:2)

如果你想要类似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 repositorygit-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...(ei,将--template=...选项添加到git clone,也许通过使它成为别名并以某种方式将其放在每个人的全局配置中。

EDIT2:在评论中讨论后:

如果子模块是只读的,则需要在更新之前使它们可写(根据注释,Windows上的git会自动执行此操作,但在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版本&gt; = 1.7.8)或<submodule>/.git/hooks(对于较旧的git版本)。