Mastering Branch Control: Restricting Push and Merge Actions on Main/Master Branch in AWS CodeCommit

Protect your main/master branch in AWS CodeCommit by creating IAM policies that deny GitPush and merge operations on specific branch references. Junior developers can create and push to feature branches, while only senior developers (Approvers group) can merge pull requests into the protected main branch.
Introduction
AWS CodeCommit is a secure, highly scalable, managed source control service that hosts private Git repositories. CodeCommit eliminates the need for you to manage your own source control system or worry about scaling its infrastructure. You can use CodeCommit to store anything from code to binaries. It supports the standard functionality of Git, so it works seamlessly with your existing Git-based tools. CodeCommit should be familiar to users of Git-based repositories such as GitHub.
In this post, I will describe a process for setting up and managing a workflow in AWS CodeCommit, specifically for a team comprising junior and senior developers. We will see how you can restrict Junior Developers from modifying the master/main branch, while proividing them access to create other branches and update those branches, leaving the Senior Developers to handle the production branch.
Prerequisites
To follow along in this post, you should have:
- an AWS billing account
- a AWS IAM account with programmatic access and admin permissions to create roles, control services, and create objects in AWS
This pattern uses IAM policies for branch protection. Unlike GitHub or GitLab, CodeCommit doesn't have built-in branch protection rules - you must implement them through IAM policy conditions.
High Level Actions
- Create IAM Users: Junior Developer and SeniorDeveloper
- Generate CodeCommit Credentials JuniorDev and SeniorDev
- Create IAM Groups for Junior Developers Group and Approvers Group; add in respective members
- Attach Policies to Junior Developers Group to limit pushes and merges to master branch
- Attach policies for Approvers Group with more access to CodeCommit
- Create a Repository in CodeCommit
- Interacting with the Repository as Junior Developer and creating a Pull Request
- Interacting with the Repository as a Senior Developer to Review and Merge the branch
Create Users
aws iam create-user --user-name juniordev
aws iam create-user --user-name seniordev
Create Git Credentials for Users
aws iam create-service-specific-credential --user-name juniordev --service-name codecommit.amazonaws.com
aws iam create-service-specific-credential --user-name seniordev --service-name codecommit.amazonaws.com
Save the ServiceUsername and ServicePassword immediately after creation - they cannot be retrieved later. Store these credentials securely as they provide Git access to your CodeCommit repositories.
- Save the ServiceUsername and ServicePassword for each user as you will use them when interacting with git
Create Groups
aws iam create-group --group-name Juniors
aws iam create-group --group-name Approvers
Add Users to Groups
aws iam add-user-to-group --group-name Juniors --user-name juniordev
aws iam add-user-to-group --group-name Approvers --user-name seniordev
Create and Attach Policies to Groups
Juniors
- Create a file called juniorsPolicy.json with the contents:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect": "Allow",
"Action": [
"codecommit:*"
],
"Resource": "arn:aws:codecommit:us-east-1:yourAWSAccountID:MyDemoRepo"
},
{
"Effect":"Deny",
"Action":[
"codecommit:GitPush",
"codecommit:DeleteBranch",
"codecommit:PutFile",
"codecommit:MergeBranchesByFastForward",
"codecommit:MergeBranchesBySquash",
"codecommit:MergeBranchesByThreeWay",
"codecommit:MergePullRequestByFastForward",
"codecommit:MergePullRequestBySquash",
"codecommit:MergePullRequestByThreeWay"
],
"Resource":"arn:aws:codecommit:*:*:*",
"Condition":{
"StringEqualsIfExists":{
"codecommit:References":[
"refs/heads/master"
]
},
"Null":{
"codecommit:References":"false"
}
}
}
]
}
The Condition block is key to branch protection. The "codecommit:References" condition restricts actions only when targeting refs/heads/master. Add "refs/heads/main" to the array if your repository uses 'main' as the default branch.
- Attach the Inline Policy
aws iam put-group-policy --group-name Juniors --policy-name JuniorsPolicy --policy-document file://juniorsPolicy.json
Approvers
- Create a file called approversPolicy.json with the contents (replacing us-east-1 with your region and 193591455755 with your AWS Billing Account ID:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codecommit:*"
],
"Resource": "arn:aws:codecommit:us-east-1:yourAWSAccountID:MyDemoRepo"
}
]
}
- Attach the Inline Policy
aws iam put-group-policy --group-name Approvers --policy-name ApproversPolicy --policy-document file://approversPolicy.json
Create Repository
aws codecommit create-repository --repository-name MyDemoRepo --repository-description "Description for MyDemoRepo"
Senior Developer Actions
Connect to Repository
git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo
- Copy and paste the git credentials for the Senior Developer
Create and Add Content
cd MyDemoRepo
echo 'test1' > index.html
Commit and Push to Repository
git add .
git commit -m 'initial add'
git push
Junior Developer Actions
Connect to Repository
git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo
- Copy and paste the git credentials for the Junior Developer
Create Branch and Add Content
cd MyDemoRepo
git checkout -b newFeature
echo 'testNewFeature' > index.html
Commit and Push to Repsoitory
git add .
git commit -m 'updated code'
git push origin newFeature
Merge (as Junior Developer)
This will produce an error:

aws codecommit create-pull-request --title "Merge newFeature into main" --description "new code" --targets repositoryName=MyDemoRepo,sourceReference=newFeature,destinationReference=master
aws codecommit merge-pull-request-by-fast-forward --pull-request-id "3" --repository-name MyDemoRepo
Merge (as Senior Developer)
This will NOT produce an error
aws codecommit create-pull-request --title "Merge newFeature into main" --description "new code" --targets repositoryName=MyDemoRepo,sourceReference=newFeature,destinationReference=master
aws codecommit merge-pull-request-by-fast-forward --pull-request-id "3" --repository-name MyDemoRepo
Move to Master and Delete Local and Remote Branch (as Senior Developer)
git checkout master
git branch -D newFeature
git push origin --delete newFeature
git pull
Bonus
For those with multiple git credentials in Windows and Credential Manager:
cmdkey /delete:git:https://git-codecommit.us-east-1.amazonaws.com
*Deletes the git entry*
cmdkey /generic:git:https://git-codecommit.us-east-1.amazonaws.com /user:"seniordev-at-193591455755" /pass:"JOs0yoySq/rU9+MESPYve4mZpfkA="
*Creates a git entry*
Use Windows Credential Manager commands (cmdkey) to switch between different CodeCommit user credentials when testing. This avoids the need to manually clear cached credentials.
Troubleshooting
| Issue | Possible Cause | Solution |
|---|---|---|
| Junior developer can still push to master | IAM policy not attached or cache issue | Verify the policy is attached to the Juniors group. IAM policy changes can take a few seconds to propagate. Try the operation again. |
| "Unable to access" error when cloning | Git credentials not configured correctly | Verify the ServiceUsername and ServicePassword are entered correctly. Use git config --global credential.helper manager on Windows. |
| Senior developer also denied merge | User not added to Approvers group or wrong policy | Verify group membership with aws iam get-group --group-name Approvers. Check the Approvers policy doesn't include deny statements. |
| Policy condition not working | Wrong branch reference format | Use the full reference path: "refs/heads/master" not just "master". The condition is case-sensitive. |
| Credentials prompt appears repeatedly | Cached credentials conflict | Clear Windows Credential Manager entries for CodeCommit: cmdkey /delete:git:https://git-codecommit.[region].amazonaws.com |