简体   繁体   English

防止git提交者创建某些目录

[英]Prevent git committers from creating certain directories

Is there a way to prevent git committers from creating a directory in the repository. 有没有办法阻止git提交者在存储库中创建目录。

We have some developers who keep misplacing files in a directory structure. 我们有一些开发人员错误地将文件放在目录结构中。 Files that should be in 应该在的文件

 a/b/c/file

End up in 最终进入

 a/a/b/c/file

I simply want to prevent the creation of 我只是想阻止创作

 a/a/*

It needs to happen suitably obviously, so that they know their files weren't committed... thus, simply ignoring a/a/* isn't enough. 它需要明显地发生,以便他们知道他们的文件没有被提交......因此,简单地忽略a/a/*是不够的。

Is there a way to do this? 有没有办法做到这一点?

EDIT 编辑

A few people have pointed out that committers should be 'trained' to not do this. 一些人指出,提交者应该“接受培训”,不要这样做。 There are a few flaws there: 那里有一些缺陷:

  • Committers are human and make mistakes; 提交者是人,犯错误; training won't prevent this from happening 培训不会阻止这种情况发生
  • This is not the kind of information that would stick in the head of a new hire during training (waaay to fine a detail) 这不是那种在培训期间会留在新员工头脑中的信息(等待细节)
  • Mostly, this occurs during merges from one branch to another, so the files are not being manually created, rather they are pulled over in a larger changeset. 大多数情况下,这发生在从一个分支到另一个分支的合并期间,因此文件不是手动创建的,而是在更大的变更集中被拖过。

Thus, the need for an automated approach. 因此,需要一种自动化方法。

User education with a 2x4 clue-stick should be the first choice. 使用2x4线索的用户教育应该是首选。 For a technological solution you could prevent them from making such commits locally with a suitable commit hook. 对于技术解决方案,您可以阻止它们使用合适的提交挂钩在本地进行此类提交。 However, they probably would fail to install the hook as well. 但是,它们可能也无法安装钩子。 So you are left with implementing a hook that rejects their pushes. 因此,你只需要实现一个拒绝推送的钩子。 You can do this with an update hook which can reject commits before they get written into the central repository. 您可以使用更新挂钩执行此操作,该挂钩可以在将提交写入中央存储库之前拒绝提交。 Here is such a hook script: 这是一个这样的钩子脚本:

#!/bin/sh
#
# update hook - args: refname sha1-old sha1-new

ref="$1"
old="$2"
new="$3"
if [ -z "$ref" -o -z "$old" -o -z "$new" ]; then
  echo >&2 "usage: $0 <ref> <oldrev> <newrev>"
  exit 1
fi

for badpath in a/a a/z/x; do
  if git ls-tree $new:$badpath >/dev/null; then
    bogus=$(git ls-tree -r --name-only $new $badpath)
    echo >&2 "REJECTED DUE TO BOGUS PATH \"$bogus\""
    exit 1
  fi
done

exit 0

If we create a simple bare repository and add this as hooks/update and make it executable (on windows, we don't need to do that - hooks are executed anyway). 如果我们创建一个简单的裸存储库并将其添加为hooks / update并使其可执行(在Windows上,我们不需要这样做 - 无论如何都会执行钩子)。 Then clone the repository and add a banned path (like a/b/c/file as in your example). 然后克隆存储库并添加一个禁止的路径(如示例中的/ b / c /文件)。 This is what I get when I push this commit: 这是我推送此提交时得到的结果:

C:\Users\Pat\AppData\Local\Temp\x\L>git push origin master
Counting objects: 9, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (7/7), 423 bytes | 0 bytes/s, done.
Total 7 (delta 0), reused 0 (delta 0)
remote: REJECTED DUE TO BOGUS PATH "a/a/b/c/file"
remote: error: hook declined to update refs/heads/master
To C:/Users/Pat/AppData/Local/Temp/x/R
 ! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'C:/Users/Pat/AppData/Local/Temp/x/R'

This illustrates two things. 这说明了两件事。 Firstly, these hook scripts are actually very simple to create and to test in some temporary repository. 首先,这些钩子脚本实际上非常简单,可以在一些临时存储库中创建和测试。 Anything you echo to stderr or stdout gets copied to the pushing user. 您回显到stderr或stdout的任何内容都会被复制到推送用户。 Second - this all works on windows too (when using Git for Windows at least). 第二 - 这也适用于Windows(至少在使用Git for Windows时)。

A commit hook works on the users local repository and would be less obnoxious but you then have the problem of ensuring that all local clones have the correct hooks in place. 提交钩子在用户本地存储库上工作并且不那么令人讨厌,但是你有一个问题就是确保所有本地克隆都有正确的钩子。 This is much simpler to handle on the server end. 这在服务器端处理起来要简单得多。

This would accomplish preventing creation of a subdirectory a , but it's not ideal, and the better answer is probably training: 这将完成阻止创建子目录a ,但它不是理想的,更好的答案可能是训练:

ln -s . a
git add a
git commit -m "Create top-level self-referential symlink to stifle subdirectory creation"

Submodules (as proposed in the comment) is an option, but that won't prevent the user from creating a/a , it could just prevent him from pushing in unrelated directories. 子模块(在评论中提出)是一个选项,但这不会阻止用户创建a/a ,它可能只是阻止他推入不相关的目录。

You can make a git hook that check that no files is placed inside the folder a/a/ and reject the push if that happen. 您可以创建一个git挂钩,检查文件夹a/a/是否放置了文件,如果发生这种情况则拒绝推送。 Checkout git hooks over there: http://git-scm.com/book/en/Customizing-Git-Git-Hooks 结帐git挂钩: http//git-scm.com/book/en/Customizing-Git-Git-Hooks

You're probably looking for the pre-receive hook. 你可能正在寻找pre-receive挂钩。 Then, you only need to write your own script - shouldn't be too hard. 然后,你只需要编写自己的脚本 - 不应该太难。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM