Merge conflicts in source control

This article originally appeared on earthli News and has been cross-posted here.


I was recently asked a question about merge conflicts in source-control systems.

[...] there keep being issues of files being over written, changes backed out etc. from people coding in the same file from different teams.

My response was as follows:

tl;dr: The way to prevent this is to keep people who have no idea what they're doing from merging files.

Extended version

Let's talk about bad merges happening accidentally. Any source-control worth its salt will support at least some form of automatic merging.

An automatic merge is generally not a problem because the system will not automatically merge when there are conflicts (i.e. simultaneous edits of the same lines, or edits that are "close" to one another in the base file).

An automatic merge can, however, introduce semantic issues.

For example if both sides declared a method with the same name, but in different places in the same file, an automatic merge will include both copies but the resulting file won't compile (because the same method was declared twice).

Or, another example is as follows:

Base file

public void A(B b)
{
  var a = new A();

  b.Do(a);
  b.Do(a);
  b.Do(a);
}

Team One version

public void A(B b)
{
  var a = new A();

  b.Do(a);
  b.Do(a);
  b.Do(a);
  a.Do();
}

Team Two version

public void A(B b)
{
  var a = null;

  b.Do(a);
  b.Do(a);
  b.Do(a);
}

Automatic merge

public void A(B b)
{
  var a = null;

  b.Do(a);
  b.Do(a);
  b.Do(a);
  a.Do();
}

The automatically merged result will compile, but it will crash at run-time. Some tools (like ReSharper) will display a warning when the merged file is opened, showing that a method is being called on a provably null variable. However, if the file is never opened or the warning ignored or overlooked, the program will crash when run.

In my experience, though, this kind of automatic-merge "error" doesn't happen very often. Code-organization techniques like putting each type in its own file and keeping methods bodies relatively compact go a long way toward preventing such conflicts. They help to drastically reduce the likelihood that two developers will be working in the same area in a file.

With these relatively rare automatic-merge errors taken care of, let's move on to errors introduced deliberately through maliciousness or stupidity. This kind of error is also very rare, in my experience, but I work with very good people.

Let's say we have two teams: Team One - branch one Works on file 1 Team Two - branch two Works on file 1 Team One promotes file 1 into the Master B branch, there are some conflicts that they are working out but the file is promoted.

I originally answered that I wasn't sure what it meant to "promote" a file while still working on it. How can a file be commited or checked in without having resolved all of the conflicts?

As it turns out, it can't. As documented in TFS Server 2012 and Promoting changes, promotion simply means telling TFS to pick up local changes and add them to the list of "Pending Changes". This is part of a new TFS2012 feature called "Local Workspaces". A promoted change corresponds to having added a file to a change list in Perforce or having staged a file in Git.

The net effect, though, is that the change is purely local. That is has been promoted has nothing to do with merging or committing to the shared repository. Other users cannot see your promoted changes. When you pull down new changes from the server, conflicts with local "promoted" changes will be indicated as usual, even if TFS has already indicated conflicts between a previous change and another promoted, uncommitted version of the same file. Any other behavior else would be madness.1

Team Two checks in their file 1 into the Master B branch. They back out the changes that Team One made without telling anyone anything.

There's your problem. This should never happen unless Team Two has truly determined that their changes have replaced all of the work that Team One did or otherwise made it obsolete. If people don't know how to deal with merges, then they should not be merging.

Just as Stevie Wonder's not allowed behind the wheel of a car, neither should some developers be allowed to deal with merge conflicts. In my opinion, though, any developer who can't deal with merges in code that he or she is working on should be moved another team or, possibly, job. You have to know your own code and you have to know your tools.2

Team One figures out the conflicts in their branch and re-promotes file one (and other files) to Master B branch. The source control system remembers that file 1 was backed out by Team Two so it doesn't promote file 1 but doesn't let the user know.

This sounds insane. When a file is promoted -- i.e. added to the pending changes -- it is assumed that the current version is added to the pending changes, akin to staging a file in Git. When further changes are made to the file locally, the source-control system should indicate that it has changed since having been promoted (i.e. staged).

When you re-promote the file (re-stage it), TFS should treat that as the most recent version in your workspace. When you pull down the changes from Team 2, you will have all-new conflicts to resolve because your newly promoted file will still be in conflict with the changes they made to "file 1" -- namely that they threw away all of the changes that you'd made previously.

And, I'm not sure how it works in TFS, but in Git, you can't "back out" a commit without leaving a trail:

  • Either there is a merge commit where you can see that Team Two chose to "accept their version" rather than "merge" or "accept other version"
  • Or, there is a "revert" commit that "undoes" the changes from a previous commit

Either way, your local changes will cause a conflict because they will have altered the same file in the same place as either the "merge" or "revert" commit and -- this is important -- will have done so after that other commit.

To recap, let me summarize what this sounds like:

  • T1: I want to check in file1
  • TFS: You have conflicts
  • T1: Promote file1 so that TFS knows about (other users can't see it yet because it hasn't been committed)
  • TFS: Okie dokie
  • T2: I want to check in file1
  • TFS: You have conflicts
  • T2: F&#$ that. Use my version. Oh, and, f&#$ T1.
  • TFS: I hear and obey. T2/file1 it is.
  • T1: OK, I resolved conflicts; here's the final version of file1
  • TFS: Thanks! tosses T1/file1 out the window

I don't believe that this is really possible -- even with TFS -- but, if this is a possibility with your source-control, then you have two problems:

  1. You have team members who don't know how to merge
  2. Your source control is helping them torpedo development

There is probably a setting in your source-control system that disallows simultaneous editing for files. This is a pretty huge restriction, but if your developers either can't or won't play nice, you probably have no choice.



  1. This is not to rule out such behavior 100%, especially in a source-control system with which I am largely unfamiliar. It only serves to indicate the degree to which I would be unwilling to work with any system that exhibits this kind of behavior.

  2. Different companies can have different grace periods for learning these two things, of course. I suppose that grace period can be interminably long, but...

Windows Live accounts and Windows 8

This article originally appeared on earthli News and has been cross-posted here.


image

tl;dr: If your Windows 8 is mysteriously moving your Windows and taskbar around, it might be because of your Windows Live account synchronizing settings from one machine to another.

Starting with Windows 8, you can connect your local user account to your Windows Live account, sharing your preferences and some Windows-App-Store application settings and logins.

I had this enabled for a while but recently discovered that it was responsible for mysterious issues I'd been experiencing on my desktop at work and my laptop at home.

The advantage of using a synchronized account is that, once you log in to Windows 8 with these settings -- no matter where -- you'll get a familiar user interface. Two of the more visible, if mundane, settings are the lock-screen wallpaper and the desktop wallpaper.

Synchronizing wallpaper makes sense because, if you took the time to change the desktop on one machine, there's a good chance you want to have the same desktop on another.

On the other hand, I wonder how many people will be surprised to see the racy and dubiously work-friendly desktop wallpaper that they chose for their home computer automatically show up when they log in at work on Monday morning. Especially if they updated the lock screen as well as the desktop wallpaper. While this type of synchronizing might endanger one's employment status, it's also exactly the kind of synchronizing that I would expect from Windows because it's not hardware-specific.

For the last several months, I've been smoke-testing Windows 8 for general use at Encodo and it's mostly been a quite pleasant upgrade from Windows 7. I don't really make much use of features from Windows 8, but it's very stable and noticeably faster on startup and coming back from hibernate than its predecessor.

Though there are some minor quibbles1, it was generally a no-brainer upgrade -- except that Windows could not seem to remember the taskbar location on either my laptop at home or the desktop at work.

Maybe you see where this is going.

In hindsight, it's bloody obvious that the taskbar location was also being synced over the Windows Live account cloud but, in my defense, Windows moves my application windows around a lot. I have two monitors and if one of them is turned off or goes into a deep sleep, Windows will oblige by moving all windows onto the remaining monitor.2 When you restore the missing monitor back to life, Windows does nothing to help you and you have to move everything back manually. At any rate, the taskbar being moved around coincided enough with other windows being moved around that I figured it was just Windows 8 being flaky.

That the issue also happened on the laptop at home was decidedly odd, though.

Now that I know what was causing the problem, I've turned off the synchronization and each copy of Windows 8 now remembers where it's taskbar was. I guess that, in the trivial situation, where the hardware is the same on both ends, it would make sense to synchronize this setting. But in my situation, where one side has a 15.4" laptop screen and the other has two monitors -- one 24" and the other 27" -- it makes no sense at all.

It's a bit of a shame that I had to resort to the rather heavy-handed solution of simply turning of synchronization entirely but I couldn't find a more fine-grained setting. The Windows 8 UI is pretty dumbed down, so there are only controls for ON and OFF.



  1. The Windows-App-store UI for wireless networks and settings is poorly made. There is no consistency to whether you use a right or left click and you can only choose to "forget" a network rather than just disconnect from it temporarily.

  2. And resizing them to fit! Yay! Thanks for your help, Windows!

Networking event #1 2013: Working with HTML5

Our first networking event of the year is scheduled for tonight (19.04) with a presentation on HTML5 development. The talk, to be presented by Marco, will cover our experiences developing a larger project for the web.

Here's the main overview:

  • Project parameters: what did we build?

  • Components, libraries and features

    • HTML5 tags & objects
    • CSS3 concepts
    • jQuery basics
  • Tools

    • IDE & Browser
    • Testing & Optimization

You can find the entire presentation in the documents section.

A provably safe parallel language extension for C#

This article originally appeared on earthli News and has been cross-posted here.


The paper Uniqueness and Reference Immutability for Safe Parallelism by Colin S. Gordon, Matthew J. Parkinson, Jared Parsons, Aleks Bromfield, Joe Duffy is quite long (26 pages), detailed and involved. To be frank, most of the notation was foreign to me -- to say nothing of making heads or tails of most of the proofs and lemmas -- but I found the higher-level discussions and conclusions quite interesting.

The abstract is concise and describes the project very well:

A key challenge for concurrent programming is that side-effects (memory operations) in one thread can affect the behavior of another thread. In this paper, we present a type system to restrict the updates to memory to prevent these unintended side-effects. We provide a novel combination of immutable and unique (isolated) types that ensures safe parallelism (race freedom and deterministic execution). The type system includes support for polymorphism over type qualifiers, and can easily create cycles of immutable objects. Key to the system's flexibility is the ability to recover immutable or externally unique references after violating uniqueness without any explicit alias tracking. Our type system models a prototype extension to C# that is in active use by a Microsoft team. We describe their experiences building large systems with this extension. We prove the soundness of the type system by an embedding into a program logic.

The project proposes a type-system extension with which developers can write provably safe parallel programs -- i.e. "race freedom and deterministic execution" -- with the amount of actual parallelism determined when the program is analyzed and compiled rather than decided by a programmer creating threads of execution.

Isolating objects for parallelism

The "isolation" part of this type system reminds me a bit of the way that SCOOP addresses concurrency. That system also allows programs to designate objects as "separate" from other objects while also releasing the program from the onus of actually creating and managing separate execution contexts. That is, the syntax of the language allows a program to be written in a provably correct way (at least as far as parallelism is concerned; see the "other provable-language projects" section below). In order to execute such a program, the runtime loads not just the program but also another file that specifies the available virtual processors (commonly mapped to threads). Sections of code marked as "separate" can be run in parallel, depending on the available number of virtual processors. Otherwise, the program runs serially.

In SCOOP, methods are used as a natural isolation barrier, with input parameters marked as "separate". See SCOOP: Concurrency for Eiffel and SCOOP (software) for more details. The paper also contains an entire section listing other projects -- many implemented on the the JVM -- that have attempted to make provably safe programming languages.

The system described in this paper goes much further, adding immutability as well as isolation (the same concept as "separate" in SCOOP). An interesting extension to the type system is that isolated object trees are free to have references to immutable objects (since those can't negatively impact parallelism). This allows for globally shared immutable state and reduces argument-passing significantly. Additionally, there are readable and writable references: the former can only be read but may be modified by other objects (otherwise it would be immutable); the latter can be read and written and is equivalent to a "normal" object in C# today. In fact, "[...] writable is the default annotation, so any single-threaded C# that does not access global state also compiles with the prototype."

Permission types

In this safe-parallel extension, a standard type system is extended so that every type can be assigned such a permission and there is "support for polymorphism over type qualifiers", which means that the extended type system includes the permission in the type, so that, given B => A, a reference to readable B can be passed to a method that expects an immutable A. In addition, covariance is also supported for generic parameter types.

When they say that the "[k]ey to the system's flexibility is the ability to recover immutable or externally unique references after violating uniqueness without any explicit alias tracking", they mean that the type system allows programs to specify sections that accept isolated references as input, lets them convert to writable references and then convert back to isolated objects -- all without losing provably safe parallelism. This is quite a feat since it allows programs to benefit from isolation, immutability and provably safe parallelism without significantly changing common programming practice. In essence, it suffices to decorate variables and method parameters with these permission extensions to modify the types and let the compiler guide you as to further changes that need to be made. That is, an input parameter for a method will be marked as immutable so that it won't be changed and subsequent misuse has to be corrected.

Even better, they found that, in practice, it is possible to use extension methods to allow parallel and standard implementations of collections (lists, maps, etc.) to share most code.

A fully polymorphic version of a map() method for a collection can coexist with a parallelized version pmap() specialized for immutable or readable collections. [...] Note that the parallelized version can still be used with writable collections through subtyping and framing as long as the mapped operation is pure; no duplication or creation of an additional collection just for concurrency is needed.

Real projects and performance impact

Much of the paper is naturally concerned with proving that their type system actually does what it says it does. As mentioned above, at least 2/3 of the paper is devoted to lemmas and large swaths of notation. For programmers, the more interesting part is the penultimate section that discusses the extension to C# and the experiences in using it for larger projects.

A source-level variant of this system, as an extension to C#, is in use by a large project at Microsoft, as their primary programming language. The group has written several million lines of code, including: core libraries (including collections with polymorphism over element permissions and data-parallel operations when safe), a webserver, a high level optimizing compiler, and an MPEG decoder.

Several million lines of code is, well, it's an enormous amount of code. I'm not sure how many programmers they have or how they're counting lines or how efficiently they write their code, but millions of lines of code suggests generated code of some kind. Still, taken with the next statement on performance, that much code more than proves that the type system is viable.

These and other applications written in the source language are performance-competitive with established implementations on standard benchmarks; we mention this not because our language design is focused on performance, but merely to point out that heavy use of reference immutability, including removing mutable static/global state, has not come at the cost of performance in the experience of the Microsoft team.

Not only is performance not impacted, but the nature of the typing extensions allows the compiler to know much more about which values and collections can be changed, which affects how aggressively this data can be cached or inlined.

In fact, the prototype compiler exploits reference immutability information for a number of otherwise-unavailable compiler optimizations. [...] Reference immutability enables some new optimizations in the compiler and runtime system. For example, the concurrent GC can use weaker read barriers for immutable data. The compiler can perform more code motion and caching, and an MSIL-to-native pass can freeze immutable data into the binary.

Incremental integration ("unstrict" blocks)

In the current implementation, there is an unstrict block that allows the team at Microsoft to temporarily turn off the new type system and to ignore safety checks. This is a pragmatic approach which allows the software to be run before it has been proven 100% parallel-safe. This is still better than having no provably safe blocks at all. Their goal is naturally to remove as many of these blocks as possible -- and, in fact, this requirement drives further refinement of the type system and library.

We continue to work on driving the number of unstrict blocks as low as possible without over-complicating the type systems use or implementation.

The project is still a work-in-progress but has seen quite a few iterations, which is promising. The paper was written in 2012; it would be very interesting to take it for a test drive in a CTP.

Other provable-language projects

A related project at Microsoft Research Spec# contributed a lot of basic knowledge about provable programs. The authors even state that the "[...] type system grew naturally from a series of efforts at safe parallelism. [...] The earliest version was simply copying Spec#s [Pure] method attribute, along with a set of carefully designed task-and data-parallelism libraries." Spec#, in turn, is a "[...] formal language for API contracts (influenced by JML, AsmL, and Eiffel), which extends C# with constructs for non-null types, preconditions, postconditions, and object invariants".

Though the implementation of this permissions-based type system may have started with Spec#, the primary focus of that project was more a valiant attempt to bring Design-by-Contract principles (examples and some discussion here) to the .NET world via C#. Though spec# has downloadable code, the project hasn't really been updated in years. This is a shame, as support for Eiffel[^1] in .NET, mentioned above as one of the key influences of spec#, was dropped by ISE Eiffel long ago.

Spec#, in turn, was mostly replaced by Microsoft Research's Contracts project (an older version of which was covered in depth in Microsoft Code Contracts: Not with a Ten-foot Pole). The Contracts project seems to be alive and well: the most recent release is from October, 2012. I have not checked it out since my initial thumbs-down review (linked above) but did note in passing that the implementation is still (A) library-only and (B) does not support Visual Studio 2012.

The library-only restriction is particularly galling, as such an implementation can lead to repeated code and unwieldy anti-patterns. As documented in the Contracts FAQ, the current implementation of the "tools take care of enforcing consistency and proper inheritance of contracts" but this is presumably accomplished with compiler errors that require the programmer to include contracts from base methods in overrides.

The seminal work Object-oriented Software Construction by Bertrand Meyer (vol. II in particular) goes into tremendous detail on a type system that incorporates contracts directly. The type system discussed in this article covers only parallel safety: null-safety and other contracts are not covered at all. If you're at all interested in these types of language extensions, the vol.2 of OOSC is a great read. The examples are all in Eiffel but should be relatively accessible. Though some features -- generics, notably but also tuples, once routines and agents -- have since made their way into C# and other more commonly used languages, many others -- such as contracts, anchored types (contravariance is far too constrained in C# to allow them), covariant return types, covariance everywhere, multiple inheritance, explicit feature removal, loop variants and invariants, etc. -- are still not available. Subsequent interesting work has also been done on extensions that allow creation of provably null-safe programs, something also addressed in part by Microsoft Research's Contracts project.

v1.8.6: Bug fix release for v1.8.5 (no new features)

The summary below describes major new features, items of note and breaking changes. The full list of issues is also available for those with access to the Encodo issue tracker.

Highlights

Breaking changes

No known breaking changes

Programming in the moderncurrent age

This article originally appeared on earthli News and has been cross-posted here.


In order to program in 2013, it is important not to waste any time honing your skills with outdated tools and work-flows. What are the essential pieces of software for developing software in 2013?

Runtime

A runtime is a given for all but the most esoteric of programming exercises. Without something to execute your code, there is almost no point in writing it.

Debugger

Programming without an integrated debugger can be very time-consuming, error-prone and will quite frankly suck the fun right out of the whole endeavor. And, by "debugger" I mean a source-level single-step debugger with call-stack and variable/object/structure inspection as well as expression evaluation. Poring through logs and inserting print statements is not a viable long-term or even medium-term solution. You shouldn't be writing in a language without one of these unless you absolutely can't avoid it (NAnt build scripts come to mind).

Compiler/Checker

A syntax/semantics checker of some sort integrated into the editor ensures a tighter feedback/error-finding loop and saves time, energy and frustration. I was deliberately cagey with the "checker" because I understand that some languages, like Javascript1, do not have a compiled form. Duck-typed languages like Python or Ruby also limit static checking but anything is better than nothing.

Versioning

A source-control system is essential in order to track changes, test ideas and manage releases. A lot of time can be wasted -- and effort lost -- without good source control. Great source control decreases timidity, encourages experimentation and allows for interruptible work-flows. I will argue below that private branches and history rewriting are also essential.

Even for the smallest projects, there is no reason to forgo any of these tools.

Managing your Source Code

tl;dr: It's 2013 and your local commit history is not sacrosanct. No one wants to see how you arrived at the solution; they just want to see clean commits that explain your solution as clearly as possible. Use git; use rebase; use "rebase interactive"; use the index; stage hunks; squash merge; go nuts.2

imageI would like to focus on the "versioning" part of the tool-chain. Source control tells the story of your code, showing how it evolved to where it is at any given point. If you look closely at the "Encodo Branching Model"3 diagram (click to enlarge), you can see the story of the source code:

  1. All development was done in the master branch until v1.0 was released
  2. Work on B was started in a feature branch
  3. Work on hotfix v1.0.1 was started in a hotfix branch
  4. Work on A was started in another feature branch
  5. Hotfix v1.0.1 was released, tagged and merged back to the master branch
  6. Development continued on master and both feature branches
  7. Master was merged to feature branch A (includes hotfix v1.0.1 commits)
  8. Finalization for release v1.1 was started in a release branch
  9. Feature A was completed and merged back to the master branch
  10. Version v1.1 was released, tagged and merged back to the master branch
  11. Master was merged to feature branch B (includes v1.1 and feature A commits)
  12. Development continued on master and feature B
  13. Version v1.2 was released and tagged

Small, precise, well-documented commits are essential in order for others to understand the project -- especially those who weren't involved in developing the code. It should be obvious from which commits you made a release. You should be able to go back to any commit and easily start working from there. You should be able to maintain multiple lines of development, both for maintenance of published versions and for development of new features. The difficulty of merging these branches should be determined by the logical distance between them rather than by the tools. Merging should almost always be automatic.

Nowhere in those requirements does it say that you're not allowed to lie about how you got to that pristine tree of commits.

Why you should be using private branches and history rewriting

A few good articles about Git have recently appeared -- Understanding the Git Workflow by Benjamin Sandofsky is one such -- explaining better than ever why rewriting history is better than server-side, immutable commits.

In the article cited above, Sandofsky divides his work up into "Short-lived work [...] larger work [...] and branch bankrupty." These concepts are documented to some degree in the Branch Management chapter of the Encodo Git Handbook (of which I am co-author). I will expand on these themes below.

Note: The linked articles deal exclusively with the command line, which isn't everyone's favorite user interface (I, for one, like it). We use the SmartGit/Hg client for visualizing diffs, organizing commits and browsing the log. We also use the command-line for a lot of operations, but SmartGit is a very nice tool and version 3 supports nearly all of the operations described in this article.

What is rebasing?

As you can see from the diagram above, a well-organized and active project will have multiple branches. Merging and rebasing are two different ways of getting commits from one branch into another.

Merging commits into a branch creates a merge commit, which shows up in the history to indicate that n commits were made on a separate branch. Rebasing those commits instead re-applies those commits to the head of the indicated branch without a merge commit. In both cases there can be conflicts, but one method doesn't pose a greatest risk of them than the other.4 You cannot tell from the history that rebased commits were developed in a separate branch. You can, however, tell that the commits were rebased because the author date (the time the commit was originally created) differs from the commit date (the last time that the commit was applied).

What do you recommend?

At Encodo, we primarily work in the master branch because we generally work on very manageable, bite-sized issues that can easily be managed in a day. Developers are free to use local branches but are not required to do so. If some other requirement demands priority, we shunt the pending issue into a private branch. Such single-issue branches are focused and involve only a handful of files. It is not at all important to "remember" that the issue was developed in a branch rather than the master branch. If there are several commits, it may be important for other users to know that they were developed together and a merge-commit can be used to indicate this. Naturally, larger changes are developed in feature branches, but those are generally the exception rather than the rule.

Remember: Nowhere in those requirements does it say that you're not allowed to lie about how you got to that pristine tree of commits.

Otherwise? Local commit history is absolutely not sacrosanct. We rebase like crazy to avoid unwanted merge commits. That is, when we pull from the central repository, we rebase our local commits on top of the commits that come form the origin. This has worked well for us.

If the local commit history is confusing -- and this will sometimes come up during the code review -- we use an interactive rebase to reorganize the files into a more soothing and/or understandable set of commits. See Sandofsky's article for a good introduction to using interactive rebasing to combine and edit commits.

Naturally, we weigh the amount of confusion caused by the offending commits against the amount of effort required to clean up the history. We don't use bisect5 very often, so we don't invest a lot of time in enforcing the clean, compilable commits required by that tool. For us, the history is interesting, but we rarely go back farther than a few weeks in the log.6

When to merge? When to rebase?

At Encodo, there are only a few reasons to retain a merge commit in the official history:

  1. If we want to remember which commits belonged to a particular feature. Any reasonable tool will show these commits graphically as a separate strand running alongside the master branch.
  2. If a rebase involves too much effort or is too error-prone. If there are a lot of commits in the branch to be integrated, there may be subtle conflicts that resolve more easily if you merge rather than rebase. Sometimes we just pull the e-brake and do a merge rather than waste time and effort trying to get a clean rebase. This is not to say that the tools are lacking or at fault but that we are pragmatic rather than ideological.7
  3. If there are merge commits in a feature branch with a large number of well-organized commits and/or a large number of changes or affected files. In this case, using a squash merge and rebuilding the commit history would be onerous and error-prone, so we just merge to avoid issues that can arise when rebasing merge commits (related to the point above).

When should I use private branches? What are they exactly?

There are no rules for local branches: you can name them whatever you like. However, if you promote a local branch to a private branch, at Encodo we use the developer's initials as the prefix for the branch. My branches are marked as "mvb/feature1", for example.

What's the difference between the two? Private branches may get pushed to our common repository. Why would you need to do that? Well, I, for example, have a desktop at work and, if I want to work at home, I have to transfer my workspace somehow to the machine at home. One solution is to work on a virtual machine that's accessible to both places; another is to remote in to the desktop at work from home; the final one is to just push that work to the central repository and pull it from home. The offline solution has the advantage of speed and less reliance on connectivity.

What often happens to me is that I start work on a feature but can only spend an hour or two on it before I get pulled off onto something else. I push the private branch, work on it a bit more at home, push back, work on another, higher-priority feature branch, merge that in to master, work on master, whatever. A few weeks later and I've got a private branch with a few ugly commits, some useful changes and a handful of merge commits from the master branch. The commit history is a disgusting mess and I have a sneaking suspicion that I've only made changes to about a dozen files but have a dozen commits for those changes.

That's where the aforementioned "branch bankruptcy" comes in. You're not obligated to keep that branch; you can keep the changes, though. As shown in the referenced article, you execute the following git commands:

git checkout master
git checkout -b cleaned_up_branch
git merge --squash private_feature_branch
git reset

The --squash tells git to squash all of the changes from the private_feature_branch into the index (staging) and reset the index so that those changes are in the working tree. From here, you can make a single, clean, well-written commit or several commits that correspond logically to the various changes you made.

Git also lets you lose your attachment to checking in all the changes in a file at once: if a file has changes that correspond to different commits, you can add only selected differences in a file to the index (staging). In praise of Gits index by Aristotle Pagaltzis provides a great introduction. If you, like me, regularly take advantage of refactoring and cleanup tools while working on something else, you'll appreciate the ability to avoid checking in dozens of no-brainer cleanup/refactoring changes along with a one-liner bug-fix.8

One final example: cherry picking and squashing

I recently renamed several projects in our solution, which involved renaming the folders as well as the project files and all references to those files and folders. Git automatically recognizes these kind of renames as long as the old file is removed and the new file is added in the same commit.

I selected all of the files for the rename in SmartGit and committed them, using the index editor to stage only the hunks from the project files that corresponded to the rename. Nice and neat. I selected a few other files and committed those as a separate bug-fix. Two seconds later, the UI refreshed and showed me a large number of deleted files that I should have included in the first commit. Now, one way to go about fixing this is to revert the two commits and start all over, picking the changes apart (including playing with the index editor to stage individual hunks).

Instead of doing that, I did the following:

  1. I committed the deleted files with the commit message "doh!" (to avoid losing these changes in the reset in step 3)
  2. I created a "temp" branch to mark that commit (to keep the commit visible once I reset in step 3)
  3. I hard-reset my master branch to the origin
  4. I cherry-picked the partial-rename commit to the workspace
  5. I cherry-picked the "doh!" commit to the workspace
  6. Now the workspace had the rename commit I'd wanted in the first place
  7. I committed that with the original commit message
  8. I cherry-picked and committed the separate bug-fix commit
  9. I deleted the "temp" branch (releasing the incorrect commits on it to be garbage-collected at some point)

Now my master branch was ready to push to the server, all neat and tidy. And nobody was the wiser.



  1. There are alternatives now, though, like Microsoft's TypeScript, that warrant a look if only because they help tighten the error-finding feedback loop and have the potential to make you more efficient (the efficiency may be robbed immediately back, however, if debugging generated code becomes difficult or even nightmarish).

  2. Once you've pushed, though? No touchie. At that point, you've handed in your test and you get graded on that.

  3. According to my business card, I'm a "senior developer and partner" at Encodo System AG.

  4. With the exception, mentioned elsewhere as well, that rebasing merge-commits can sometimes require you to re-resolve previously resolved conflicts, which can be error-prone if the conflicts were difficult to resolve in the first place. Merging merge-commits avoids this problem.

  5. bisect is a git feature that executes a command against various commits to try to localize the commit that caused a build or test failure. Basically, you tell it the last commit that worked and git uses a binary search to find the offending commit. Of course, if you have commits that don't compile, this won't work very well. We haven't used this feature very much because we know the code in our repositories well and using blame and log is much faster. Bisect is much more useful for maintainers that don't know the code very well, but still need to figure out at which commit it stopped working.

  6. To be clear: we're only so cavalier with our private repositories to which access is restricted to those who already know what's going on. If we commit changes to public, open-source or customer repositories, we make sure that every commit compiles. See Aristotle's index article (cited above) for tips on building and testing against staged files to ensure that a project compiles, runs and passes all tests before making a commit -- even if you're not committing all extant changes.

  7. That said, with experience we've learned that an interactive rebase and judicious squashing will create commits that avoid these problems. With practice, these situations crop up more and more rarely.

  8. Of course, you can also create a separate branch for your refactoring and merge it all back together, but that's more work and is in my experience rarely necessary.

Updating to a touch-friendly UI

This article originally appeared on earthli News and has been cross-posted here.


I was recently redesigning a web page and wanted to make it easier to use from touch-screen browsers. Links made only of text are relatively easy to click with a mouse, but tend to make poor touch targets. If the layout has enough space around the link, this can be remedied by applying CSS.

The basic box

FirstSecondThird

Suppose we have a box with three links in it, as shown to the right.

Setting the height

The first step is to make this box taller, so the logical thing to do is to set the height. We'll have to pick a value, so set height: 40px on the gray box.

FirstSecondThird

Aligning vertically

This isn't exactly what we want, though; we'd rather have the vertical space equally distributed. Also, if you hover over the links, you can see that the space below the text is not active. Maybe we can try to add vertical-align: middle to align the content.

FirstSecondThird

Unfortunately, this doesn't have the desired effect. The vertical-align property works when used this way in table cells, but otherwise has no effect for block elements. Knowing that, we can set display: table-cell for the gray box.

FirstSecondThird

And now the box has become longer, because the 50% width of the box is calculated differently for table cells than for regular boxes (especially when a table cell is found outside of a table).

Relative positioning

Let's abandon the vertical-alignment approach and try using positioning instead. Set position: relative and top: 25% to center the links vertically.

FirstSecondThird

Now that looks much better, but the space above and below the links is still not active. Perhaps we can use the height trick again, to make the individual links taller as well. So we set height: 100% on each of the links.

FirstSecondThird

We didn't get the expected result, but we should have expected that: the links are inline elements and can only have a height set if we set display: inline-block on each link as well. We use inline-block rather than block so that the links stay on the same line.

FirstSecondThird

The links are now the right size, but they stick out below the gray box, which isn't what we wanted at all. We're kind of out of ideas with this approach, but there is another way we can get the desired effect.

Positive padding and negative margins

Let's start with the original gray box and, instead of choosing a random height as we did above -- 40px -- let's set padding: 8px on the gray box to make room above and below the links.

FirstSecondThird

With just one CSS style, we've already got the links nicely aligned and, as an added benefit, this technique scales even if the font size is changed. The 8-pixel padding is preserved regardless of how large the font gets.1

FirstSecondThird

This approach seems promising, but the links are still not tall enough. The naive approach of setting height: 100% on the links probably won't work as expected, but let's try it anyway.

FirstSecondThird

It looks like the links were already 100% of the height of the container; in hindsight it's obvious, since the height of the gray box is determined by the height of the links. The 100% height refers to the client area of the gray box, which doesn't include the padding.

We'd actually like the links to have padding above and below just as the gray box has. As we saw above, the links will only honor the padding if they also have display: inline-block, so let's set that in addition to padding: 8px.

FirstSecondThird

We're almost there. The only thing remaining is to make the vertical padding of the links overlap with the vertical padding of the gray box. We can do this by using a negative vertical margin, setting margin: -8px.

FirstSecondThird

We finally have the result we wanted. The links are now large enough for the average finger to strike without trying too hard. Welcome to the CSS-enabled touch-friendly world of web design.

The code for the final example is shown below, with the sizing/positioning styles highlighted:

.gray-box
{
  background-color: gray;
  border: 1px solid black;
  border-width: 1px 0;
  width: 50%;
  text-align: center;
  padding: 8px 0;
}

.gray-box a
{
  background-color: #8F8F8F;
  display: inline-block;
  padding: 8px 20px;
  margin: -8px 0;
}

<div class="gray-box">
  <a href="#" style="color: goldenrod">First</a>
  <a href="#" style="color: gold">Second</a>
  <a href="#" style="color: yellowgreen">Third</a>
</div>


  1. Naturally, we could also use .8em instead and then the padding will scale with the font size. This would work just as well with the height. Let's pretend that we're working with a specification that requires an 8-pixel padding instead of a flexible one.

Visual Studio & Resharper Hotkey Reference (PDF)

It's always a good idea to familiarize yourself with the hotkeys (shortcuts, accelerators, etc.) for any piece of software that you use a lot. Using a keyboard shortcut is often much faster than reaching for the mouse. Applications with a lot of functionality -- like Word, IDEs and graphics tools -- have a lot of hotkeys, and they will help you become much more efficient.

imageAt Encodo, we do a lot of our programming in Visual Studio and Resharper. There are a lot of very useful hotkeys for this IDE combination and we listed the ones we use in a new document that you can download called the Encodo Visual Studio & Resharper Hotkey Reference.

We managed to make all of the shortcuts fit on a single A4 page, so you can print it out and keep it on your desk until you've got them memorized. Almost all of the hotkeys are the standard ones for Visual Studio and for ReSharper (when using the Visual Studio key mapping), so you won't even have to change anything.

To get the few non-standard hotkeys in the Encodo standard settings, you can import this VS2012 settings file. In addition to the most important combinations listed in the hotkey reference, the file includes the following changes to the standard layout.

  • Ctrl+W: Close window
  • Alt+Shift+W: Close all but this window
  • Ctrl+Shift+W: Close all windows
  • Ctrl+Shift+E: Select current word

And, even if you have your own preferred hotkeys, you can still take a look at the chart to discover a feature of Visual Studio or ReSharper that you may have missed.


At the time of writing, we're using Visual Studio 2012 SP1 and Resharper 7.1.

The Next Opera Next Browser

This article originally appeared on earthli News and has been cross-posted here.


imageOpera started a public beta-testing program a few years ago called Opera Next. Whereas the stable version naturally moved along more slowly -- but always rock-solid -- Opera Next often had a more up-to-date HTML/CSS renderer (code-named Presto) and Javascript engine (code-named Carakan). Opera recently anounced that future versions -- Opera Next Next -- would be built on the WebKit HTML/CSS renderer and Google's open-source V8 Javascript engine instead.

Why is it good news?

This is, I think, good news for both Opera users and Opera as a company. Opera and WebKit: a personal perspective by Bruce Lawson is of the same mind, writing pragmatically that, "Operas Presto engine was a means to an end".

The browser landscape has changed significantly since IE dominated the world with over 90% market share in 2004. IE now has less than 50% worldwide browser share (desktop share is 54%), but Chrome and Firefox each have about 20% as well. Users for some sites, like Wikipedia, are divided up much more evenly between Chrome, Firefox and IE with Safari and Opera making up about 10%. The point is, that the browser market is considerably different than it once was -- and all participants are actively working against documented W3C standards and specifications. Sure, there are still browser-specific CSS prefixes and some highly specific implementations (e.g. the file API from Google) but they mostly stick to a process and all browser vendors have input into an open process. And Gecko and WebKit code is open source.

As Lawson puts it so well,

These days, web standards arent a differentiator between browsers. Excellent standards support is a given in modern browsers. Attempting to compete on standards support is like opening a restaurant and putting a sign in the window saying All our chefs wash their hands before handling food.

Why WebKit?

All of which is why Lawson (he's the guy who wrote the press release for Opera's move to WebKit) writes,

[i]t seems to me that WebKit simply isnt the same as the competitors against which we fought, and its level of standards support and pace of development match those that Opera aspires to.

The Trident code-base -- the renderer for Microsoft's browsers -- was and still is closed-source. While it has been much more actively developed in the last couple of years, back in the bad old days of IE6, the code base was stagnant, lacked innovation and had little to no standards support.

WebKit is certainly not any of these things. If you follow the WebKit changelogs, it's clear that the majority of changes are to implement an HTML5 feature or to improve performance or to use less memory for common tasks. This is a vibrant, highly active and open-source project with developers from at least two large development teams -- Apple and Google -- actively contributing to it.1

Opera adding their cadre of excellent engineers to the mix can only be a good thing -- for everyone involved. They've already written that they plan to port their superior HTML5 forms support to WebKit, a very useful feature on which other participants were dragging their feet.

Running just to stay in place

A while back, Opera made a valiant attempt to get the whole browser running in a hardware-accelerated mode and almost made it, but had to pull back just before release because of stability issues on some machines. The mode is still there if you want to enable it. Flow layout is great and WebGL also made it in, but the implementation lagged. As did many other features.

While Opera was first to implement a few features -- like HTML Forms or their excellent SVG support -- they were having trouble keeping up and implementing every working draft and standard. I wonder whether the Opera dev team took a look at the Comparison on Opera vs. Chrome and despaired of ever catching up. For the first 3/4 of the page, Opera and Chrome are dead-even. And then things go downhill for Opera from there: 3D Transforms, filter effects, masks, touch events, border images, device-orientation events. These are all things that are standardized (working drafts anyway) and that I have used -- or wanted to use -- in current web projects.

They probably had to make hard choices about where to invest their time, energy and money. Some have tried to argue that the departure of the Presto engine will adversely affect standards acceptance. The article Hey Presto, Opera switches to WebKit by Peter Bright writes the following:

Opera could have gone the route that Microsoft has chosen, trying to educate Web developers and providing tools to make cross-platform testing and development easier, but perhaps the company [...] felt that asking Web developers to stick to standards was [...] futile. Historically, the company has tried to do just this, but its success at influencing real Web developers has been limited; for all the emphasis placed on standards, many developers don't, in practice, care about them.

The developers over which Opera had influence were most likely already coding to standards. The move to WebKit isn't going to change any of that. Opera's 2% of the market was not enough to even get any developers to test with it, and many products clearly got managerial approval to just stick an if (Opera) { fail(); } statement in their web sites to prevent their site from appearing buggy in an untested browser. It's hard to see how Opera's move will change standards development or acceptance.

Why Opera?

I don't think that most users chose Opera because of its renderer. In all honesty, there were very few cases where Opera rendered a site better than other browsers -- and enough examples where Opera did not render as well, whether due to missing functionality or deliberate crippling by the site.

Innovation

Opera has led the way with many non-renderer innovations.

  • Tabbed browsing
  • Speed dial
  • Browsing sessions (tabs+history)
  • Popup blocking
  • Restart from last browsing session (with history)
  • Mouse gestures
  • Searchable window list (essential when dozens or hundreds of tabs are open)

These features were all pioneered by Opera and many have since been adopted by other major browsers (either natively or through extensions). It's certainly a good thing to think that the development team that brought you these innovations and features will be spending less time on HTML5 minutiae and more time on browser features like these.2



  1. The Chrome team has a stated goal of pushing changes in Chromium back upstream to the WebKit main line. Apple has historically done a lot of this as well. I'm not sure what the situation is now, so take my statement with a grain of salt.

  2. This is not to say that I haven't considered the possibility that Opera will, instead of moving the high-level dev staff to working on WebKit patches, simply drop them from the staff in order to save money. Their press release didn't indicate that they were slimming down, but then it wouldn't, would it? Time will tell.

Archive of Quino release notes are now online

For a long time, we maintained our release notes in a wiki that's only accessible for Encodo employees. For the last several versions -- since v1.7.6 -- we've published them on the web site, available for all to see.1 Because they reveal the progress and history of Quino quite nicely, we've made all archival release notes available on the web site as well.

Browse to the Quino folder in the blogs to see them all. Some highlights are listed below:

  • v0.1 -- November 2007: Even the very first version already included the core of Quino: metadata, basic schema migration and an automatically generated Winforms-based UI
  • v0.5 -- July 2008: Introduced reporting integration, based on the DevExpress reporting system and including a report-designer UI
  • v1.0 -- April 2009: The 1.0 release coincided with the initial release of the first suite of applications built with Quino2 and included a lot of performance tweaks (e.g. caching)
  • v1.0.5 -- September 2009: Included the first version of the MS-SQL driver, with support for automated schema migration (putting it more or less in the same class as the PostgreSql driver).
  • v1.5.0 -- October 2010: Quino officially moved to .NET 4.0 and VS2010
  • v1.6.0 -- March 2011: Included an initial verison of a Mongo/NoSQL data driver (without schema-migration support)
  • v1.7.0 -- February 2012: Included a radical rewrite of the startup and shutdown mechanism, including configuration, service locator registration as well as the feedback sub-system
  • v1.7.6 -- August 2012: Quino moved to NuGet for all third-party package integration, with NAnt integration for all common tasks
  • v1.8.0 -- August 2012 and 1.8.1 -- September 2012: The data-driver architecture was overhauled to improve support for multiple databases, remoting, cloud integration, custom caching and mini-drivers
  • v1.8.3 -- October 2012: Introduced a user interface to help analyze data traffic (which integrated with the statistics maintained by the data driver) for Winform applications
  • v1.8.5 -- November 2012: The latest available release -- as of the end of 2012 -- includes an overhaul of the metadata-generation pattern with an upgrade path for applications as well as support for running against a local database using the Mongo data driver.
  • v1.8.63: Coming up in the next release, is support for plugins and model overlays to allow an application to load customizations without recompiling.


  1. Please note that the detailed release notes include links to our issue-tracking system, for which a login is currently required.

  2. The initial version of Quino was developed while working on a suite of applications for running a medium-sized school. The software includes teacher/student administration, curriculum management, scheduling and planning as well as integration with mail/calendar and schedule-display systems. By the time we finished, it also included a web interface for various reporting services and an absence-tracking and management system is going to be released soon.

  3. The release notes were not available at publication time.