Blame, don’t shame!

Occasionally a tester reports a bug which is not introduced in the last commit. After investigating the bug the cause is found, but what to do? Most version control systems support a tool called blame. This however requires you to first find the code behind the bug. So after you find the cause, knowing who did this is only going towards a shaming situation.

git bisect

In most cases finding the cause of a bug is most time consuming, so how can we optimize this? How can we stop blaming, just for shaming? git bisect is a helpful tool which can help us achieve these goals.

Bug report!

Let’s imagine a scenario where the following bug is reported:

Given a user is on the checkout page,
when hovering over the help icon
then the help text is not visible,
but we expected the help text to be visible!

Test to identify

In this scenario the tests are run with grunt, karma and ngScenario. In grunt we configured a task to run all our tests: 

grunt test

To automatically see if the bug is present, it is best to write a test to confirm the case. For this example’s sake, this test case will be called confirm case.

Preparations

In this scenario, there are biweekly sprints, where each sprint will have a new release. The last release didn’t have this bug, which will serve as a reference for git bisect. For this example, the sha for the release tag is #tag.

To start the analyses, run:

git bisect start

Then let git know the current commit is broken:

git bisect bad

Tell git the first correct commit:

git bisect good #tag

Analyse

With git bisect git will checkout commits between the first good commit and the current bad commit. On every checkout git is able to run some commands to tell if the checked out commit is good or bad to narrow down the search to the first bad commit. Aka the commit that introduced the bug! With the help of the automated tests git can automatically find the first bad commit for us:

git bisect run grunt 

Blame

Now that the first bad commit has been identified, it is easy to find the cause if the commit messages make sense! In this example:

Author: Bob
Renamed the ‘buynow’ directive to ‘checkout’. 

To initialize the new directive include this tag in your view:
“`html
<div data-checkout=”checkoutid” />
“`

Resolve

Now that the commit is found, we have the following information:

  • The change set that introduced the bug
    Obviously this change set is a lot smaller compared to all changes made from the tag till the bad bug
  • The commit message with useful information about what the change was made for
    When a commit message is scoped to just this change, it is easy to understand why something is changed
  • The author of the commit
    If there are still misunderstandings, the author is known and hopefully can explain some decisions to resolve the bug

In this example the css for showing the help text is bound on the attribute:

[data-buynow]:hover { … }

This caused the hover to not work anymore and the fix is just renamed the selector as well!

Conclusion

With git bisect bugs can be debugged more easily and straight forward. When someone is blamed, this person is not shamed. This person is then instead asked for his knowledge on this commit, rather then just pointing a finger!

Solve the problem as a team 🙂

Another git merge strategy

Intro

There are so many ways on how to utilize git and each has their own advantages and disadvantages. After playing with several strategies I found one that suits my needs and want to share this strategy, to maybe improve or get even more idea’s to an even better suiting strategy.

Rebasing vs Merging

The main goal of both rebasing and merging is to combine different change sets into one. Even though they serve the same purpose, they are still very different. 

Merging

With merging you will create a new commit with the result of the merge between the branches. This merge commit is kept by git as a reference point for the next time git wants to resolve a merge conflict.

Merge Example

git merge

In this example a feature branch is being merged two times back into a master branch. When resolving the first merge conflicts these resolutions will be saved in the first (green) merge commit. When merging the feature branch for the second time, git will recalculate from the first (green) merge commit. The second (green) merge commit will only have to merge the last two (orange) feature branch commits with the (blue) master commits.

Rebasing

When resolving merge conflicts with a rebase, there won’t be a merge commit. Instead the merge conflicts will be resolved on the commits themselves.

Example

before_rebase

Same as with merging we have commits in a feature branch.

first_rebase
When rebasing the changes of the feature branch will be applied on top of master.

before_second_rebase

The next rebase will be applied on top of those changes again.

rebase_result

The end result will be a linear log of changes.

Rebasing for a cleaner log and more

Rebasing will result in a cleaner log, but there are more benefits for rebasing over merging. For instance your merge conflicts will be resolved on commit basis, where as the merge will be one huge change set of all changes combined into one big merge party. Other tools like bisect will also work a lot better, since the commits are actually preserved in a linear history.

For more more awesome info about commit messages, here is an nice post explaining how commit messages can be very usefull: deliberate-git

Feature branches

Imagine working on a new feature. During your development, you notice there is a bug in the code you would want to fix before finishing your new feature. We can simply create a new branch, branched from the stable master and apply this bug fix. Now we switch back into our local branch containing the changes we made up until we found the bug and continue. How awesome is that?

Applying the bug fix, could cause you to not being able to finish your feature on this day, but you still want to share your code with the rest of your team. You can’t push this to the master, as you want only stable code in the master branch… No worries, we can push the commit to a Feature branch!

Pausing/Dropping

An additional advantage would be when problems occur while developing this feature, either from business side or from technical side, the feature can be paused or even dropped at any time. Preventing risks of having a release of other features postponed.

Testing

We only want stable code in our master branch and Feature branches can help us achieve that. The feature can be tested isolated from any other parallel developed feature.

Local pulling

Ideally we would want even stable code in the feature branch, which would allow test suites to be run at every commit in the feature branch for even more feedback. However in the previous example, a commit was pushed which would break tests.

Pulling from a local machine is one of the solutions which I prefer. In order to pull from a local machine, the developer hosting the files, must start the daemon first. This forces awareness. When you are pulling from a local machine, you are more aware of the fact that you might actually pull something in which is not stable.

before_local_pulling

This allows for even tighter collaboration between the developers. Being able to commit not working changes, allows smaller commits which would not work separately but would work when combined with the commits of the other developers. 

rebase_local_pull

After pulling and finishing the changes on a local machine, we can squash the commits into one working commit and share this in the feature branch to allow QA to test these changes. (Note: Squashing commits means rewriting those multiple commits and commit them as if they were one commit)

squashed_commit

After QA has tested and approved the feature, we can squash the bug fixes into grouped commits. Don’t simply merge all commits into one commit, but merge them into sensible commits.

Knowledge Sharing

By working on a feature with such small tasks, each team member learns more about the feature being implemented. Instead of having three features implemented separately by three developers, the three developers could develop a bit of each feature instead, spreading the knowledge of the feature as well as having the feature earlier testable.

Conclusion

Cleaner log + applying commits one by one = resolving conflicts more easily

With the help of rebasing, we create a log history that is easy to read. Rebasing applies the changes commit for commit on top of the changes made in an other branch.

Parallel development + Feature branches = Flexible release scope

With the help of feature branches we can group commits together and squash  them into sensible commits to keep the log even more clean. Features won’t be blocking each other from being released anymore and if needed they can be dropped entirely.

Sequential Feature development + local pulling = More knowledge + Earlier testable feature

With the help of pulling from local repositories we can work even more closely on features. Sharing more knowledge among the team and preventing QA from having to test all features at the end of the sprint!