Lock files from being merged from master into branches

How can I semi-permanently lock certain files from being merged.

At my company we have a Gitlab premium subscription, and we are hosted on Gitlab.com
We maintain an internal repository which defines our aws-auto-scaling runners(with docker+machine) as IAC. We have several different runner configurations (they are all auto-scaling docker-machine runners). To keep track of them, in our runner IAC repo we have a branch for each client.
So client A will have a branch [clientA/runner],
client B will have [clientB/runner, clientB/special-purpose-runner, etc.]

We only deploy runners from branches, and we use the master branch as a place to make global configuration changes(there is a change in security groups, we changed the subnet the runners are hosted in, etc.) So if I make a change to master, we will then merge master into each of the client branches at a convenient time so that they use the most up-to-date changes to the code and infra.

My problem is that each of these branches require a different client configuration that is used by Ansible. Client A may want an idle count of 2, while client B might want an idle count of 6. So when we merge the master branch into the client branches, it’s a pain and it’s error prone to have to manually omit the master config file from merging.

There are only a few files on each branch that need this protection, but from what I have found the only way to do this is to lock files from being changed on the master branch. I would like to update the master branch, then merge it into each of the client branches, but omit the config file as well as one other file since these 2 files need to be different depending on the branch.

Is there any way to enforce this? Even a way to loosely enforce it that is easily overridden is fine.

I am eventually going to create automation to merge the changes automatically via a pipeline, in which case I can just cherry pick all files except the ones we wish to omit, but until then I would like to find a way to do this.

Thank you in advance for helping out a git noob.

HI @Btripp1986

You might be able to do something with code owners or merge request approvals, but I suspect neither of these are quite what you want.

One very easy kludge would be to have a job like this which would just prevent any merge that touches a particular file:

    stage: careful
        - if: true
              - protected-file.yaml
          when: never
        - when: on_success

however, that’s not quite what you want either.

I’m not sure whether there’s an easy way to solve this one (but I’d be very interested to see ideas from others), but where I have similar situations, I store all the configurations on every branch, and then copy the right file into the right location, depending on the branch.

I don’t know whether this would be useful in your situation, but this is how the CI config might look:

    - prepare

.prepare: &prepare
    stage: prepare
        - cp $CLIENT_CONFIGURATION .config.yaml

    <<: *prepare
        CLIENT_CONFIGURATION: .config.clientA
        - if:'$CI_COMMIT_BRANCH =~ /^clientA\/[A-Za-z0-9-\.]+$/'
          when: on_success
         - when: never

    <<: *prepare
        CLIENT_CONFIGURATION: .config.clientB
        - if:'$CI_COMMIT_BRANCH =~ /^clientB\/[A-Za-z0-9-\.]+$/'
          when: on_success
         - when: never

Sorry not to have a more straightforward answer to this one, it’s an interesting problem!


Thanks for the ideas @snim2
I think that would get me to the desired end state if I refactor the repo a little bit, but I’ll wait and see if a more suitable strategy gets mentioned before implementing it. Thanks again for the input!

1 Like

I went with this strategy. After some slight refactoring this seems like a much more robust strategy than we had before and I think it will create less confusion for users and contributors to the repository alike.

Thanks again for the help snim2 (not actually tagging you so that you don’t get a notification for this post)

1 Like