Within IT there are lots of different ways to solve problems, architect solutions, deploy applications, etc. And when we look at the options that Git gives us for code management, there are lots of different commands and tools packed within it.
In this article I want to explore Git tags and branches and understand the lingo as well as the use cases.
Within the gitglossary we have the definition for a branch.
A "branch" is a line of development. The most recent commit on a branch is referred to as the tip of that branch. The tip of the branch is referenced by a branch head, which moves forward as additional development is done on the branch. A single Git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the "current" or "checked out" branch), and HEAD points to that branch.
In a working environment, where and how does a branch fit in?
Lots of engineers create a new branch from the production branch to work on a bug fix or to add a new feature, or to experiment with something. Using a branch doesn’t affect the production code. When they have finished their work they can then request a review of the code and their branch is merged into the production branch.
Branches work well as they avoid anyone directly working on the production branch of code. Also, having separate branches for features or bug fixes means that each engineer can work independently and doesn’t directly impact any other engineer's work. The other advantage branches give you is the ability to carry out reviews and testing on individual branches without holding up other work that might be happening.
The biggest disadvantage of branches comes when merging. It can be time consuming when you come to merge a branch into the production one if there are merge conflicts.
If we go back to the gitglossary a tag is defined as:
A ref under refs/tags/ namespace that points to an object of an arbitrary type (typically a tag points to either a tag or a commit object). In contrast to a head, a tag is not updated by the commit command. A tag is most typically used to mark a particular point in the commit ancestry chain.
Tags are a great way of marking significant events within your code base. When it comes to releasing a new version of your product, you can tag it. It can also be a way of referencing a point in time within your code for later reference. You can easily find that point in the code using a tag, it is much harder, if not impossible to find that point in time within a branch alone.
Let’s take a look at the workflow and commands you’d typically encounter if you were using branches.
If you’d like to create a new branch from the production code, then you would use the command:
git checkout -b branchname
This command creates the branch and also switches your working context to be in that branch. From here you can start to make your changes and commit files and they will be attached to the branch you’ve just created.
When you create a branch on your desktop or workstation it won't automatically create within the remote location as well. So after you have made your changes and committed them it’s time to push those changes to the remote location.
You have to use a slightly different command than just_ git push_ to do this, as you need the branch to be created in the remote location. The command you would use is:
git push -u origin branchname
Of course, if your branch already exists in the remote location, you can just run
If you have multiple branches on your machine and not sure which branch you are working within you can use the following command to check:
If you discover you are working within the wrong branch, you can change the branch you are working within using the following command:
git checkout branchname
If you wish to create a new tag to associate with your latest code changes to achieve that you would use the git tag command. An example would be:
git tag v2.0
Much like branches, any changes you make to your local copy of the code base is not automatically reflected automatically in the remote repository. To ensure your tag is pushed to the remote repository alongside any of your code changes you need to explicitly tell Git to do that.
To do that you would use the command:
git push --tags
If you wish to see what tags are already associated with the repository and code then you can use the following command to see that information:
When working within a CI/CD pipeline environment there are lots of different ways a team might deploy to production. Teams can choose to follow a specific branching strategy that works best for them.
Some of the most common are branching strategies are:
Each has their own advantages and disadvantages. There is no right branching strategy, it’s up to an individual team to choose what works for them.
For this article we are going to take a closer look at how the GitFlow strategy uses branches and tags.
Within the GitFlow process you will have the main branch of code where all production history is stored and it’s the single source of truth for the team.
There will then be other branches that are used to work on features or bug fixes. One branch will typically be used as the development environment, where new features are worked on.
Other branches will branch off the development branch and they will again have their own purpose, a new feature or bug fix for example. These branches will merge back into the development branch and not directly interact with the main branch.
Once the development branch has enough features within it for a release it will be time to push those changes into the main branch. This is also the time when a tag will be attached to code to signify that new release, for example the engineer might tag it v4.0.
Git branches and Git tags have their place in any development environment. Branches are great for helping engineers work on coding features or bug fixes without touching the main code branch. While tags are great for labelling a point in time within the code, for example a new release of your application.
These Git features aren’t competing features.
They aren’t alternatives to each other.
They are features that can work together to add functionality and flexibility to your workflow.
If you aren’t already using both of these features in your development environment, please do take the time to discuss with your team the introduction of them.