Reputation: 31
Sadly, our master branch is not protected anymore.
Mistakes can happen, but how can I prevent accidental pushes to master?
Upvotes: 2
Views: 2123
Reputation: 14723
Two suggestions to avoid mistakes:
Split the integration workflow in (Main repo + Fork repo), which can optionally be enforced by setting appropriate permissions to collaborators.
Use some git hook, e.g. on client side.
I'll elaborate only on the idea 1. below, since idea 2. is addressed in @WilliamPursell's answer.
Whether your team is working in a public or private organization repo, it's possible to make forks (e.g., private forks).
Then, you will have for example two remotes:
https://github.com/Orga/project.git
(Main)https://github.com/user/project.git
(user's Fork)Then, two options:
Either you only grant Release Managers "push access" to the Main repo, in which case no mistake is possible,
Or all devs have push access to Main, typically using SSH: in this case, you could just ensure that the devs configure their local clone with:
git remote remove origin && git remote add upstream https://github.com/Orga/project.git
git remote add origin [email protected]:user/project.git
In which case, some git push upstream master
(or git push
from a wrong configuration) won't be able to push through without querying one's HTTPS username or so, and then detect and stop the potential mistake.
In both cases, the idea would be to follow a Pull-Request based workflow to integrate changes in Main's master
branch…
Note that if you adopt the workflow I suggested above, sometimes one may need to directly push to the upstream repo (with an SSH URL then), and it is then a bit cumbersome to run git remote set-url upstream …
manually several times.
As a result, I ended up implementing a dedicated Git alias that allows one to easily switch any remote from SSH→HTTPS, and conversely (SSH←HTTPS).
Here is the full definition, then an example of use.
git config --global alias.togglessh '!f(){ if [ $# -lt 1 ]; then
printf "Usage: git togglessh origin
or: git togglessh <remote> # toggle ssh<->https in remote URL\n";
else url=$(git remote get-url "$1");
if echo "$url" | grep -q -e "^git@"; then
url=$(echo "$url" | sed -e "s/^git@//; s|:|/|; s|^|https://|");
else
url=$(echo "$url" | sed -e "s|^https://||; s|^ssh://||; s|/|:|; s|^|git@|");
fi; git remote set-url "$1" "$url"; echo "$1 -> $url"; fi; }; f'
$ git togglessh
Usage: git togglessh origin
or: git togglessh <remote> # toggle ssh<->https in remote URL
$ git remote -v
upstream [email protected]:erikmd/git-scripts.git (fetch)
upstream [email protected]:erikmd/git-scripts.git (push)
$ git togglessh upstream
upstream -> https://github.com/erikmd/git-scripts.git
$ git remote -v
upstream https://github.com/erikmd/git-scripts.git (fetch)
upstream https://github.com/erikmd/git-scripts.git (push)
$ git togglessh upstream
upstream -> [email protected]:erikmd/git-scripts.git
Upvotes: 1
Reputation: 126203
You can use a pre-commit hook -- look in .git/hooks/pre-commit.sample for information on how this hook works and an example.
You could also possibly use a server-side pre-receive hook, but setting that up generally requires admin access to the remote.
Upvotes: -1
Reputation: 212248
It's unfortunate that you need to do this for every repo (although you can use templates to alleviate this for each user), but you can just use a pre-push
hook. Something like:
#!/bin/sh
read ref name remote_ref remote_name
if test "$ref" = refs/heads/master; then
echo stubbornly refusing to push master >&2
exit 1
fi
should be adequate. Put that file in .git/hooks/pre-push
and make it executable and any accidental push of refs/heads/master
will be rejected.
Upvotes: 4