Alexander Mills
Alexander Mills

Reputation: 100386

Allow only one branch to be pushed to remote

We have a Git remote (for production), using OpenShift.

Locally, I want to ensure that only the master branch can be pushed to this remote. Are there any special steps I should take to ensure this happens, or should I just rely on Git defaults?

I am 99% certain that the production Git remote only looks at the master branch. So my understanding is that the only way we could push a different branch locally would be something like:

git push prod_remote a_feature_branch:master

So my question is - is there a way to prevent someone on my team from doing that (without a force flag)?

Upvotes: 1

Views: 545

Answers (1)

torek
torek

Reputation: 489828

On the receiving side, the Git that is receiving commits has no notion of the branch names, if any, attached to commits on the sending Git. All it knows is that it has received some set of objects, followed by a request to update some set of references. If those references are spelled refs/heads/whatever, they are branch-name create, delete, or update operations for the branch named whatever.

Hence, on the receiving side, the answer is no: there is no way to prevent anyone from doing that. If they can get commits delivered to the receiving Git at all, they can deliver whatever commits and whatever reference name updates they like. You can use any authentication data left behind (e.g., from ssh or an access control system like Gitolite) to inspect the commits and/or the reference name updates, but you know nothing of their origin, you have only hash IDs and the names.

On the sending side, you can use a pre-push hook to do a great deal more. A pre-push hook is run with:

  • $1: the name of the remote, if the push is using a named remote;
  • $2: the URL corresponding to $1

(if not using a named remote, the two command-line arguments are identical), and on standard input, a stream of lines, one line per push refspec, with each line having four items:

  • local ref (e.g., refs/heads/branch)
  • local hash ID
  • remote ref
  • remote hash ID

(see the githooks documentation for details). However, the sending side hook is up to each sender, since each person has full control over her/his repository and, for that matter, whether to invoke any hooks.

If everyone who will push voluntarily opts in, you can provide them with a hook that will:

  • check the remote name ($1) and/or URL ($2);
  • if those match the repository you want protected, check whether any of the remote refs on the input stream match refs/heads/master;
  • if all those checks apply, check the corresponding local ref and/or hash in any way you like.

Upvotes: 1

Related Questions