Github is the most famous Open-Source application repository. A lot of companies keep there their code, for example Microsoft keeps there .Net Core and many, many more. Additionally most of developers, who learn after work have their public repositories on Github. I personally had my repository on Azure DevOps, but later decided to publish my code additionally on GitHub. Even thou I don’ like GitHub’s simplicity.
Problem
There was one problem, I had to copy my code manually from Azure DevOps to GitHub. There is import repository functionality, but it takes too much time to use it frequently, additionally it’s pretty big manual process, you need to configure couple things and you need to do it from GUI, it wasn’t an option for long term.
From my colleague I heard that Microsoft uses Azure DevOps for everyday work and publish code on GitHub. Their work environment of Azure DevOps is last staging environment, when everything works for them, they push new version of Azure DevOps for rest of the world.
Then I thought, if they can work on Azure DevOps and have their code on GitHub, that means it’s possible to make it automatically, I wouldn’t believe they were updating GitHub repository manually.
Solution
There are 3 solution where only two of them works perfectly. We’ll start from partial solution, it won’t work in Github <–> Azure DevOps, but I decided to post it, because it’s perfect solution for Github <–> Github, Azure DevOps <–> Azure DevOps etc, and it’s common practice in Open-Source.
Fork
Mysterious Fork
button that is visible on top of every repository. It’ll let you create copy of repository that is still connected (somehow) with original repository. So when you Copy
repository, origin will be that copied repository, but when you Fork
repository you’ll create copy of that repository under your account and origin will be your repository, but still you’ll be able to merge changes to original. Or to say it correctly, owner of original repository will be able to merge your changes to his code.
It is the way Open-Source works, people don’t want pushes straight to public repository of their project, they want that contributors fork repository, then create functionality and after that owner of original repository will merge those changes to original. It gives more control for owner and doesn’t mix each contributors work.
If you still can’t understand it then think about it like big branch, normal branch will separate your work from other team members, fork would let you separate two organizations working on the same project. Inside they can have their own branches that won’t interfere with other organization and at the same time they can merge their code with each other.
Microsoft prepared great tutorial about forks in Azure DevOps, and they work the same way everywhere.
As I said before, this solution won’t work in cross repository situation, Microsoft owns Github, so maybe in future we’ll be able to Fork Github to Azure DevOps and vice versa.
Setup two repositories in IDE
It is solution that works fine, but in my opinion is the worst, because you need to configure your IDE so it’ll push your changes into both Azure DevOps and Github repositories. I don’t like it, because it’s additional work for every developer, everyone needs to configure it. It also means that there might be some synchronization problems, if two developers would push code at the same time, before you ask, it’s possible.
You can configure it in Visual Studio repository settings. In section where remotes are specified. You can add more remotes, you can even fetch from one repository and push to different if you’d like.
Visual will then push to two different remotes on his own, but somehow I don’t like when the same action is done on two different things, that’s why I present you third option…
Sync using CI
In my opinion it is the best solution. No one need to know about it, it will work behind the scene. All you need to do is create CI pipeline and from there call script that will push your selected branch, in my case it was only master
, to Github. So it’s similar to 2nd solution, but it is configure once and there is no chance that 2 developers push code at the same time. There is only one source of truth and it’s not developer’s work station.
Additionally you can select which branches you want to push, your Github repository won’t be polluted with some feature branches etc. It’s more secure, because only pipeline needs to know Github PAT or credentials. Now that I praised this solution, I’ll show you how to do it.
Sync Pipeline Visual Designer
All you need to do is create pipeline with script task.
git push https://[Username]:$[Password/PAT]@github.com/[Repository].git [branch]
for example
git push https://[Username]:$(GithubKey)@github.com/MartinBialkowski/AutoSFaP.git head:refs/heads/master
I’m using PAT from variable, to make it impossible for anyone to read.
You may ask why head:refs/heads/master
? Well without it, if branch not exists on GitHub, pipeline will fail. This solution lets you synchronize your project with newly created repository on GitHub.
Currently I’m working on extension for maketplace which will add task for build pipeline. With that you’ll be able to just use task and push to GitHub from Azure DevOps, but it’s still in development (I need to learn how to create something on marketplace)
For now, you can easily use solution from above. I’m using it now and it works perfect. If you have problem, please let me know and maybe we’ll be able to workout some solution.
Hi, the CI pipline reports
“error: src refspec head does not match any”
Seems if there is no repository there has to be some conditional logic to integrate the repose GitHub repo to create it, clone the DevOps repo over to it, before subsequent syncs to it (pushes) can be undertaken.
head:refs/heads/master does not seem to do anything.
Hi,
To be honest I haven’t tried it without creating repo first. It seems we would have to use GitHub API to create repo.
So you were able to push to empty repo with just git push
https://[Username]:$[Password/PAT]@github.com/[Repository].git master
?I had problems with that and I found that by adding head:refs/heads/master git will create branch for you if it not exist.