mlaraki
mlaraki

Reputation: 31

How can I prevent myself from pushing to the master branch?

Sadly, our master branch is not protected anymore.
Mistakes can happen, but how can I prevent accidental pushes to master?

Greedy Microsoft

Upvotes: 2

Views: 2123

Answers (3)

ErikMD
ErikMD

Reputation: 14723

Two suggestions to avoid mistakes:

  1. Split the integration workflow in (Main repo + Fork repo), which can optionally be enforced by setting appropriate permissions to collaborators.

  2. 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.

Main+Fork repos

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:

    • (1) an HTTPS (not SSH) remote URL:
      git remote remove origin && git remote add upstream https://github.com/Orga/project.git
    • and (2) an SSH remote to their Fork:
      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…

Going further with the HTTPS-only remote URL approach

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

Chris Dodd
Chris Dodd

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

William Pursell
William Pursell

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

Related Questions