Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Is it possible to 'Sync' a branch using Pipelines

Brady March 23, 2021

My current branch/pipeline strategy is as follows:

  • master -> Production Branch
  • dev -> development Branch
  • feature/*, bugfix/* -> feature or bugfix branches off of dev branch
  • release/* -> release branch off of dev branch
  • hotfix/* -> quick fixes off of release branch

 

Feature branches are created off of the development branch and merged back in. On commits to the development branch, I've configured pipelines to automatically create a release/* branch off of the dev branch and commit to it. Then, on the release branch, pipelines deploys to a staging environment. Subsequently merging a PR from release/* to master will trigger a deploy to production.

This final commit/merge causes the master branch and the dev branch to become out of sync, forcing me to manually, within the Bitbucket UI, click "sync" from the dropdown menu on the dev branch.

I'd like to be able to automate this step with pipelines if possible. Ideally, a commit to master and a successful production deployment would automatically sync the dev branch with the master branch. Is something like this possible? It seems to be treated as a typical commit in the UI, but i was unable to re-create this functionality in pipelines using my intuition.

1 answer

1 accepted

2 votes
Answer accepted
Theodora Boudale
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
March 26, 2021

Hi @Brady ,

This should be possible. A sync is basically a merge operation which you can perform during the Pipelines build and then push to dev branch.

I would just like to ask for clarification: the pipeline that deploys to production (and where you also want to sync dev with master), is it configured to run for commits on master? I.e. is it defined in the

branches:
master:

part of the bitbucket-pipelines.yml file?

If so, what you can do is add the following commands in the script for master, after the command(s) that does the deployment:

- git fetch origin "+refs/heads/*:refs/remotes/origin/*"
- git checkout -b dev origin/dev
- git merge master
- git push origin dev

This should sync dev branch with master.

Is this something that works for you?

Kind regards,
Theodora

Brady March 30, 2021

Hi @Theodora Boudale

Sorry for the delay in getting back to you. I finally merged a PR to master for the repo in question today. Your understanding is correct and your solution worked great! Thank you so much for the help.

I have a few more questions about the solution you provided if you are able to help further or point me in the right direction..

First, I'd like to be able to add some sort of tailored commit message to that `merge` so that I can skip CI when merging into dev (I don't want to trigger a staging deployment based on code that was already deployed to staging). In the Bitbucket Cloud UI this is possible and sort of required when clicking sync (see image). I tried adding the -m option (per git docs):

git merge -m '[skip ci] Merged master into dev' master

(as is what seems to work in the UI) to the merge command but this didn't appear to have any effect, and the commit message from my merge of

release/* -> master

was used, thus triggering the `dev` branch pipeline.

 

Second, this all assumes that no changes occur in the dev branch between when a staging deployment occurs e.g.:

dev -> release/*

and this merging operation of

master -> dev

However, if a feature branch merges into dev during this time, I imagine this could lead to merge conflicts. Would the protocol then be to manually resolve conflicts? Could this potentially cause any serious issues (other than headaches)?

Lastly (and I guess less importantly of the three), I wouldn't say I'm a noob when it comes to git, but I don't really understand what is happening in that fetch. What exactly is "+refs/heads/*:refs/remotes/origin/*"? I've been using git for about 4 years now and I've never come across anything like that.. What's happening here?

Thank you again for your very helpful response and in advance for any continued support!

 

Screen Shot 2021-03-30 at 11.00.35 PM.png

Theodora Boudale
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
April 7, 2021

Hi @Brady,

Thank you for the update, you are very welcome and it's good to hear that this worked for you!

Regarding your questions:

 

1. Merge commit message

I believe that the git merge command in the script is doing a fast forward merge, so no merge commit is actually created like when you do a sync from the UI.

After the fast forward merge, the last commit of master becomes the last commit of dev as well, and since this doesn't have [skip ci] in its message, a build gets triggered for dev.

To avoid this, you can add the option --no-ff in the merge command, which will force a merge commit to get created and add the commit message as well:

git merge master --no-ff -m '[skip ci] Merged master into dev'

 

2. Merge conflicts

A merge conflict could indeed arise and since this can only be resolved manually, I believe the step will fail in this case and the sync won't happen.

If you want to avoid failure of the step because of a merge conflict, you could add the commands in an after-script section of this step.

Please note that the after-script section will run anyway, whether the step succeeds or fails. So, if you want to sync only in case the previous commands of the step have succeeded, you may want to leave the commands for sync inside the script.

If you want to sync the branch regardless, you can use the after-script section. In this case, if the sync fails, the build status won't get affected, but you will need to resolve the conflicts locally, merge and push.

You can check our doc for the after-script keyword and example here, it's quite a long doc, so you can search the page for after-script to find the relevant section.

 

3. Fetch command

When you run Pipelines builds on a branch, only that branch is cloned in the Docker container where the build runs.

For builds that run e.g. on master, the .git/config file that is created in that clone includes the following:

[remote "origin"]
url = http://bitbucket.org/<workspace-id>/<repo-slug>
fetch = +refs/heads/master:refs/remotes/origin/master

You can check that if you add the command cat .git/config in your yml file in the definition for master.

So if you do a git fetch, only master refs will be fetched and you won't be able to check out another branch during the build.

git fetch origin "+refs/heads/*:refs/remotes/origin/*" is going to fetch all refs in that clone so you can then check out dev branch.

Since you only want to check out dev branch, you could actually use the following command instead, in order to fetch only dev refs:

git fetch origin "+refs/heads/dev:refs/remotes/origin/dev"

 

I hope this helps, please feel free to let me know if you have any other questions!

Kind regards,
Theodora

Like # people like this
Brady April 7, 2021

@Theodora Boudale Thank you so much for all of the help! I really appreciate you taking the time to write out such an in depth answer. I had no idea the after-script keyword existed (guess I need to dig into the docs more). --no-ff worked beautifully, and I even learned something new about git.

 

Endless thanks to you :) !!!

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
TAGS
AUG Leaders

Atlassian Community Events