My Git Workflow

Pipes and nodes to replicate a git workflow of multiple branches merging into each other

I haven’t written about my Git workflow for over a decade. The last time I documented my Git workflow was during a contract. I needed to explain Git to a new employee who was new to development.

My perspective

I’m writing this post based on my experience as a solo developer. Unless I am in a contract, I spend much of my time working solo. There is no reason these workflows won’t work with small or larger teams; your results will vary. With larger teams you don’t get a choice though as the organization decides what is best.

Project Type

The type and state of the project maters. When the project is in the initial stages of development and there hasn’t been a release, everything happens in “main”. A release could be the first alpha release for testers, the initial preview for a client or just the point that feels right. If the project is past its first release, the only question that matters is, public or private repo?

If the project lives in a public repository, all my development happens on a fork. The fork is effectively my feature/dev branch. I will merge back into “main” as often as possible. I will merge when a specific feature is complete, when a bug is fixed or just when it feels right. My work on Budget is an example of this, I have a fork and never commit directly into the “main” repo.

When the project lives in a private repository, all my development happens on feature branches. Where possible these are small feature branches. We all know that sometimes you are going to have the long-lived feature branches, in those instances I will merge main into the long-lived feature branch anytime “main” changes. Budget Pro lives in a private repository so there is no fork, just the main repository.

Feature branches

Whenever possible, yes, small feature branches are the way to go. The only real change in my approach is where the feature branch lives, is it a fork or a branch off “main”.

There are exceptions, there will always be edge cases. Edge cases are different for all of us, you know yours. If your edge cases are rare, it is ok to break the rules occasionally.

If you got to the end of this post and are wondering, well, that seem simple, yes, that is the point. Our work is hard enough, we don’t need to complicate it by adding unnecessary steps to our development processes.

I have avoided talking about continuous integration and continuous delivery in this post, they are topics for a different day. Our first priorities should be making development easy and ensuring “main” is stable.

This post is a continuation of a series in which I talk about me development process. Please check out some of my other posts, my typical project setup and action class usage in my Laravel apps.

Code Rewrite

Three wooden blocks with the words "time" "to" and "update" on them. The blocks are sitting on a white surface against a light background

I’ve discussed in a previous blog post that Budget Pro and Budget are two different Apps. I won’t repeat the rationale here, however regardless of my choice I will still need to rewrite the code for the “budget service“.

What is the budget service?

The budget service receives a collection of “budget items” from the Costs to Expect API. It is responsible for taking these budget item definitions and then creating the users Budget.

Budget items have several parameters controlling whether and how they should appear on the users Budget.

Parameter:Description:
FrequencyHow often does the budget item repeat and how does it repeat?
Start DateWhen is the budget item effective from?
End DateWhen is the budget item effective until?
AdjustmentHas the budget item been adjusted, for example value changed
PaidHas the budget item been marked as paid for the selected period?
DisabledHas the budget item been marked as disabled?
AccountWhich account does the budget item belong to?
TypeWhat is the type of the budget item, income, savings, expense etc.
Parameters that exist on budget items in Budget.

The service iterates through all the defined budget items and allocates them to each period (month) accordingly. From this, the service then calculates the projected balance for each defined account.

Why the code rewrite?

The existing budget service is serviceable. It has warts because features were added after the original design but other than me being unhappy with it, it works well enough and has tests. Me being unhappy with it is not reason enough to rewrite, we would never release anything if we kept refactoring code each time we were unhappy with it.

So, why a full code rewrite?

Well, Budget Pro is significantly more complicated that Budget. In Budget Pro we support multiple period types, many more adjustments, custom display options as well as other changes. Additionally, users can have multiple budgets meaning the service needs to know which budget it is handling as well as the permissions due to sharing features.

The original service wasn’t designed to handle custom display options let alone more advanced parameters. The budget service already feels “wrong” so although I could tack on support for all these features, I would end up with something even more clunky than now and inevitably need to rewrite it anyway.

Struggling?

What is the problem, why the need for a blog post? Well, I’m struggling, and I think I’ve worked out why.

When I created the original budget service I was working from a clean sheet. I had the data the service would use; I had a design to achieve, and I could decide how I got from A to B.

With the new service, I have a lot more baggage; I have the data, I have an updated design for the UI, I know the new features but I also have an example of a service that doesn’t work.

We all code in a specific way and this is the problem. I know what I did before isn’t right; however it does solve the problem. I could go back to basics and design from a clean sheet but that is foolish because of the existing service. As much as the existing service won’t work for Budget Pro, it has been improved over time and works and obviously, some of what it does is correct.

What am I doing?

I’m designing the new service slowly, bit by bit. I’m keeping an eye on the original service but conscious that there are many things that need to change.

The first major change is support for user options. There are multiple sections of the service that need access to user options. For example, the spend ranges for budget items, the number of ‘periods’ to display and colours. I’ve opted to use a Service Provider to register the Budget service and corresponding helper services. This makes it trivial to access the service throughout the App via the Service Container. The next issue is more parameters, specifically the more complex frequencies and more adjustments. In the original service I handled this as I iterated through the data. With a small number of parameters, this is easy but as the number of parameters grow this gets more difficult. I’m going to create data structure that manage each parameter which will hopefully help me keep the core iterating code nice and simple.

Below is a comparison image for the old and new service. As you can see the complexity has increased. However, the new service is much clearer regarding implementation.

Budget Pro and Budget "Budget" services compared. Tree structure of the two services compared, the Budget Pro services contains twice as many files/classes
The “Budget” service in Budget & Budget Pro

Will it work?

Only time can answer that but yes, I suspect everything will be fine. Yes, there will be bug fixes and there will be addons that make my eye hurt but that is working code.

A year after Budget Pro releases I will be in a better position to answer this question. I will have had to tweak things, fix many bugs, some hopefully due to scale and be working on new features. It will be at this point I will be able to say for sure if all the effort was worthwhile.