Software Engineering · Git

Git (cont.)

In this post I’m going to be talking about how I use git. That is, what conventions I use, and what style I apply.

First, Git is a Distributed Version Control System.

A project is stored in a repository, which is a tree. The way I do things is to have a main branch that holds commits that developers have created. Typically this branch is called main, master, or develop, (I prefer main).

A developer pulls or clones this branch as it’s the one that their changes need to synchronise with.

git clone https://github.com/shanehowearth/example

Now, the important bits, on my projects a developer doesn’t make changes directly to main. I have been on projects that do this, but I found that it doesn’t allow developers to experiment and get feedback from their fellow developers in a helpful meaningful way (I mean, it could also have been that the ‘team’ that I was working for were incapable of helpful meaningful feedback, but that’s another story :-).

Instead a developer branches off from main, onto a topic branch. (Note: the -b is a shortcut that tells git to create and checkout the branch at the same time).

git checkout -b create_login

The developer now makes changes to the source tree, and makes commits to their topic branch

Note the commit message, it’s composed of three things, the type of the commit feat meaning a feature being added, the scope of the commit (auth) meaning that this commit affects the authorisation section of the code, and a small message on the change add login function.

There’s no reason that the commit message cannot be extended onto multiple lines if further explanation is required, keeping in mind, that most things in software development are about communicating to other developers (including future you/me!) why something happened.

git add auth.go
git commit -m "feat (auth): add login function"

The developer will make more commits, and then move on to the next phase, creating a Pull Request, sometimes also known as a Change Request.

To do that the developer needs to share their branch, and the best place for it to be shared is on the central repository where the project’s source code already resides.

In the time between the clone, and the developer’s changes, the tip of main (the most recent commit) may have changed, other developers may have added their commits to the main branch.

So, the first thing our developer does is synchronises their copy of main.

git checkout main
git pull

And then the developer moves their branch to the (new) tip of main, using rebase.

git checkout create_login
git rebase main

There might be conflicts, that is, git may detect that the hunks in the commits of this topic branch might overlap with hunks of commits in main.

Best practice is to rebase the branch commits, such that the commit being edited is the one that conflicts.

Finding that commit is a bit of detective work, you can use git bisect, but generally I usegit log --stat and look for the commit with changes to the files mentioned in the error.

Once the offending commit is found, it needs to be edited - let’s imagine it was the 3rd most recent commit in the topic branch. The developer would then use rebase to got back in history to that commit so that they can make the necessary changes.

git rebase -i HEAD~3

Then make the necessary changes, then get everything back on track

git add <changed file>
git rebase --continue

And push the topic branch to the central repository

git push --set-upstream origin create_login

A reviewer can then inspect the changes, recommend some improvements, and provide general feedback.

The developer then rebase and merge the topic branch into main (typically this is done using github’s web UI).

Summary

It seems like a torturous and dangerous journey, and people often avoid rebase because it can lead to a loss of work (if you ever get to a point where you think work is going to be lost, you can git rebase --abort, but that’s only going to happen when the topic branch is being changed because of a conflict with main, or during the feedback loop with the reviewer.

The advantage of this methodology is a much cleaner main branch, no messy merge commits, and no loss of history (all of the developers’ commits are now on main).

It is, in my opinion, the superior path to take, and I hope that, with a little practice, you will agree.

Published:
comments powered by Disqus