Registering / Installing a Windows Service

After you have written your Windows Service in Visual Studio you might want to run this to test and use the service.

You can run your service with a few simple steps: I used a service called ServiceName in the following examples.

First start a command prompt: cmd (as admin)

Install a service is done using sc create, syntax:
sc create ServiceName binPath=”pathto.exe”. If the command was successfull it will report SUCCESS.
Example:

Install a service is done using sc create, syntax:
sc create ServiceName binPath=”pathto.exe”.

If the command was successfull it will report SUCCESS. Example:

C:\WINDOWS\system32>sc create ServiceName binPath=”C:\repos\ServiceMonitor\ServiceName\bin\Debug\ServiceName.exe”
[SC] CreateService SUCCESS

To start the service use the command net start, syntax:
net start ServiceName

C:\WINDOWS\system32>net start ServiceName
The ServiceName service is starting.
The ServiceName service was started successfully.

To stop the service use the command net stop, syntax:
net stop ServiceName
Example:

C:\WINDOWS\system32>net stop ServiceName
The ServiceName service is stopping.
The ServiceName service was stopped successfully.

To delete / uninstall the service use sc delete, syntax:
sc delete ServiceName
Example:

C:\WINDOWS\system32>sc delete servicename
[SC] DeleteService SUCCESS

UPDATE 28-2-2019: New post, I added a installer in the executable. This enables the service to install running the executable. Read on in this follow up article: http://kannekens.nl/registering-installing-a-windows-service-part-2/

Allow anonymous access to a Windows file share

I found an article writen by Nikola Radosavljević when I was trying to configure a Windows share to allow access from unknown users from other computers on the same network: http://nikolar.com/2015/03/10/creating-network-share-with-anonymous-access/

Creating network share with anonymous access

March 10, 2015

I needed to create a network share on Windows server machine which would require no authentication whatsoever from users. This post is intended to serve me as a reminder, since googling the solution every time eats easily away hours.

Settings which need to be changed of course depend on version of Windows of network share host. This post describes how to do it on a Windows 2012 R2.

Roughly what needs to be done is:

network share should be created

share permissions need to be set

security settings need to be changed

In more detail:

Share a folder by opening folder properties, navigating to Sharing tab and clicking

Advanced Sharing…

Enable sharing and click Permissions

Add Everyone (should already be there), Guest and ANONYMOUS LOGON and give them Read access

Open Group Policy Editor (hit Ctrl+R, type gpedit.msc and hit enter)

Navigate to Computer Configuration → Windows Settings → Security Settings → Local Policies → Security Options

Change following:

Accounts: Guest account status – change to Enabled

Network access: Let Everyone permissions apply to anonymous users – change to Enabled

Network access: Restrict anonymous access to Named Pipes and Shares – change to Disabled

Network access: Shares that can be accessed anonymously – enter name of share you created in the text field

————

Then after this I still had no access. After further investigation I made the following 2 additional changes:

1 I removed “guest” account from “Deny access to this computer from the network”

2 I removed a cached password on the client computer in “control userpasswords2”

Git Branching – Branches in a Nutshell

https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell

3.1 Git Branching – Branches in a Nutshell

Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects.

Some people refer to Git’s branching model as its “killer feature,” and it certainly sets Git apart in the VCS community. Why is it so special? The way Git branches is incredibly lightweight, making branching operations nearly instantaneous, and switching back and forth between branches generally just as fast. Unlike many other VCSs, Git encourages workflows that branch and merge often, even multiple times in a day. Understanding and mastering this feature gives you a powerful and unique tool and can entirely change the way that you develop.

Branches in a Nutshell

To really understand the way Git does branching, we need to take a step back and examine how Git stores its data.

As you may remember from Getting Started, Git doesn’t store data as a series of changesets or differences, but instead as a series of snapshots.

When you make a commit, Git stores a commit object that contains a pointer to the snapshot of the content you staged. This object also contains the author’s name and email address, the message that you typed, and pointers to the commit or commits that directly came before this commit (its parent or parents): zero parents for the initial commit, one parent for a normal commit, and multiple parents for a commit that results from a merge of two or more branches.

To visualize this, let’s assume that you have a directory containing three files, and you stage them all and commit. Staging the files computes a checksum for each one (the SHA-1 hash we mentioned in Getting Started), stores that version of the file in the Git repository (Git refers to them as blobs), and adds that checksum to the staging area:

$ git add README test.rb LICENSE

$ git commit -m ‘The initial commit of my project’

When you create the commit by running git commit, Git checksums each subdirectory (in this case, just the root project directory) and stores those tree objects in the Git repository. Git then creates a commit object that has the metadata and a pointer to the root project tree so it can re-create that snapshot when needed.

Your Git repository now contains five objects: three blobs (each representing the contents of one of the three files), one tree that lists the contents of the directory and specifies which file names are stored as which blobs, and one commit with the pointer to that root tree and all the commit metadata.

Figure 9. A commit and its tree

If you make some changes and commit again, the next commit stores a pointer to the commit that came immediately before it.

Figure 10. Commits and their parents

A branch in Git is simply a lightweight movable pointer to one of these commits. The default branch name in Git is master. As you start making commits, you’re given a master branch that points to the last commit you made. Every time you commit, the master branch pointer moves forward automatically.

Note The “master” branch in Git is not a special branch. It is exactly like any other branch. The only reason nearly every repository has one is that the git init command creates it by default and most people don’t bother to change it.

Figure 11. A branch and its commit history

Creating a New Branch

What happens when you create a new branch? Well, doing so creates a new pointer for you to move around. Let’s say you want to create a new branch called testing. You do this with the git branch command:

$ git branch testing

This creates a new pointer to the same commit you’re currently on.

Figure 12. Two branches pointing into the same series of commits

How does Git know what branch you’re currently on? It keeps a special pointer called HEAD. Note that this is a lot different than the concept of HEAD in other VCSs you may be used to, such as Subversion or CVS. In Git, this is a pointer to the local branch you’re currently on. In this case, you’re still on master. The git branch command only created a new branch — it didn’t switch to that branch.

Figure 13. HEAD pointing to a branch

You can easily see this by running a simple git log command that shows you where the branch pointers are pointing. This option is called –decorate.

$ git log –oneline –decorate

f30ab (HEAD -> master, testing) add feature #32 – ability to add new formats to the central interface

34ac2 Fixed bug #1328 – stack overflow under certain conditions

98ca9 The initial commit of my project

You can see the “master” and “testing” branches that are right there next to the f30ab commit.

Switching Branches

To switch to an existing branch, you run the git checkout command. Let’s switch to the new testing branch:

$ git checkout testing

This moves HEAD to point to the testing branch.

Figure 14. HEAD points to the current branch

What is the significance of that? Well, let’s do another commit:

$ vim test.rb

$ git commit -a -m ‘made a change’

Figure 15. The HEAD branch moves forward when a commit is made

This is interesting, because now your testing branch has moved forward, but your master branch still points to the commit you were on when you ran git checkout to switch branches. Let’s switch back to the master branch:

$ git checkout master

Figure 16. HEAD moves when you checkout

That command did two things. It moved the HEAD pointer back to point to the master branch, and it reverted the files in your working directory back to the snapshot that master points to. This also means the changes you make from this point forward will diverge from an older version of the project. It essentially rewinds the work you’ve done in your testing branch so you can go in a different direction.

Note Switching branches changes files in your working directory It’s important to note that when you switch branches in Git, files in your working directory will change. If you switch to an older branch, your working directory will be reverted to look like it did the last time you committed on that branch. If Git cannot do it cleanly, it will not let you switch at all.

Let’s make a few changes and commit again:

$ vim test.rb

$ git commit -a -m ‘made other changes’

Now your project history has diverged (see Divergent history). You created and switched to a branch, did some work on it, and then switched back to your main branch and did other work. Both of those changes are isolated in separate branches: you can switch back and forth between the branches and merge them together when you’re ready. And you did all that with simple branch, checkout, and commit commands.

Figure 17. Divergent history

You can also see this easily with the git log command. If you run git log –oneline –decorate –graph –all it will print out the history of your commits, showing where your branch pointers are and how your history has diverged.

$ git log –oneline –decorate –graph –all

* c2b9e (HEAD, master) made other changes

| * 87ab2 (testing) made a change

|/

* f30ab add feature #32 – ability to add new formats to the

* 34ac2 fixed bug #1328 – stack overflow under certain conditions

* 98ca9 initial commit of my project

Because a branch in Git is actually a simple file that contains the 40 character SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. Creating a new branch is as quick and simple as writing 41 bytes to a file (40 characters and a newline).

This is in sharp contrast to the way most older VCS tools branch, which involves copying all of the project’s files into a second directory. This can take several seconds or even minutes, depending on the size of the project, whereas in Git the process is always instantaneous. Also, because we’re recording the parents when we commit, finding a proper merge base for merging is automatically done for us and is generally very easy to do. These features help encourage developers to create and use branches often. R

Simple unit tests in Visual Studio solutions

In Visual Studio it is really simple to add unit tests that are automatically run in your build script. Right click your solution to add a test project:

Add a few test methods:

Check this Step-By-Step for an explanation:

https://visualstudiomagazine.com/articles/2013/07/29/test-driven-development-with-visual-studio-2012.aspx

Check this link for some Unit test basics:

https://docs.microsoft.com/en-us/visualstudio/test/unit-test-basics?view=vs-2017

/// <summary>
/// Test if flipcoins throws as many times as requested
/// </summary>
[TestMethod()] public void FlipCoinsTest1Times()
{
//Arrange
int odd, even;
int times = 1;

//Act
CoinFlipper coinFlipper = new CoinFlipper();
coinFlipper.FlipCoins(times, out odd, out even);

//Assert Assert.IsTrue(times == odd + even);
}

Open Test explorer window

Right click a selection of tests and select “Run selected tests”.

When the tests are OK, we can check in the solution. Default the Build in Azure will run libraries with names containing *test*.

The results for this solution: 8 tests passed.

Hosted Build has errors for missing reference Crystal reports libraries

I was planning a migration for my solution from a build on my local machine to a build in Azure Devops. I want to use the Hosted VS2017 because then I do not have to worry about maintaining local Build servers.

When I added the solution to Azure and set up a build pipeline I encountered the following errors in the MSBuild log:

2019-01-10T10:11:49.9382855Z ##[error]Notepad\CrystalReportsViewer.cs(8,7): Error CS0246: The type or namespace name ‘CrystalDecisions’ could not be found (are you missing a using directive or an assembly reference?)
2019-01-10T10:11:49.9412999Z ##[error]Notepad\CrystalReport1.cs(153,53): Error CS0246: The type or namespace name ‘RequestContext’ could not be found (are you missing a using directive or an assembly reference?)
2019-01-10T10:11:49.9414407Z ##[error]Notepad\CrystalReportsViewer.cs(14,16): Error CS0246: The type or namespace name ‘ReportDocument’ could not be found (are you missing a using directive or an assembly reference?)
2019-01-10T10:11:49.9415960Z ##[error]Notepad\CrystalReport1.cs(19,35): Error CS0246: The type or namespace name ‘ReportClass’ could not be found (are you missing a using directive or an assembly reference?)
2019-01-10T10:11:49.9430403Z ##[error]Notepad\CrystalReport1.cs(24,32): Error CS0115: ‘CrystalReport1.ResourceName’: no suitable method found to override
2019-01-10T10:11:49.9432260Z ##[error]Notepad\CrystalReport1.cs(33,30): Error CS0115: ‘CrystalReport1.NewGenerator’: no suitable method found to override
2019-01-10T10:11:49.9433304Z ##[error]Notepad\CrystalReport1.cs(42,32): Error CS0115: ‘CrystalReport1.FullResourceName’: no suitable method found to override

I found a solution for this issue adding a pre-build event:

First I needed to add the CRRuntime msi and a pre-build.bat file to my solution:

The content for the pre-build file is an administrator installation of the CRRuntime msi. The command is:
msiexec /a “%1CRRuntime_64bit_13_0_23.msi” /quiet /norestart /log “%1CRRuntime_64bit_13_0_23_install.log”. I only want this to be installed when building a release (in Azure). For this I added the condition to only install for release builds.

if %2 == “release” msiexec /a “%1CRRuntime_64bit_13_0_23.msi” /quiet /norestart /log “%1CRRuntime_64bit_13_0_23_install.log”

Last I have added a pre-build event command line for the solution:
“$(ProjectDir)pre-build.bat” “$(ProjectDir)” “$(ConfigurationName)”

That’s that. Now the host will install the Crystal reports run time before building the solution.

How to set up a local deployment for an Azure build application

*Important note: This solution will only work when you do NOT have a .gitignore file in your repository*

Configure a local agent

First requirement is that you set up a local agent that will be used for the local tasks.

How to configure local build and deploy agents is explained here:

https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=vsts

The result should look somewhat like this:

To control this agent you can choose to install it as a service on Windows.

Or you can choose to run the agent from the command line. To start and stop the agent I added two scripts:

Start.cmd:

Start.cmd:
cd c:
cd \EK-VSTS-Agent
start “EK-VSTS Azure agent” .\run.cmd
exit

Stop.cmd:

taskkill /FI “WindowTitle eq EK-VSTS Azure agent*” /T /F

Setup a build and release pipeline in Azure

Goto Pipelines in your Azure Devops project and click on new pipeline. My example uses a project named WPFDatasetWithSQL.

*Important note: This solution will only work when you do NOT have a .gitignore file in your repository*

Click continue and choose .Net Desktop and click Apply.

If you want to build the solution using a hosted machine keep the “Agent pool” set on “Hosted VS2017”. If you need local components to build you could choose to use a local machine or set up the required components in this build script.

For this example I have no need for extra components and I will keep the Agent pool on Hosted VS2017.

We are going to change a few setps in this script:

1 Set the MSBuild Arguments to /target:publish. This changes the MSBuild to add a app.publish to the build directory for click once deployment.

2 Change the step Copy Files to add the app.publish folder to the artifacts folder.
Display name = Copy Files to: $(build.artifactstagingdirectory)
Source Folder = $(Build.SourcesDirectory)\src\BLM\bin\$(BuildConfiguration)\app.publish
Contents = **\**

3 Change the artifact name.
Display name = Publish Artifact: $(System.TeamProject)-$(Build.BuildNumber)
Artifact name = $(System.TeamProject)-$(Build.BuildNumber)

Click Save and keep the default name.

Set up a release pipeline

Now we will set up a release pipeline in which we can control and manage releases for this application.

Click on Releases in the menu and click New pipeline.

Choose a Empty job template. The release pipeline is going to contain not much more than a few copy tasks.

For starters we will have to choose an artifact. Choice is simple, we are going to use the artifacts from the build pipeline. Select the Source Build pipeline set up in the previous step and finish this by clicking the Add button below.

Next step in this release pipeline is a deployment to “Test”. For this purpose we will rename the default “Stage 1” to “Test”. For this, clicking the Stage1 image (not on the link to job with task) will open a properties window. Rename Stage1 to Test and click save right top in the corner.

Now click the link to job and task in the Test stage. Click the agent job and change the agent pool to the pool where you added the local agent. In my example I added the local agent to a pool named “local machine”.

Now we will add a job to copy the publish folder to a local directory. Click on the puls sign next to “Agent job” and search for “Copy Files”

Select The task added below Job agent and fill in the details:

Select The task added below Job agent and fill in the details:
Display name = Copy Files to: c:\drop\$(System.TeamProject)\$(Release.EnvironmentName)\$(Release.ReleaseName)\
Source Folder = $(system.defaultworkingdirectory)_WPFDatasetWithSQL-.NET Desktop-CI * This last directory name is the build pipeline name
Target Folder = c:\drop\$(System.TeamProject)\$(Release.EnvironmentName)\$(Release.ReleaseName)\

The source folder will contain the pipeline name for the build pipeline preceded by an underscore:

Click save in top right hand corner.

Now we are going to add the production stage and the required copy jobs for this stage.

Click on releases in the left menu and click edit.

Click “Clone” in Test stage. And rename this new stage “Copy of Test” to “Production”. Click the task details and here I added System.TeamProject to the source folder name. This removes the build number from the destination name.

Next click the plus sign for the “Agent job” to add a command line script. With this command line we will first clean the install folder before we copy the new release in that location. The command line script is rd /S /Q c:\drop\$(System.TeamProject)\Install\

Last task for this job is to add a second “Copy Files” task. This task will copy the publish content in the install folder.

For the first run disable the Command line script because the folder will not yet exist. This will cause an error if the command is executed while the directory does not exist. After the first run the command can be enabled.

Last option is to add an approval trigger on production. A test manager or a group of testers can be allowed to approve the release after testing.

Another nice feature is to enable continuous integration and continuous deployment in Azure. For this go to the build pipeline and click the checkbox for “Enable continuous integration” in the tab “Triggers”.

Second, go to release pipeline click the continuous deployment trigger and enable continuous deployment every time a new build is available. Click save.

First two times the deployment failed. I checked the logging and fixed some typing errors.

After approving the release the install folder will be updated with the required binaries.

All done. Enjoy.

Libben rint sa’t it rint

libben rint sa’t it rint

en net sa’t wy wolle

somtiiden lok

dan wer de soarch oan ‘e holle

djipten en delten

yn us bestean

se komme op us paed

en wy hawwe te gean

heallege glezen

bin’ ek healfol

dat is wat libben

us hjir sizze wol

Dagen fan ljocht

dagen fan tsjuster

hjoed moat wy libje

want juster wie juster

moarn is de takomst

mar it libben is hjoed

wachtsje net langer

want no hast’ de moed

pak dan dy kans

libje de dei

want foar dast’ it wist

is it foarby

Jan van der Meer

het leven loopt zoals het loopt

en niet wat we willen

soms tijd

dan weer de zorgen aan het hoofd

diepten en hoogten

in ons bestaan

ze komen op ons pad

en we moeten gaan

halflege glazen

zijn ook halfvol

dat is wat het leven

ons hier zeggen wil

Dagen van licht

dagen van duisternis

vandaag moeten we leven

omdat gisteren gisteren was

morgen is de toekomst

maar het leven is vandaag

wacht niet langer

want nu heb je de moed

Grijp dan die kans

leef de dag

want voor je het weet

is het voorbij

Jan van der Meer

Unblock project files in Visual Studio

When you open a copy of project files from a remote location / downloaded from the internet you get the message that the project location is not trusted:

or a security warning when opening the project warning that the project file may have come from a location that is not fully trusted:

First assure yourself that the files you downloaded are from a trustworthy source. If this is the case then you could remove the warnings from these files like this:

Unblock downloaded files in folder including subfolders:

gci -path “C:\BeeHive” -recurse | Unblock-File (replace “C:\BeeHive” with the folder in which you want to unblock all files)

Async Await usage examples

//Wait Async use:

private async void button1_Click(object sender, EventArgs e)
{
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();

// Call the method that runs synchronously.
//string result = await WaitSynchronously ();

// Display the result.
textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
await Task.Delay(10000);
return “Finished”;
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
// Add a using directive for System.Threading.
Thread.Sleep(10000);
return “Finished”;
}

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
public static void Main()
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
GetPageSizeAsync(args[1]).Wait();
else
Console.WriteLine(“Enter at least one URL on the command line.”);
}

private static async Task GetPageSizeAsync(string url)
{
var client = new HttpClient();
var uri = new Uri(Uri.EscapeUriString(url));
byte[] urlContents = await client.GetByteArrayAsync(uri);
Console.WriteLine($”{url}: {urlContents.Length/2:N0} characters”);
}
}
// The following call from the command line:
// await1 http://docs.microsoft.com
// displays output like the following:
// http://docs.microsoft.com: 7,967 characters

//In a separate class:

using System;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class Example
{
static async Task Main()
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length < 2)
throw new ArgumentNullException(“No URIs specified on the command line.”);

// Don’t pass the executable file name
var uris = args.Skip(1).ToArray();

long characters = await GetPageLengthsAsync(uris);
Console.WriteLine($”{uris.Length} pages, {characters:N0} characters”);
}

private static async Task<long> GetPageLengthsAsync(string[] uris)
{
var client = new HttpClient();
long pageLengths = 0;

foreach (var uri in uris)
{
var escapedUri = new Uri(Uri.EscapeUriString(uri));
string pageContents = await client.GetStringAsync(escapedUri);
Interlocked.Add(ref pageLengths, pageContents.Length);
}

return pageLengths;
}
}

A successful Git branching model

By Vincent Driessen
on Tuesday, January 05, 2010

Check out my latest post: An Intro to Decoders

In this post I present the development model that I’ve introduced for some of my projects (both at work and private) about a year ago, and which has turned out to be very successful. I’ve been meaning to write about it for a while now, but I’ve never really found the time to do so thoroughly, until now. I won’t talk about any of the projects’ details, merely about the branching strategy and release management.

Why git?

For a thorough discussion on the pros and cons of Git compared to centralized source code control systems, see the web. There are plenty of flame wars going on there. As a developer, I prefer Git above all other tools around today. Git really changed the way developers think of merging and branching. From the classic CVS/Subversion world I came from, merging/branching has always been considered a bit scary (“beware of merge conflicts, they bite you!”) and something you only do every once in a while.

But with Git, these actions are extremely cheap and simple, and they are considered one of the core parts of your daily workflow, really. For example, in CVS/Subversion books, branching and merging is first discussed in the later chapters (for advanced users), while in every Git book, it’s already covered in chapter 3 (basics).

As a consequence of its simplicity and repetitive nature, branching and merging are no longer something to be afraid of. Version control tools are supposed to assist in branching/merging more than anything else.

Enough about the tools, let’s head onto the development model. The model that I’m going to present here is essentially no more than a set of procedures that every team member has to follow in order to come to a managed software development process.

Decentralized but centralized

The repository setup that we use and that works well with this branching model, is that with a central “truth” repo. Note that this repo is only considered to be the central one (since Git is a DVCS, there is no such thing as a central repo at a technical level). We will refer to this repo as origin, since this name is familiar to all Git users.

Each developer pulls and pushes to origin. But besides the centralized push-pull relationships, each developer may also pull changes from other peers to form sub teams. For example, this might be useful to work together with two or more developers on a big new feature, before pushing the work in progress to origin prematurely. In the figure above, there are subteams of Alice and Bob, Alice and David, and Clair and David.

Technically, this means nothing more than that Alice has defined a Git remote, named bob, pointing to Bob’s repository, and vice versa.

The main branches

At the core, the development model is greatly inspired by existing models out there. The central repo holds two main branches with an infinite lifetime:

  • master
  • develop

The master branch at origin should be familiar to every Git user. Parallel to the master branch, another branch exists called develop.

We consider origin/master to be the main branch where the source code of HEAD always reflects a production-ready state.

We consider origin/develop to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the “integration branch”. This is where any automatic nightly builds are built from.

When the source code in the develop branch reaches a stable point and is ready to be released, all of the changes should be merged back into master somehow and then tagged with a release number. How this is done in detail will be discussed further on.

Therefore, each time when changes are merged back into master, this is a new production release by definition. We tend to be very strict at this, so that theoretically, we could use a Git hook script to automatically build and roll-out our software to our production servers everytime there was a commit on master.

Supporting branches

Next to the main branches master and develop, our development model uses a variety of supporting branches to aid parallel development between team members, ease tracking of features, prepare for production releases and to assist in quickly fixing live production problems. Unlike the main branches, these branches always have a limited life time, since they will be removed eventually.

The different types of branches we may use are:

  • Feature branches
  • Release branches
  • Hotfix branches

Each of these branches have a specific purpose and are bound to strict rules as to which branches may be their originating branch and which branches must be their merge targets. We will walk through them in a minute.

By no means are these branches “special” from a technical perspective. The branch types are categorized by how we use them. They are of course plain old Git branches.

Feature branches

May branch off from:
develop
Must merge back into:
develop
Branch naming convention:
anything except master, develop, release-*, or hotfix-*

Feature branches (or sometimes called topic branches) are used to develop new features for the upcoming or a distant future release. When starting development of a feature, the target release in which this feature will be incorporated may well be unknown at that point. The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release) or discarded (in case of a disappointing experiment).

Feature branches typically exist in developer repos only, not in origin.

Creating a feature branch

When starting work on a new feature, branch off from the develop branch.

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

Incorporating a finished feature on develop

Finished features may be merged into the develop branch to definitely add them to the upcoming release:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

The --no-ff flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature. Compare:

In the latter case, it is impossible to see from the Git history which of the commit objects together have implemented a feature—you would have to manually read all the log messages. Reverting a whole feature (i.e. a group of commits), is a true headache in the latter situation, whereas it is easily done if the --no-ff flag was used.

Yes, it will create a few more (empty) commit objects, but the gain is much bigger than the cost.

Release branches

May branch off from:
develop
Must merge back into:
develop and master
Branch naming convention:
release-*

Release branches support preparation of a new production release. They allow for last-minute dotting of i’s and crossing t’s. Furthermore, they allow for minor bug fixes and preparing meta-data for a release (version number, build dates, etc.). By doing all of this work on a release branch, the develop branch is cleared to receive features for the next big release.

The key moment to branch off a new release branch from develop is when develop (almost) reflects the desired state of the new release. At least all features that are targeted for the release-to-be-built must be merged in to develop at this point in time. All features targeted at future releases may not—they must wait until after the release branch is branched off.

It is exactly at the start of a release branch that the upcoming release gets assigned a version number—not any earlier. Up until that moment, the develop branch reflected changes for the “next release”, but it is unclear whether that “next release” will eventually become 0.3 or 1.0, until the release branch is started. That decision is made on the start of the release branch and is carried out by the project’s rules on version number bumping.

Creating a release branch

Release branches are created from the develop branch. For example, say version 1.1.5 is the current production release and we have a big release coming up. The state of develop is ready for the “next release” and we have decided that this will become version 1.2 (rather than 1.1.6 or 2.0). So we branch off and give the release branch a name reflecting the new version number:

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

After creating a new branch and switching to it, we bump the version number. Here, bump-version.sh is a fictional shell script that changes some files in the working copy to reflect the new version. (This can of course be a manual change—the point being that some files change.) Then, the bumped version number is committed.

This new branch may exist there for a while, until the release may be rolled out definitely. During that time, bug fixes may be applied in this branch (rather than on the develop branch). Adding large new features here is strictly prohibited. They must be merged into develop, and therefore, wait for the next big release.

Finishing a release branch

When the state of the release branch is ready to become a real release, some actions need to be carried out. First, the release branch is merged into master (since every commit on master is a new release by definition, remember). Next, that commit on master must be tagged for easy future reference to this historical version. Finally, the changes made on the release branch need to be merged back into develop, so that future releases also contain these bug fixes.

The first two steps in Git:

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

The release is now done, and tagged for future reference.

Edit: You might as well want to use the -s or -u <key> flags to sign your tag cryptographically.

To keep the changes made in the release branch, we need to merge those back into develop, though. In Git:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

This step may well lead to a merge conflict (probably even, since we have changed the version number). If so, fix it and commit.

Now we are really done and the release branch may be removed, since we don’t need it anymore:

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

Hotfix branches

May branch off from:
master
Must merge back into:
develop and master
Branch naming convention:
hotfix-*

Hotfix branches are very much like release branches in that they are also meant to prepare for a new production release, albeit unplanned. They arise from the necessity to act immediately upon an undesired state of a live production version. When a critical bug in a production version must be resolved immediately, a hotfix branch may be branched off from the corresponding tag on the master branch that marks the production version.

The essence is that work of team members (on the develop branch) can continue, while another person is preparing a quick production fix.

Creating the hotfix branch

Hotfix branches are created from the master branch. For example, say version 1.2 is the current production release running live and causing troubles due to a severe bug. But changes on develop are yet unstable. We may then branch off a hotfix branch and start fixing the problem:

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

Don’t forget to bump the version number after branching off!

Then, fix the bug and commit the fix in one or more separate commits.

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

Finishing a hotfix branch

When finished, the bugfix needs to be merged back into master, but also needs to be merged back into develop, in order to safeguard that the bugfix is included in the next release as well. This is completely similar to how release branches are finished.

First, update master and tag the release.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1

Edit: You might as well want to use the -s or -u <key> flags to sign your tag cryptographically.

Next, include the bugfix in develop, too:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

The one exception to the rule here is that, when a release branch currently exists, the hotfix changes need to be merged into that release branch, instead of develop. Back-merging the bugfix into the release branch will eventually result in the bugfix being merged into develop too, when the release branch is finished. (If work in develop immediately requires this bugfix and cannot wait for the release branch to be finished, you may safely merge the bugfix into develop now already as well.)

Finally, remove the temporary branch:

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

Summary

While there is nothing really shocking new to this branching model, the “big picture” figure that this post began with has turned out to be tremendously useful in our projects. It forms an elegant mental model that is easy to comprehend and allows team members to develop a shared understanding of the branching and releasing processes.

A high-quality PDF version of the figure is provided here. Go ahead and hang it on the wall for quick reference at any time.

Update: And for anyone who requested it: here’s the gitflow-model.src.key of the main diagram image (Apple Keynote).


Git-branching-model.pdf

Git-branching-model

If you want to get in touch, I’m @nvie on Twitter.