Daniel Siepmann - Coding is Art

Blog Post

My Git Workflow

Published: , Updated:

Topics: git

Introduction

I've read different tips & tricks from developers. I've also read different workflows like "git flow". And I've worked with some freelancers and agencies on a dozen of projects.

This post will share my current git workflow that works for all of our clients in all the projects. This includes switching projects and knowing where to continue once you come back. And this also ensures the rest of the team can continue with your work in case you become ill.

Branching

I create a new branch for each new to-do I have to solve. It doesn't matter whether it is a bugfix, hotfix, task, new feature or something else. I do not distinguish, because it doesn't matter for the actual to-do.

The branch name is often created out of an issue system. I use the issue number (which usually exists) as a prefix, followed by some meaningful description in lowercase separated with -. But the format is not that important. Adding the issue number as prefix makes it easy to autocomplete the branch based on your current task and eases switching. Most systems will interact with each other, allowing to auto link the branch to the issue.

Commits

I might create multiple commits for a single to do. The first one might be an empty commit used to describe the goal and setting the focus.

Further commits might be added leading to a history like (only showing first line of each commit):

  1. Make copyright year dynamic
  2. Migrate hardcoded year to TypoScript dynamic year
  3. Migrate TypoScript year to ViewHelper usage

It doesn't matter too much how many commits I'll have in the end, see Merging.

Different fine-grained commits allow me to rebase, revert, check history of my own ideas to solve a to-do. They also allow teammates to review all in one or step by step. They add extra info for everyone without extra work.

I share every commit with the outer world. That ensures there is a back-up of my work done so far, in case my machine will break. Also, everyone else can have a look how far I've come and can continue the work.

WIP

I sometimes need to switch between to-dos. I then add a WIP commit where I document the current state of the to-do I'm leaving. This commit includes a WIP prefix, so everyone can see within the git history that this commit is not finished. The commit also includes a list of the open tasks to solve the to-do. E.g.:

WIP: Make copyright year dynamic

In order to not adjust the year every year.

WIP:

    * Find location of hard coded year
    * Change location to be dynamic
    * Add tests to ensure the year will be changed

I then share this commit with everyone else. This ensures that I can read what I've to do next time I'm working on this task. But everyone else within the team also can follow up. E.g., in case I am on holiday or am ill.

Merging

I prefer to squash all commits related to a single to do. Most web UIs support this out of the box. This single squashed commit will then be added to the target branch, leaving a clean history.

Some can be configured to use the first commit message as the final commit message. I'll then add a first empty commit to the branch which is used for the final commit within the project. Empty commits can be created via git commit --allow-empty. This also allows you to document your focus and goal within git as a first step before even starting to solve a to-do.

Cocnrete example

Let's say I've received a new issue with number 314 that is about adjusting the current year within the copyright of the footer. Here's what I do:

  1. Fetch the current state of the project via git fetch.
  2. Switch over to the latest state to start working via git checkout origin/main. Where origin/main is your actual branch where you start new work. Some might use origin/dev or origin/develop instead.
  3. Create a new branch for your changes via git switch -c 314-fix-copyright-in-footer.
  4. Do your changes. E.g., make the actual year dynamic, so you do not need to solve the same issue every year. This includes adding automated tests and manual testing.
  5. Commit your changes to the repository via git commit -av. Adding a commit message like:

    Make copyright year in footer dynamic

    This removes the need to adjust the year in future.

    Relates: #314

  6. Share your changes with your team via git push.
  7. Open a pull or merge request and wait for feedback.
  8. Merge your changes once the pull or merge request got approved.

This is the ideal workflow. But sometimes your changes take longer, and you might switch to another to do. I then still follow up to step 4, followed by this workflow, until we can continue with step 5 as we finished our to-do:

  1. Commit current changed as a WIP (=Work In Progress) commit via git commit -av. Adding a commit message like:

    WIP:Make copyright year in footer dynamic

    This removes the need to adjust the year in future.

    WIP:

    * Find the location of hardcoded year.
    * Adjust the source to make this year dynamic.
    * Add tests to ensure the year always matches current year.

    Relates: #314

  2. Share your changes with your team via git push.

I'll do the following when I come back to a WIP to do:

  1. Check if others have continued with my work via git fetch.
  2. I switch back to the task via git switch 314-fix-copyright-in-footer.
  3. Update my local state to the latest state via git reset --hard origin/314-fix-copyright-in-footer.
  4. Continue with my work and apply changes.
  5. Add my changed via git commit -av --amend. I'll adjust the WIP list accordingly with each commit, until I am finished and can remove the whole WIP info.
  6. Share my changes with the world via git push -f.

Acknowledgements

Thanks to berkes for making me feel to share my current workflow with his post on mastodon: https://fosstodon.org/web/@berkes@bitcoinhackers.org/108876619095503590.

Further reading

Other possible workflows, tips and tricks related to that: