Is there a way to prevent git committers from creating a directory in the repository.
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.
Is there a way to do this?
A few people have pointed out that committers should be 'trained' to not do this. There are a few flaws there:
Thus, the need for an automated approach.
User education with a 2x4 clue-stick should be the first choice. 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). Then clone the repository and add a banned path (like a/b/c/file as in your example). 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. Second - this all works on windows too (when using Git for Windows at least).
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:
ln -s . a
git add a
git commit -m "Create top-level self-referential symlink to stifle subdirectory creation"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With