How to move a part of your .Net code as open source

During the process of building your .Net application you may realize that there is a part of it that can be reusable. If you have the authorization from the company you are working for or if it’s simply a private side project you can extract a part of your software and make it open source. One advantage to make it open source is to get other people use it, and find potential issues or improvement. You may also receive contributions from external. Finally, it is a good way to build a portfolio by showing to the world a piece of your work. This article describe steps of how to move a part of a C# code from a private repository in VSTS (Visual Studio Team Services) into GitHub. During the process, we will show how to extract, create a new project, create a nuget package, distribute your package and how to have code compiled and tested on every time a commit is pushed to the public repository.

Isolation

Isolating your code withing your actual code is the first step. You must be able to extract the code you think can be reusable in a unique namespace within your actual project. A good idea is to have a folder where you move all your files and setup a unique namespace. This will probably make your actual code not working because of some missing references, but it should not be a big deal to add using at the top of each file that were using the logic. In this article, I will extract code about Circuit Breaker.
IsolateCode

Creating a New Project

The next step is to take the isolated code and to copy the files in a new solution. First, create a new solution with Visual Studio. Create 2 projects : one for your code, one for your unit test. Copy the files that you have isolated into the code project. Do the same with the actual unit test you have.SolutionNewProjects

Migrating Visual Studio Tests Tool to an Alternative

Some modifications may be required for unit test if you are using Microsoft.VisualStudio.TestTools.UnitTesting. Most open source continuous integration doesn’t run Visual Studio to build and run your test. Whence, you need to use something that can be ran over the console. This doesn’t mean that you will not be able to run unit tests with Visual Studio, but means that you cannot use the Microsoft Unit Testing Framework. Multiple alternatives to Microsoft Visual Studio Unit Test exist like nUnit and xUnit. For the example, I will convert all unit tests to xUnit.

The first step is to remove the reference to Microsoft.VisualStudio.TestTools.UnitTesting. This got added when adding a new unit test project. Open the project, under references, select the DLL and hit delete. After, we need to install xUnit Nuget packages.

xunit.1.9.2
xunit.runner.visualstudio.2.1.0
xunit.runner.console.2.1.0

One is the main xUnit library, the other one allow to run the test from Visual Studio and from a console. Visual Studio Nuget package allows to debug which is very interesting. The console is required to be able to run, later, the test automatically when you push your code into the public repository. The third step is to clean up the test files. Remove all using that reference to the Visual Studio Testing framework (using Microsoft.VisualStudio.TestTools.UnitTesting). The next clean up is to remove the attribute [TestClass]. xUnit doesn’t need to have an attribute on top of the class. Finally, you need to change [TestMethod] attribute to [Fact]. You will need to add xUnit using (using Xunit) at the top of the file.

If you have [TestCategory] attribute you will need to use [Trait(“Category”, “CI”)].
If you use [ExpectedException] to validate exception, than you will need to remove it to use a new assertion which is better because it’s more specific. The following code has the old attributes commented and the new attribute and new assertion.

//[TestMethod]
[Fact]
//[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void GivenCircuitBreaker_WhenConstructorWithInvalidThreshold_ThenThrowException()
{
     Xunit.Assert.Throws<ArgumentOutOfRangeException>(() => new DotNetCircuitBreaker.CircuitBreaker(0, TimeSpan.FromMinutes(5)));
}

Assertions syntax is different too. For example, asserting an equality won’t be Assert.AreEqual(x,y) but Assert.Equal(x,y). You can find the whole list of assertion in the official xUnit documentation.

Generate Nuget Package

This step is potentially optional. However, having a new Nuget package generated every new version of your assembly. The first step is to generate a nuspec from your project. Use the Nuget.exe in the project. This will generate a file with some place older that will be replaced from your assembly. You should open this file to add some more detailed information like what new in the specific version, dependencies on other packages etc. Here is how look a nuspec file.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2016</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>

From that basic generated file, it’s important to add at least the files you want to add into the nuget package. Here is how it looks at the for this example.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <projectUrl>https://github.com/MrDesjardins/DotNetCircuitBreaker</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Initial release</releaseNotes>
    <copyright>Copyright 2016</copyright>
    <tags>circuit breaker</tags>
  </metadata>
  <files>
		<file src="bin\Release\DotNetCircuitBreaker.dll" target="lib" />
		<file src="bin\Release\DotNetCircuitBreaker.pdb" target="lib" />
  </files>
</package>

Two important details. First, the project url is set to GitHub, where we will push the code in the next step. This is normal at this point that you might not know the complete URL but usually it’s your GitHub user name followed by the name of your project. Second is the files element that contain the release library and the pbd. The DLL is the actual code that will be used by the consumer of your package and the PDB is the debugging file that Visual Studio can use.

Once you have built you solution once (in release mode) you can try to generate the nuget package manually :

nuget pack DotNetCircuitBreaker.csproj -Prop Configuration=Release

It’s important to set the configuration, otherwise you may have Nuget getting you that error : “authors is required” or “description is required”. In all case, we do not want to generate the package manually in later I will show you how to generate and publish it automatically on the web.

For the first publish of your Nuget package, let’s use the manually created package to upload it. In few, the upload will be done by each publish with GitHub so you will not have to do it manually. Create a Nuget.org account, in your profile click Upload a package.

Publish your Source Code

We are almost ready to publish our code on GitHub — a public repository. GitHub is widely known and used by several huge company, Microsoft included. It is a good place to publish your source code because it has a huge volume of users, it’s easy to use and a lot of developer already have an account which let them participate to your project easily. Before setuping GitHub, we must create a file that describe the project which will be used as the main page when people come in you GitHub project. The second one is a ignore file that will discard binaries and other development files from being published. You can find a template to use on GitHub. Simply copy it and save it at the root of your project. The read me file is a markdown file. It must named readme.md. The files structure should look like this :

FileStructureWithReadMe

Next step is to create your project on GitHub.
GitHubNewRepository

This is very fast and once it’s created you can go in the root of your project with a console and use git :

git init
git remote add origin https://github.com/MrDesjardins/DotNetCircuitBreaker.git
git add .
git commit -m "first commit"
git push -u origin master

Continuous Integration

The next step is to have every time your push new code on GitHub to have this one built and your test ran. The goal is to be sure that what you publish is in a good state. We can also add a step that if everything is fine and that the version of your assembly increase to have a Nuget package generated. You can find all steps in this previous post : Continuous Integration with Travis CI.

Consume

Once the code is published, the last step is to consume your package from your open source. You need to go back to your original project where the code originate. Then, you need to go in reference, and get the Nuget package you published. The code is out of your main repository which allow you to work on it with affecting your main project. People outside your main project can contribute, find issues and fix this open source part. You can yourself use in multiple projects this package, even use it in different company. Finally, you have some exposure about what you can do and save many hours to other people who can benefit of your code.

How to clone a branch from a Git Repository without downloading every branches

gitlogo

The hard way to get a branch clone is to clone the repository and do a checkout to the desired branch. The first operation will download every files from the repositories. This mean that if you have several branches that you will download them all. Indeed, Git is smart and you do have the master branch and branches are only a difference. Nevertheless, this can be huge and if you really want just to access a specific branch can be long and a waste of bandwidth. This is why Git gives you the posibility to clone a branch with the -b. This will save you the checkout operation but it does not save you the download problem — you still download all commits. To be efficient, you should use the –single-branch argument which will tell Git to take care of only the branch specified.

Here is an example:

git clone -b TheBranchName --single-branch https://YourGitUrl/RepositotyName LocalFolderNameForTheBranch

This is very efficient. If your branch has only 1 file, than you will download only that single file instead of all files from all others branches.

Create a new branch from an existing remote branch

If you want to quickly works on a new feature without affecting the team’s branch or the master branch, you may want to create a specific branch for your work. This is also known as a topic branch. Here are the commands that I use.

mkdir MyNewFeature
cd MyNewFeature
git init
git clone -b teamBranch https://yourgit.git
git checkout -b users/mrdesjardins/MyNewFeature
git branch -u origin/teamBranch
git push origin users/mrdesjardins/MyNewFeature

The first two lines create a new folder and move your position into it. This has nothing to do with Git. The next one create a new local branch with the specified existing remote branch of the remote server. At that moment, you have the same branch. You need to create a new local branch from that branch. This is done with checkout. Something interesting but not required is to set the upstream. Setting the upstream allow to know if the branch you branched from has changed. This way you can synchronize (pull). The last line is pushing your new local branch to the server. In that example, the same name so I do not need semi-colon. Otherwise you need to specify local:remove. For example, I could create the local without having the users/mrdesjardins/ and just using MyNewFeature local branch into the remote location users/mrdesjardins/MyNewFeature.

Git Combining Commit Not Pushed Yet

You are working on your computer, did several commit and you are ready to push. However, you may not want to push all the commit but only one that combine all your commit. Multiple cases exist like that you want all the code but not some of the comment related to commits. Another case could be that you the commit was not significant and you want to get ride of it. This is often the case of a commit without message. The change are required, but an empty commit is not.

To combine commit you need to use the rebase method inside your own branch. This is done by using rebase interactive command.

git rebase -i #All since the last commit
git rebase -i HEAD~5 #Last 5 commits

I wrote two commands that are doing almost the same. the first one does not specify the commit to takes. By default, it will takes all commit not pushed. The second command take the last 5 commits. This will redirect you to the interactive rebase screen. From that screen, it is possible to squash, edit or pick a command. You will also notice that the screen display all commit from the more old to the newest commit. You will see one line per commit. This allow you to edit every line by choosing if you want to keep the commit, with pick, to get the code but not the message with squash or to edit the commit with edit.

Let’s take the scenario that we want to combine everything in one commit. In that case, you pick the first commit ans squash all the other ones. You save and Git will open your default editor to allow you to edit the final message. Save and you are all set. At any time, if conflict occur you can abort. You just need to do the abort method of the git rebase command.

git rebase --abort

How To Use Git From Visual Studio Online

If you have a Git repository in Visual Studio Online and want to use a third party to manage your source code, like SourceTree, you need to configure something in Visual Studio.

First, open your Visual Studio Online portal and go into your profile to setup an alternative authentication. The profile is in the top-right corner of Visual Studio. Click your name and then click My Profile.

Step1Profile

Second, click the Crendential tab. This will allow you to have an alternative login name and a password to use for application like SourceTree (or any other system).

Step2AlternateAuthentification

When this is done, the third step is to copy the Git Http path which is the one you see in your browser when you click in the project you want to code, then code. The syntax should looks like the example below.

https://YOURRepositoryNAME.visualstudio.com/DefaultCollection/_git/Project

You need that http url to paste it into your software and be able to clone the repository. From there, you can use git to do every other commands you wish.

Create a New Git Branch with Uncommited Code

If you started doing some code modification but you realize that you should have done these modifications in a branch instead of directly into the branch you did the modification, you can move all files into a new branch. The command is checkout with the parameter -b which create the branch if this one does not exist.

git checkout -b NewBranch
git add .

The git add . simply add all uncommited file into the staged area.

Other possibility exist like using git stash to move uncommited code into a temporary place and unstash into another branch.

git stash
git checkout NewBranch
git stash apply

Git Adding a File to a Previous Commit

Imagine that you are doing a commit and you forgot to bring a file or multiples files. You can do a second commit but this would have the consequence to have two commits for something that in fact would have been in one. Git allows you to alter a past commit with the amend parameter.

For example, here is a small commit of 1 file.

git add main.cs
git commit -m "This is my first commit"

This is how to add a second file to this first commit.

git add util.cs
git commit --amend --no-edit

The –no-edit parameter specify that we do not want to modify the message. If you are doing a git log, you will see a single commit.

How to Rebase your Working Branch Without Commit your Working Files

Let’s start by building the scenario that you have two files that you want to share to everybody and one that is a configuration file that should not be shared. In some point in the development you want to get the latest version of the master branch into your feature branch. This require to you to do a merge or to rebase. Merging is interesting but will cause having in your feature branch all file becoming modified which will be hard later for the pull request. The reason is that you want to pull request only your modification and not the files that has been merged. This is where rebase can be interesting. The problem is that if you try to rebase you will get a message saying that you need to commit or stash or change first. This is comprehensive since when rebase you are moving the HEAD of your feature branch in the front of the master one. It needs to have a “node” to move. To do, you have to go into your feature branch, add all files you want to commit and commit.

git checkout Feature1
git add File1
git add File2
git rebase master

The last line will fail. The reason is that you still have the configuration file not commited, and you do not want to. This is where the stash command shine. The git stash command allow you to put somewhere the remaining files that have change into a “stash” which will allow you later to get back (after the rebase). To execute the stash, you have to execute the stash command in the branch you want the files not staged to be stashed.

git checkout Feature1
git stash
git rebase master
git stash pop

You should be all set with the latest version of the master branch and also your files back (the configuration file in our example).

GitHub Command Line Basic

The first thing is to create a repository. You can create one free at GitHub. After created the repository on GitHub get the URL of the repository and copy paste to the console with the clone command.
GitHubCloneHttpUrl

Download the repository to your computer with the clone command.

git clone https://github.com/MrDesjardins/TestingGit.git

GitCloneExistingRepository
Open notepad and modify an existing file. You can do it manually by specifying the file

git add README.md

You can use the add command with the the -u for all modified file but not for adding new file.

In both case, if you check the status you will see that the file is modified.

git status
git commit -m "Message here"
git status

Checking the status will not any more say that the file is modified but that your branch is ahead of origin/master by one commit

Doing another change on the same file will set back the status to modified.

You need to commit again before sending everything to the server. If you do not want to have the latest change, before commiting you can rollback the file with the checkout command.

git checkout readme.md

Before having your code available with everybody, it is possible to see all branches.

git branch -r 
git branch -a

To send the code to the server, we need to push. We need to specify the the remote.
git push origin master

This was the easy step. Now let’s dp a branch that we will than later merge back into this master branch.

git checkout -b "Branch1"
//or
$ git branch Branch1
$ git checkout Branch1

if we are checking the branches, we will see one local branch and not a remote one.

git branch -a
//create file test1.txt
git add text1.txt
git commit -m "Added test1.txt from branch1"
git checkout -b Branch2
//create file test1.txt
git add text1.txt
git commit -m "Added test1.txt from branch2"

From there we can do several thing like a pull request, pulling directly or pushing to another branch.
Let’s first stats with a pull request. To do, you need to go on Github.
GitComment

The web UI allows you to comment on the branch, but also inside every files. At the end, we can close the pull request.

You can close the pull request if you are not satisfy or you can accept and merge form the website or the console.
The console allows you to get the code and test it before pushing it back to the server. If you do not have the branch on your computer than you need to fetch and checkout. Finally, merge the master to the branch to check the pull request with the whole main branch.

git fetch origin
git checkout -b branch1 origin/branch1
git merge master

Once everything is done (mergin, making sure that it build, unit test works, etc), than it is the time to merge everything in the master.
or if you already have the branch in your computer, you can get the code with the fetch command and than check the modification with git log. Finally, you can get merge.

git fetch origin origin/branch1
git log origin/branch1
git merge origin/branch1

To accept the pull request this can be done by checkout the master and merge the branch into it. Finally, push everything to the server.

git checkout master
git merge --no-ff branch1
git commit -m "Merging Blah Blah"
git push origin master

Like in this example, conflict can occur.
GitConflct
You can also see the conflict with the git status command.
GitStatusConflict

Before resolving conflict, you need to be sure that you have configured the merging tool. Here is the configuration for WinMerge. This configuration must be set in your .gitconfig from your user folder. You can access it by using : %USERPROFILE%/.gitconfig

[merge]
    tool = winmerge
[mergetool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$MERGED"
    keepBackup = false
    trustExitCode = false

    tool = winmerge
[difftool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$LOCAL" "$REMOTE" -dl "Local" -dr

If you prefer kdiff3 tool which is a 3-way commit tool use this command

[merge]
    tool = kdiff3
[mergetool "kdiff3"]
    path = C:\\Program Files (x86)\\KDiff3\\kdiff3.exe
    keepBackup = false
    trustExitCode = false

From there you can go git mergetool and git will go through all files that must resolve conflict.

git mergetool

Once all conflicts solve, merge done, commit done and push to the server done, than the pull request is automatically closed for you.

We still have branch 2 to merge. Let’s do it without pull request. But before, lets move into branch2 and delete the readme file. Than let’s try to undo this delete.

git checkout branch2
del readme.md
git checkout -- readme.md

Same thing with a new file.

git add readme.md2
git reset readme.md2

Last thing with a modified date.

//modify file
git checkout -- readme.md

So you have two remembers two different commands. One is checkout and one is reset to undo something to a file.

Concerning undoing, if you have commit, you can also undo this command. In fact, committing only put the file in the stage area. To undo a commit use the git reset command.

git reset --soft HEAD~1