For most of today's developers, using Git is akin to breathing, in that you can't live without it. Along with version control, Git's use has even expanded in recent years into the area of GitOps, or managing and versioning configurations through Git. What a lot of users don't realize or think about is that Git tracks not only file changes for each commit but also a lot of meta-data around commits and branches. Your DevOps can leverage this data or automate IT operations using software development best practices, such as with CI/CD.
In my case, I use an automated process (DevOps) whereby a new branch is created every time I promote an image into a downstream CI/CD environment (namespace) in Kubernetes (here is a shameless plug of my Opensource.com article describing the process). This allows me to modify the deployment descriptors for a particular deployment in a downstream CI/CD environment independent of the other environments and enables me to version those changes (GitOps).
I will discuss a typical scenario where a breaking bug is discovered in QA, and no one is sure which build introduced the bug. I can't and don't want to rely on image meta-data to find the branch in Git that holds the proper deployment descriptors for several reasons, especially considering I may need to search one local repository or multiple remote images. So how can I easily leverage the information in a Git repository to find what I am looking for?
Use the for-each-ref command
This scenario is where the
for-each-ref command is of some real use. It allows me to search all my Git repository's branches filtered by the naming convention I use (a good reason to enforce naming conventions when creating branches) and returns the most recently modified branches in descending sort order. For example:
$ git clone firstname.lastname@example.org:elcicd/Test-CICD1.git
$ cd Test-CICD1
$ git for-each-ref --format='%(refname:short) (%(committerdate))' \
origin/deployment-qa-c6e94a5 (Wed May 12 19:40:46 2021 -0500)
origin/deployment-qa-b70b438 (Fri Apr 23 15:42:30 2021 -0500)
origin/deployment-qa-347fc1d (Thu Apr 15 17:11:25 2021 -0500)
origin/deployment-qa-c1df9dd (Wed Apr 7 11:10:32 2021 -0500)
origin/deployment-qa-260f8f1 (Tue Apr 6 15:50:05 2021 -0500)
The commands above clone a repository I often use to test Kubernetes deployments. I then use
git for-each-ref to search the branches by the date of the last commit, restrict the search to the branches that match the deployment branch naming convention for the QA environment, and return the most recent five. These roughly (i.e., not necessarily, but close enough) correspond to the last five versions of the component/microservice I want to redeploy.
deployment-qa-* is based on the naming convention:
The information returned can be used by developers or QA personnel when running the CI/CD redeployment pipeline to decide what version to roll back/forward to in a Kubernetes namespace and thus eventually return to a known good state. This process narrows down when and what introduced the breaking bug in the contrived scenario.
While the naming convention and scenario above are particular to needs and automated CI/CD processes, there are other, more generally useful ways to use
for-each-ref. Many organizations have branch naming conventions similar to the following:
The ID value refers to the ID describing the feature or bug in a project management system like Rally or Jira; e.g.:
This ID allows users to easily and quickly get some added visibility into the greater development history of the repository and project (using
refs/remotes/**/v.123-feature-*), depending on the development process and branch naming convention policies. The process works on tags, too, so listing out the latest pre-prod, prod, or other specific versions could be done almost as easily (not all tags are pulled by default).
These are only particular and narrow examples of using the
for-each-ref. From authors to commit messages, the official documentation provides insight into many details that can be searched, filtered, and reported.