/ GIT, CHERRY-PICK, BASH

Cherry-pick automation with Bash

I manage my Jekyll blog in a Git repo. My publication process uses 2 branches:

  • master contains all production content
  • feature/newposts has the new blog posts, ready to get published, one commit per post

To publish an existing post:

  1. I check the to-be-published post in the feature/newposts branch
  2. Then, get the associated commit
  3. And cherry pick it in the master branch
  4. Finally, I push

While not that slow, this is very boring. This post explains how I "automated" the above process using bash magic.

Date

Bash users know how to get the current date:

date

This outputs:

Sun Aug  5 12:15:23 CEST 2018

However, the Jekyll blog post filename is formatted as 2018-08-05-xxx-yyy-zzz.adoc. Having a look at the man page, the relevant syntax is:

date +'%Y-%m-%d'

It outputs the expected string:

2018-08-05

Path

To get the path of a file in a Git tree, one needs to use the git ls-tree command:

git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'`

This yields:

100644 blob 2cb14109c9a41b67609b93a9fea904735d082a5c	_posts/2018-08-05-spring-boot-integration-intellij-idea.adoc

Note that the hash is the blob’s hash, and not the commit’s hash. From that point, there are two ways:

  1. Get the commit with this blob
  2. Get the commit with this path

For no real reason, I chose the second option.

To get the path only, the output needs to be cut:

git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-

This now correctly prints:

_posts/2018-08-05-spring-boot-integration-intellij-idea.adoc

Commit

git log is the command to get the commit for a specific path. It allows a branch option.

git log feature/newposts -- $(git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-)

This outputs:

commit dcc9dc60dc7ee615f35703c9a8e696d2dcae6d41
Author: Nicolas Fränkel <nicolas@frankel.ch>
Date:   Sun Apr 1 23:36:20 2018 +0200

    Add Spring Boot integration in IntelliJ IDEA post

      Fix #25

To limit the output to the commit value, use the --format option:

git log feature/newposts --format=%H -- $(git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-)

The result is:

dcc9dc60dc7ee615f35703c9a8e696d2dcae6d41

Cherry-pick

The final step is to cherry-pick the relevant commit. At this point, this is a no-brainer:

git cherry-pick $(git log feature/newposts --format=%H -- $(git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-))

Final touch

I didn’t find a way to cherry-pick into a specific branch, so that it adds the commit to the current one.

The above command just needs to be padded with a checkout to the master branch, and back.

git checkout master && \
git cherry-pick $(git log feature/newposts --format=%H -- $(git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-)) && \
git checkout -

As we’ve seen in an earlier post, if the snippet above is written in a bash script whose name starts with git- and that is located on the PATH, then it’s possible to invoke it through git:

git-publish
#!/bin/bash
git checkout master && \
git cherry-pick $(git log feature/newposts --format=%H -- $(git ls-tree -r feature/newposts  | grep `date +'%Y-%m-%d'` | cut -c54-)) && \
git checkout -

At this point, the script can be invoked like this:

git publish
Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a technologist focusing on cloud-native technologies, DevOps, CI/CD pipelines, and system observability. His focus revolves around creating technical content, delivering talks, and engaging with developer communities to promote the adoption of modern software practices. With a strong background in software, he has worked extensively with the JVM, applying his expertise across various industries. In addition to his technical work, he is the author of several books and regularly shares insights through his blog and open-source contributions.

Read More
Cherry-pick automation with Bash
Share this