Imagine quite a common situation. You are a part of the development team. There is some kind of user story or a technical task that needs to be implemented. You create a branch for it. Your hard work has just started. After one week of development, you are finished with it. You have been synchronizing your branch with the main one (does not matter if this is development, stage, master, or any other – a shared one) multiple times during your work or you did it just in the end.
Problem number 1: You need to remember to merge changes from the main branch or to rebase quite regularly. If you forget about it for a day or two it may cost you grimace (or two!) on your face.
Problem number 2: If you do it in the end, there is usually a lot of conflicts with other changes that were performed during this period of time. It quite often leads to anger, sweating, and quite a several bad words.
Ok, you finally synchronized your branch and it is ready for a pull request. Now, the reviewer sees something similar to this view:
This branch contains a vertical slice that allows users to download a small file. There are 45 commits that touch 82 files. 4571 lines of code were added, 45 removed.
Problem number 3: The reviewer has now to focus on the entire slice in his code review. He needs to either go commit by commit or through each of 82 files. PR can include changes related to business logic, architecture, code formatting, renaming, and many, many more.
As you can see there are a lot of different areas to focus on. If the reviewer focuses on each file only for a minute, it will take him 82 minutes to finish it. With such an approach, many important issues will be overlooked. What about things like architecture analysis, looking at design patterns, and testing the outcome to see if it works as desired? There is a high chance that in the end, the reviewer will be exhausted and demotivated to handle such an amount of work. Another (really bad) option is that he goes with LGTM (Looks Good To Me) and PR is approved.
The review goes on and after 4 hours you get the response. It looks as below:
There are 53 comments from the reviewer and your pull request is rejected.
Problem number 4: You see 53 comments. That is a lot. You need to go through all the inputs. For sure there will be things like cleanup of namespaces or rename of methods. There will be as well comments that are discussable (here you still need to discuss each of these). But there are also hardcore ones – switch it to this design pattern, refactor quite a lot of code. After several rounds of review & rework, you are ready to merge it! Ooops, look – you need to rebase, again some conflicts. Finally, it is merged after 2 days full of R&R rounds. There is a high chance that in the end, you will be exhausted and demotivated to handle such an amount of work and comments. It might be even worse – am I the right person for this job?
Imagine another situation. Instead of taking a user story or a task into one branch, you analyze it first with your colleagues who will implement it with you. After some time, you decide to split it into small subtasks:
1. Prepare download icon design (approx. 1-2 hours)
2. Integrate download icon into file row without any action connected (approx. 2-3 hours)
3. Handle business rule number 1 required to generate download link (approx. 3-4 hours)
4. Handle business rule number 2 required to generate download link (approx. 3-4 hours)
5. Prepare technical implementation to generate download link (approx. 6-8 hours)
6. Connect technical implementation with business rules (approx. 3-4 hours)
7. Implement endpoints (approx. 3-4 hours)
8. Trigger download action on clicking the download icon (approx. 1-2 hours)
Now, you are ready for short living branches, the ones that live for a short amount of time after the creation. What does a short amount of time mean? You should agree on it with your team and in the beginning try to keep it (after some time you will not try, you just do it :)). Within this period of time, you should make sure that the branch is merged and closed. This way, the speed of change is entering previously unimaginable levels. More and more people start to increase their motivation (“yeah, my code is merged!” or “great, a small number of changes, I will try to rock it!”). The feedback loop is shortened to a minimum.
I tried to sum up my recommendations for a time when you decide to enter this world:
Recommendation number 1: Analyse and split. Divide your work on a user story or a technical task into smaller pieces. From this moment, each subtask can be treated as a separate, short living branch and you can easily parallelize the work with your colleagues – each of them will take one subtask and create its own branch.
Recommendation number 2: New work discovered = new branch created. Whenever you find a new thing to be done after the initial split, treat it as a new, short living branch (add subtask and start your work).
Recommendation number 3: The shorter = the better. Do not go with more than 1-2 days for each branch. Even if you will have to merge changes to or rebase your branch at the end of work, then it will not be as much as it would have been after 1-2 weeks. I try to keep it alive for 4-6 hours. If you follow this recommendation, usually it is easier to get “team willingness” to perform reviews way faster than before.
Recommendation number 4: The less = the better. Try to keep your pull requests as small as possible. This way, the reviewer who looks at your code where there are 4 files changed and 8 commits, will be motivated to deeply look at changes. On the other hand, you will see e.g. 5-10 comments that can be quickly solved. This will not demotivate you in comparison to 53! Observation from my side – the fewer files are in PR, the faster feedback I get – sometimes it is ready after 10 minutes from the request to review and I am able to merge.
Recommendation number 5: Try to start from the bottom. Whenever you divide your stories or technical tasks, try to start from the work that is not visible to a user. When you implement a new feature, make sure that the trigger between the user and a code is implemented as the last step (e.g. the icon that the user can click in a view or endpoints that can be called by any type of client).
Recommendation number 6 (advanced): One area of change = one branch. This is usually achievable after some time. An example – during your work on short living branch which is responsible to add an icon to a file row, you discovered that it would make sense to move 20 files to another namespace and another 15 files to a different one (not directly related to the change you make). Of course, it can be handled within separate commits in the current branch but I suggest creating another short living branch that will include only these commits that touches the structure of namespaces. Another example – the first branch creates a UI component, the second branch integrates it.
In my experience, changing your thinking to short leaving branches, brings much good and benefit – both for a product (increased quality because of deep focus during code reviews) and for team members (increased motivation).
However, be careful – if done incorrectly, it can decrease product stability (when changes are not well thought out, especially in continuous deployment environments) and decrease the motivation of several guys (when the team is used to working separately for 1-2 weeks, this will be quite a long process to convince all of them).
And you? What do you think about it?