söndag 26 november 2017

Refactoring: Replace Magic Number with Symbolic Constant example i C#

Part three in my series of refactors I've used the most from the book Refactoring - Improving the design of existing code.

Replace Magic Number with Symbolic Constant

You have a literal number with a particular meaning.
Create a constant, name it after the meaning, and replace the number with it.

Example 1

The code before

1:  double PotentialEnergy(double mass, double height)  
2:  {  
3:    return mass * 9.81 * height;  
4:  }  

The code after

1:  private const double GravitationalConstant = 9.81;  
3:  double PotentialEnergy(double mass, double height)  
4:  {  
5:    return mass * GravitationalConstant * height;  
6:  }  

Example 2

I thought I would find a better example, but it wasn't that easy, so I settled with just another example. The example below is from the page https://www.eliotsykes.com/magic-numbers, but I think the real world examples in the bottom of that page might give you a better understanding of how you can use constants.

The code before

1:  public bool AllowedToComment()  
2:  {  
3:    return _age >= 13 && CommentsInLastHour.Count < 20;  
4:  }  

The code after

1:  const int CommenterMinAge = 13;  
2:  const int MaxCommentsPerHour = 20;  
4:  public bool AllowedToComment()  
5:  {  
6:    return _age >= CommenterMinAge && CommentsInLastHour.Count < MaxCommentsPerHour;  
7:  }  


Magic numbers are one of the oldest ills in computing. They are numbers with special values that usually are not obvious. Magic numbers are really nasty when you need to reference the same logical number in more than one place. If the numbers might ever change, making the change is a nightmare. Even if you don't make a change, you have the difficulty of figuring out what is going on.

The source code

måndag 13 november 2017

Refactoring: Introduce Explaining Variable example i C#

Part two in my series of refactors I've used the most from the book Refactoring - Improving the design of existing code.

Introduce Explaining Variable

More known as Extract Variable

You have a complicated expression.
Put the result of the expression, or parts of the expression, in a temporary variable with a name that explains the purpose.

Example 1: The code before

1:  if (platform.ToUpper().IndexOf("MAC") > -1 &&  
2:    browser.ToUpper().IndexOf("IE") > -1 &&  
3:    WasInitialized() && resize > 0)  
4:  {  
5:    // do something  
6:  }  

Example 1: The code after

1:  bool isMacOs = platform.ToUpper().IndexOf("MAC") > -1;  
2:  bool isIEBrowser = browser.ToUpper().IndexOf("IE") > -1;  
3:  bool wasResized = resize > 0;  
5:  if (isMacOs && isIEBrowser && WasInitialized() && wasResized)  
6:  {  
7:    // do something  
8:  }  

Example 2: The code before

1:  public double Price()  
2:  {  
3:    // price is base price - quantity discount + shipping  
4:    return _quantity * _itemPrice -  
5:        Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +  
6:        Math.Min(_quantity * _itemPrice * 0.1, 100);  
7:  }  

Example 2: The code after

1:  public double Price()  
2:  {  
3:    var basePrice = _quantity * _itemPrice;  
4:    var quantityDiscount = Math.Max(0, _quantity - 500) * _itemPrice * 0.05;  
5:    var shipping = Math.Min(_quantity * _itemPrice * 0.1, 100);  
6:    return basePrice - quantityDiscount + shipping;  
7:  }  

Example 2: The code after (using Extract Method)

1:  public double Price()  
2:  {  
3:    return BasePrice() - QuantityDiscount() + Shipping();  
4:  }  
6:  private int BasePrice()  
7:  {  
8:    return _quantity * _itemPrice;  
9:  }  
11:  private double QuantityDiscount()  
12:  {  
13:    return Math.Max(0, _quantity - 500) * _itemPrice * 0.05;  
14:  }  
16:  private double Shipping()  
17:  {  
18:    return Math.Min(_quantity * _itemPrice * 0.1, 100);  
19:  }  

Example 2: The code after (using Expression Body Definitions)

If you're using C# 6 or above you can use Expression Body Definitions to shorten your methods.

1:  public double Price()  
2:    => BasePrice - QuantityDiscount + Shipping;  
4:  private int BasePrice   
5:    => _quantity * _itemPrice;  
7:  private double QuantityDiscount   
8:    => Math.Max(0, _quantity - 500) * _itemPrice * 0.05;  
10:  private double Shipping  
11:    => Math.Min(_quantity * _itemPrice * 0.1, 100);  


Expressions can become very complex and hard to read. In such situations temporary variables can be helpful to break down the expression into something more manageable.
Introduce Explaining Variable is particularly valuable with conditional logic in which it is useful to take each clause of a condition and explain what the condition means with a well-named temp.

The source code

Personal thoughts

An easy-to-do refactoring that can do so much for the code readability. Low hanging fruit!

söndag 12 november 2017

Refactoring: Extract Method example in C#

Many years ago I read the book Refactoring - Improving the design of existing code by Martin Fowler and found that it contained lots of interesting thoughts about code readability.

Instead of just doing a reread of it, I thought it might be interesting to write about the refactors that I've had the most use of during my time as a (mostly web) developer.

The examples in the book are written i Java, I will copy and translate them to C#.

I begin the series with the Extract Method refactoring.

Extract Method

You have a code fragment that can be grouped together.
Turn the fragment into a method whose name explains the purpose of the method.

The code before

The example is a short method that prints out how much a customer owes.

1:  public void PrintOwing()  
2:  {  
3:    Decimal outstanding = 0;  
5:    // print banner  
6:    Console.Out.WriteLine("*************************");  
7:    Console.Out.WriteLine("***** Customer Owes *****");  
8:    Console.Out.WriteLine("*************************");  
10:    // calculate outstanding  
11:    foreach (var order in _orders)  
12:    {  
13:      outstanding += order.GetAmount();  
14:    }  
16:    // print details  
17:    Console.Out.WriteLine("name: " + _name);  
18:    Console.Out.WriteLine("amount: " + outstanding);  
19:  }  

The code after

The three sections in PrintOwing has been moved out to three separate methods, which makes the PrintOwing method really short and you get the big picture of what it does real easy.

1:  public void PrintOwing()  
2:  {  
3:    PrintBanner();  
4:    var outstanding = GetOutstanding();  
5:    PrintDetails(outstanding);  
6:  }  
8:  private void PrintBanner()  
9:  {  
10:    Console.Out.WriteLine("*************************");  
11:    Console.Out.WriteLine("***** Customer Owes *****");  
12:    Console.Out.WriteLine("*************************");  
13:  }  
15:  private decimal GetOutstanding()  
16:  {  
17:    Decimal outstanding = 0;  
18:    foreach (var order in _orders)  
19:    {  
20:      outstanding += order.GetAmount();  
21:    }  
22:    return outstanding;  
23:  }  
25:  private void PrintDetails(decimal outstanding)  
26:  {  
27:    Console.Out.WriteLine("name: " + _name);  
28:    Console.Out.WriteLine("amount: " + outstanding);  
29:  }  


The big wins with the extract method refactoring is that the code is divided into fine grained chunks that increases the chance of code reuse, and that the code itself can be read more like a series of comments.

How to Refactor

Read more about how to do this refactor step-by-step and more here.

The source code

Personal thoughts

Replace foreach with Linq

I really like to Linq-ify code when it makes the code shorter and better expresses what it does. Like replacing a foreach loop with Linqs Sum method.

I prefer this
1:  private decimal GetOutstanding()  
2:  {  
3:    return _orders.Sum(order => order.GetAmount());  
4:  }  

instead of this
1:  private decimal GetOutstanding()  
2:  {  
3:    Decimal outstanding = 0;  
4:    foreach (var order in _orders)  
5:    {  
6:      outstanding += order.GetAmount();  
7:    }  
8:    return outstanding;  
9:  }  

because I think Sum shows more clearly than the foreach loop what we're after.

Thoughts that popped up during writing

The PrintOwing method was short to begin with. Did the three extract method operations really make it better? I've performed the extract method on much longer methods, where I clearly saw the advantage, but here I don't find it quite as clear.

One thing that happens when you extract code to smaller methods is that its makes the code easier to reuse. Suppose I want to print the same banner from another method, after the refactoring I can just call the PrintBanner method instead of copy-pasting the code.

So, what's the problem with copy-paste coding? Well, suppose you need to print the same banner in five different methods. If you haven't extracted the banner printing code to a separate method the same code will exist at five places. What happens when your customer wants you to change the banner layout, maybe change the "*" to a "#"? Will you find every copy of the banner printing code? With five different copies of it, I think the risk is high that some of the copies will be forgotten to be changed, and voila, you've created a bug!

My guess is that although PrintOwing was short from the start, it is possible to understand the big picture about what it does faster when it is even shorter. Compare these two really hypothetical eye movement scanning examples when reading the code to get the big picture of what PrintOwing does.

In the example above, you have to read a lot of code to understand the big picture of what the code does. That's bad, but on the other side, you get a good bit of insight into the details. You can see that the eyes make big jumps up and down when looking for a variable and what value it has been assigned to, and how it has been used. Details are mixed with the bigger picture.

In this second example the eyes have to scan a lot less code and don't have to do big jumps to find out where the variable gets its value from.

Maybe you would scan the code in the first example a lot different than I've drawn. Maybe you scan for comments, read them and skip the code. Well, I read comments as well, but my experience is that way too often the comment related to the code does not really match the code. The comment says one thing, and the code does something like it but not quite, or maybe even something waaay off.
In this example, the comments are replaced with the names of the methods the code is extracted to, so the problem can still exist, if the method is given a bad name it won't match the code it contains.

lördag 9 september 2017

Livemap24, shows public transports on a map in "realtime"

The site Livemap24 shows millions of individually tracked public transport units on a navigatable map. It seems to be real time, but when reading discussions about it, it seems like they don't have enough data to be able to show exact positions for all of them. Some probably just are best guessed from a time table.

Cool idea that can be better when more open data becomes available!

Individually tracked bus in Årsta, Stockholm.

Is this heart rate signature normal? (Or is it a hardware / software / biological bug?)

During the current running season I bought myself a Garmin Forerunner 235 gps watch, which have given me more insights into my running. Before I didn't get statistics of my cadence or heart rate (and was a bit worried that my phone would take damage if it started to rain when out for a run).

Now that I have gathered heart rate statistics for a while, I see a recurring pattern in almost all of my heart rate diagrams. In the beginning of the run the heart rate is rather stable at a value, but suddenly there is a threshold and the heart rate jumps to a stable significantly higher pace.

I think it makes perfectly sense that the heart rate increases during running, but I find that steep rise a bit odd and therefore wonder what could cause it. I suspect that my wrist becoming sweaty after a while can play a role in this, but still, I think that wouldn't show up as that steep in the diagram.

This season I mostly have been running 5 km runs and haven't been doing any warm-up before starting running. 

Here are other diagrams.

This diagram looks more what I would suspect most of the diagrams would look like, but its kind is rare for me.

A seven km run with a jump from 120 to 170+ at around 3 km.

 A five km run with a jump from 140 to 170 at around 3,5 km.

A five km run with a jump from 120- to 160+ at around 1 km.

So, it this anything that looks familiar to you? In that case, any idea what causes the steep rise?

Want to learn? 3 months Pluralsight for free. If you haven't tried it, I really advise you to because I like it a lot!

I have taken a few courses on Pluralsight to learn about WPF, ASP.NET MVC and Linq. My experience is that it is a really fast way to get into something. The courses are nicely separated into different modules and sections, so if you feel you already know some of the content it is easy to navigate to the parts that you need to know more about.

And I prefer to learn something by having someone speaking about it than to just read about it.

To get your free months, you have to sign-up on Visual Studio in the cloud, but that's also free. Just follow the instructions linked below.


I'm on to learn some basics about Angular 2, just to get a grip on what it's about.

In case you use the offer, hope you'll have a nice learning experience!

tisdag 5 september 2017

"ToLookup" to the rescue when "GroupBy" or "ToDictionary" isn't quite right for the job

More than once I've been writing code using LINQs GroupBy and ToDictionary methods with a feeling that the code didn't become as clear as I wanted it to be. I did some web searching, hoping that there might exist a third party library with a smart solution, but what I found though, was that I didn't even have to install another library, LINQ already contained a method for it!

I'll try to show you how ToLookup can be useful with a phony example.


Suppose a group of smurfs take turn rolling a die and want us to print the result on the screen, like this:
 Smurfs that rolled a 1  
  - Grouchy Smurf  
  - Greedy Smurf  
 Smurfs that rolled a 2  
  - Smurfette  
 Smurfs that rolled a 3  
  - Papa Smurf  
  - Hefty Smurf  
 Smurfs that rolled a 4  
 Smurfs that rolled a 5  
  - Brainy Smurf  
 Smurfs that rolled a 6  
  - Clumsy Smurf  

For this I use a class to store each result in:
 class DieRollResult  
   public string Player { get; set; }  
   public int Value { get; set; }  

And a list to store all the results of a round in:
 var resultList = new List<DieRollResult>()  
   new DieRollResult{ Player= "Papa Smurf", Value = 3},  
   new DieRollResult{ Player= "Smurfette", Value = 2},  
   new DieRollResult{ Player= "Hefty Smurf", Value = 3},  
   new DieRollResult{ Player= "Brainy Smurf", Value = 5},  
   new DieRollResult{ Player= "Grouchy Smurf", Value = 1},  
   new DieRollResult{ Player= "Clumsy Smurf", Value = 6},  
   new DieRollResult{ Player= "Greedy Smurf", Value = 1},  

A solution using GroupBy

Notice the usage of SingleOrDefault to find the right group, it isn't possible to find it by using an index. 
Notice also that using this result set no smurf rolled a 4, and because empty groups like this are allowed a null check has to be done before iterating through the group to avoid a NullReferenceException.

A solution using GroupBy combined with ToDictionary

This time, notice the rather verbose expression to assign the variable resultGroups.
Notice also that this time, the group can be fetched using an index, but we still have to check if the dictionary really contains that index key to avoid a KeyNotFoundException.

A solution using ToLookup

So, finally, by using the ToLookup method, the assignment of the variable resultGroups is as short and clear as in the GroupBy example.
It is also possible to use an index to get the right group to iterate through. And since the ILookup object just returns an empty IEnumerable when it is indexed with a key that it doesn't contain, there is no need to check for null or if the key exists like we had to do in the other examples!

This is why I like the ToLookup method, it raises the signal-to-noise ratio a tiny bit, but sometimes it is just that small improvement that can make the code clearer. 

On the downside though, the method seems to be used so seldom that I think few programmers have seen it, so using it might make the code break the "Principle of least surprise".

måndag 28 augusti 2017

How to show nicely formatted source code in your blogger posts

I haven't dug deep into this, but so far the site below has been enough.


  • Copy and paste the code you want formatted into the top form
  • Click "Format Source Code" button
  • Copy the generated html code and paste it into your post in html mode

Time to clean up the repo? Commands to list and sort git branches

As a preparation for a future branch cleanup in our git repos at work I googled for and tried a few branch listing and sorting commands that might come in handy.

List branches 
sorted by last commit date
 git for-each-ref --sort=committerdate refs/remotes/ --format='%(committerdate:short) %(refname:short)'  

Example result
 2016-09-05 origin/PBI-0096  
 2016-10-02 origin/PBI-146   
 2016-11-25 origin/PBI-1320  

List branches 
with age and last committer name 
sorted by last commit date
 for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ai %ar by %an" $branch | head -n 1` \\t$branch; done | sort -r  

Example result
 2016-10-06 16:17:17 +0200 11 months ago by Harry Potter     origin/PBI-88  
 2016-10-05 14:24:24 +0200 11 months ago by Joe Labero    origin/PBI-146  
 2016-09-02 12:10:17 +0200 12 months ago by Nicola Tesla    origin/PBI-0096  

List branches 
with age and last committer name 
sorted by last committer
 for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --pretty=format:"%Cred %cn %>|(40) %Cblue %ar %>|(80) %Creset" $branch | head -n 1` $branch; done | sort -r  

Example result
 Harry Potter 3 days ago origin/PBI-5124  
 Harry Potter 8 weeks ago origin/PBI-4584  
 Harry Potter 2 days ago origin/PBI-5129  
 Joe Labero 7 weeks ago origin/PBI-4590  
 Joe Labero 6 weeks ago origin/PBI-4742  

onsdag 9 augusti 2017

Anyone else having the same kind of double vision?

I think I've had double vision for a long time, but maybe it has become worse the last five years or maybe it just has started to bug me more than before.

Here are two examples that show how text can appear for me.

Here are some characteristics of the phenomenon:

  1. The duplicate image is less prominent than the original image, it's like a shadow of the original image. The color of the duplicate looks like a washed-out version of the original.
  2. The duplicate image always appear moved upwards compared to the original.
  3. The duplicate appear the same when using both eyes or one eye at a time, regardless of which eye I look with.
  4. The farther away from the original I am, the higher up the duplicate appear.
  5. The duplicate disappears when looking through the top edge of the glasses. Looking through a small hole also makes it disappear.

I've been to an ophthalmologist three times. The first time he suspected an incipient cataract or keratoconus (a bulging cornea). But after my two revisits both those suspicions got depreciated. And no new ideas came up :(
I also have a minor squint, but that can't be the source of the problem since the duplicate appears even when I look with one eye at a time.

I don't know the exact strength of my glasses, but it is around -6 for both eyes. The values for the astigmatism correction I have no clue about, have to check it up...

The double vision really bugs me when:
  • Trying to help someone with his code by sitting beside him and look at the code on his monitor from the side. The duplicate characters make the code unreadable.
  • Meeting persons on the street. Since faces also get distorted by the double vision, it makes it hard to know if it's a person I know or not until coming pretty close.
  • Looking at subtitled movies on the TV
  • Driving in darkness, it's hard to read signs from far away

So, since both the ophthalmologist and the optician are clueless, it would be nice to know if anyone else has experienced this, or even better, if anyone knows what it could be and how to fix it!

onsdag 21 juni 2017

"Software" books that make me wanna start my own business

Here's a short list of books that have been mentioned in the developer podcasts I listen to. I've read two of them, and it started an itch, an itch to try start my own business. Really get the thoughts flowing. Maybe it will for you too?

Developer Hegemony

The Future of Labor
Erik Dietrich

Erik explains what he thinks is wrong with software corporate structure. He divides the employees into three categories, pragmatists (the coders that just want to make a living), idealists (the bosses that live the company culture and put in lots of extra hours to become an opportunist, but never will be) and opportunists (company founders/owners) and uses these categories to describe the work life in companies of today. He wants to see a transformation of software creation and proposes people starting their own single-person businesses and join forces when needed. He want us to become something that he calls efficiencers.

He is a guest in these podcasts and talks about his ideas and his book there:

He's also a guest in this older episode:

His blog:

Soft Skills

The software developer's life manual
John Z. Sonmez

John goes through the important things you as a software developer need to know careerwise. Giving tips about what to think about when working at a company, for starting your own startup, marketing yourself, learning and teaching.

He's been a guest in these podcasts:

Do you see a pattern? :)

His blog:

Escape 9-5, Live Anywhere, and Join the New Rich
Timothy Ferriss

I haven't read this book yet, was just about to, but felt a bit overwhelmed of this "genre" after reading Developer Hegemony. When reading up on it now, it doesn't seem software related either, but my impression is that the tips might fit a developer that are about to start something of his own.

It was interesting listening to him on the podcast anyway (or, well, when searching for the podcast I was sure I had heard him in the first time, I can't no longer find it. He and his book was probably mentioned by some other interesting guest...). 

Here is a recording of Scott Hanselmans interview with him anyway. 

And his blog

onsdag 14 juni 2017

How to activate the detailed scroll bar in Visual Studio

I haven't been using the detailed scroll bar in Visual Studio much and it probably is more shiny than useful. But still, if you have some screen space to spare, you can as well activate it, because suddenly it might come in handy!

So, what does it really do for you? It shows you the code in the active tab... in the scroll bar!!


To activate it, goto Tools > Options > Text Editor
To use it for all languages, proceed with All languages > Scroll Bars > Behavior
  • Select Use map mode for vertical scroll bar
  • Check the Show Preview Tooltip check box to get the preview on hoover.
  • Select the look of the map, Off (to only have the preview tooltip), Narrow, Medium or Wide

Click OK and watch the magic happen! =)

måndag 5 juni 2017

How to edit the Where-clause in "Edit Top 200 Rows" in SQL Server Management Studio

When you want to edit data in a table directly in the table without writing any update queries, you can right-click the table in the SQL Server Management Studio and select "Edit Top 200 Rows" in the menu.

Then you can go from cell to cell and edit the values for the top 200 rows in a view like the one below.

But what if the top 200 rows aren't the rows you want to edit? You would like add a where clause to select the rows you edit. There is a way, when standing in a "Edit Top 200 Rows" view, a few extra icons are added to the toolbar. Locate the one that has the text SQL on it. Click on it to show an SQL pane.

In the SQL pane you can edit the query as you like. 

When you're done with the query editing, locate and click on the "Execute SQL" button to update the content in the editable table view.

Good luck, have fun! :)

söndag 4 juni 2017

"Learn Git Branching", the site that finally made me get a grip on git!

My git journey


Sometimes I feel lucky that the first company I worked for as a software developer was using Subversion instead of SourceSafe. As I remember it, Subversion together with the Windows Explorer integrated Subversion client TortoiseSvn, was pretty easy to learn and felt as a great tool. Sure, there were some gotchas, but still, the learning curve felt pretty flat.

When I moved on, from employment to employment, the companies I came to often used SourceSafe. I could cope with that, because I used Subversion on the side. After many years as a Subversion user, I heard about the greatness of git and tried a few times to get a grip on it... but didn't get it. One of the reasons to that was that as a TortoiseSvn user I thought that TortoiseGit would be almost the same experience. The image below is what you meet when trying to get the source code to your computer, lots of checkboxes I didn't have a clue what they did!

I gave up rather fast, but tried again, and gave up, and so on. 


Finally I found the git visual client SourceTree, that was powerful enough to let me do most of the things I needed. Some visual clients was so stripped that it wasn't possible to do anything but the simplest commands. With SourceTree I could finally work with git and began to learn, but the learning curve felt steep, and the fact that I came from Subversion probably made it steeper than if I hadn't had the Subversion thinking. Anyway, now I learned things, but still many things felt really confusing.

Learn Git Branching

One day, I found the site http://learngitbranching.js.org/ Spending some time on that site made a big difference! Suddenly I got a feel for the differences between Subversion and git branches! The two top reasons I find the site so great is that you solve problems using real git commands and that it shows visually what happens with the commits and branches.


Learning git on my own, using SourceTree and the "Learn Git Branching" site, made it possible for me, on my latest employment, to do the migration of the source code from TFVC to git, set up a branching strategy, and to help my collegues get a quick start with git so they didn't have to take the same long journey as me =)

tisdag 30 maj 2017

Delete batches of tags in git

List tags

To list all tags, run
git tag

To list tags matching a pattern, use
git tag -l name_pattern 

For example, to list all tags with a name that begins with Release
git tag -l Release*

Delete tags locally

To delete a single tag
git tag -d name_of_tag

To delete multiple tags
git tag -d name_of_tag1 name_of_tag2

To delete all tags locally
git tag | xargs git tag -d  
(xargs takes the output from the first command and passes it as argument to the next)

To delete all tags that matches a name pattern
git tag -l Release* | xargs git tag -d

Delete tags on the remote

Assuming the remote is named origin and you want to delete all release tags for the 1.x and 2.x releases
git tag -l {Release/1.*,Release/2.*} | xargs git push --delete origin

REMEMBER to make sure that your pattern ONLY matches the tags that you want to delete. Inspect the result from the listing of matched tags before piping them to the next command.

Screenshot tool: Lightshot

Lightshot is a program that you can install for free in Windows (or Mac).

When installed, just press the Print Screen button and then select the area on the screen that you want captured.

When an area has been selected, it is possible to add text, arrows, boxes or freehand forms. When done, it's possible to copy the result to clipboard, save it to disk, print it or search for similar images on Google.

A really handy tool!

Download here

Revert a merge commit using SourceTree

Update 1 (no need to investigate the parents)

The use case I need this for is when a feature branch has been merged to master, and after that something arises that makes us want to remove that feature from the master branch again. In the text below I describe how to find the parents of a merge commit, but since the checked out branch always will become the parent number one when merging in another branch, the investigation of the parents isn't needed. The only command needed is therefore
git revert the_hash_of_the_commit_to_revert -m 1

Update 2 (commands for the commit message editor)

When the commit message editor opens up, just accept and exit by writing 
Or, if you want to change the commit message, press i, write your message and then
<Esc> :wq <Enter>

Revert a "normal" commit

Normally when you want to undo the changes of a commit that has been pushed, you can do a reverse commit inside SourceTree by doing a right click on the commit and choose "Reverse commit..." like in the image below.

But if the commit you're trying to reverse is a merge commit you'll get the message:

git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=manager-st revert --no-edit 5a1f18d0d344e4ce9f23b02752cf4674c973cdf4
error: Commit 5a1f18d0d344e4ce9f23b02752cf4674c973cdf4 is a merge but no -m option was given.
fatal: revert failed

Completed with errors, see above.

Which means you've got to use the Terminal window.

Revert a merge commit

The case

Suppose we have the state as seen in the image below. Suddenly we realize that the changes made in the demo_branch are wrong and have to be removed from the master branch.

To do this we have to issue the revert command and specify the -m option. The -m option specifies which of the parents that was the mainline that we want the resulting code to be like.

Identify the commit to revert

The commit we want to undo is the commit with id 0c9c102

Find the correct parent

To the right in the button bar in the top of SourceTree window there is a button for opening the Terminal window.

Click on it and you'll see the Terminal window below.

Run the command git log to list the commits. Find the commit we want to revert (when you´ve found your commit, stop the listing with ctrl-z). In the image below we see that commit 0c9c102 is a merge, having two parents with the ids 618383a (parent 1) and b8a9ad7 (parent 2).

In this case we want to use the commit in the master branch as parent, the commit with id 618383a that is. That parent was listed in the log as the first parent, therefore we refer to it as parent 1.

Execute the revert command

To recap, we want to revert the commit 0c9c102 using parent 1 as the index to the -m (mainline) option. Therefore the command to write in the terminal window becomes:

git revert 0c9c102 -m 1

After issuing the command an editor for editing the commit message opens up (see below). To accept the default message and exit the editor, press Esc and then ZZ.

Now a new commit has been added, which reverts the changes introduced by the merge commit.



In case you had a hard time following my explanation, maybe the answers in the sources I used can help you.