Automating GIT merges with Powershell and Visual Studio Team Services (VSTS)

Harrison Bay
Timely
5 min readApr 26, 2018

--

Background

The other day I went to open a pull request against a feature branch and I noticed a whole lot of changes I didn’t push myself in the diff. I instantly realised I was working on a newer version of master than what my feature branch was based on.

I had a few options, I could:

  1. Tell the reviewer of the pull request to only look at the commits authored by me in the past day.
  2. Checkout the upstream branch, pull master, open a separate pull request and self merge that in.
  3. Create some automation to sync my feature branch with master.

I decided this was a good chance to brush up my scripting skills and automate something.

Discovery

One thing I’ve learnt about building anything is buy-in is key. Before I went any further I described the problem I was having to a few of my colleagues. Turns out they all faced the same hassle.

One of them noted that merge conflicts are a sticking point and you can’t automate that. I needed a way to report merge conflicts out and automatically merge anything else. For this we decided posting to Slack was appropriate.

Step 1. Writing the script

To get this up and running locally all you’ll need is

  • Powershell v3 or later
  • Git
  • A Target Repository with read/write access

Cloning the repo

This fragment of code checks out a target folder, if the folder hasn’t been cloned already it runs git clone. You’ll notice I pipe the output of git clone to write-host . This little workaround is needed because when Powershell invokes git the output is recorded as stderror which when using Powershell ISE or VSTS build agents handle as an error.

List, Iterate, Checkout, Pull, Push

This snippet contains the bulk of the heavy lifting.

  1. Firstly we list all the branches in the target repo using git for-each-ref which returns a list of branch names likeorigin/master
  2. Next we iterate over the branch names, chop of the first 7 characters and compare them to the pattern we expect with PowerShell -like
  3. git checkout is run and then git pull which ensures the local version is up to date.
  4. Then we pull in master using git pull origin $defaultBranch which is where the merge commit will be created if successful.
  5. To see if the pull succeeded we use git status --porcelain this command returns the files in the working directory.
  6. If there’s none then we can run git push if there are files we not the failure and clean the working directory & reset the head.
  7. The final step in the loop checks out master again and deletes the branch we were working on so if you re-run this you get a fresh copy.

Reporting the changes

To keep the script relatively simple I opted to use a PowerShell Module to call Slack found here.

This block is all about formatting the Slack messages.

  1. We go grab the commit details from git about the latest commit in master
  2. Group the result list by value, these are emoji’s for success and failed
  3. Loop through the list appending the status to the message
  4. Post the message to Slack.

Here’s an example message from the snippet above.

The final product

All these code snippets combine to make one big script, which will clone the repo, list all the branches, checkout each, pull master, push successful merges (if that’s enabled) and report the results to Slack.

If you’re like me you’d look at this and say we’re pretty much done, and for the most part we are. That being said we still don’t have it running anywhere except locally, which ain’t ideal.

Configuring VSTS

For this step you’re gonna need to be able to create build definitions in VSTS and be able to change user permissions with VSTS source control.

1. Firstly create yourself a build definition in VSTS. Give it a creative name, I called mine ‘The Great Merger’.

2. Configure the ‘Get sources’ step which will clone your chosen repo, I opted to clean the sources and output directory each build, to keep the build server fresh.

3. Now create an Agent phase. Important note, remember to check Allow scripts to access OAuth token which allows the build agent to communicate with git using it’s built-in Authentication provider.

4. Inside the newly created Agent phase create an inline PowerShell step and paste in the script.

5. Next head to the Variables tab and decide which variables you want to sub-in. Here’s mine:

You might also want to include the Slack API Key which we store in Azure Keyvault, I also had to add system.prefergit = true which tells the agent to use the git cli.

And that should just about do it. Lastly if you’re using ‘VSTS Git’ you’ll want to check the permissions of the ‘Project Collection Build Service’ user and check it has Contributor permissions.

After fixing that up all that’s left is to run the build and see what happens. Happy merging!

--

--