Skip to content

Instantly share code, notes, and snippets.

@frg
Last active April 30, 2023 08:19
Show Gist options
  • Save frg/99c384f0960ae22c103c2499afd5ff38 to your computer and use it in GitHub Desktop.
Save frg/99c384f0960ae22c103c2499afd5ff38 to your computer and use it in GitHub Desktop.

Find which version(s) a commit is in (GitFlow)

A Bash script that helps you find branches containing a specific commit in a Git repository. The script filters branches based on the GitFlow naming conventions. The output lists the versions in which the commit exists, sorted according to SemVer.

Usage

./find_commit_versions.sh -c <commit-hash> [-r <repository-path>]

Arguments

  • -c (required): The commit hash to search for in the branches.
  • -r (optional): The path to the Git repository. Defaults to the current directory if not provided.

Example

./find_commit_versions.sh -c cc7486d -r /path/to/git/repository

Script Behaviour

  1. Checks if the required commit hash argument is provided.
  2. Validates the provided repository path, or uses the current directory as the default path.
  3. Fetches the latest commits from the remote silently.
  4. Finds all remote branches containing the specified commit.
  5. Filters the branches based on the following conditions:
    • The branch name is exactly "master".
    • The branch name matches the pattern "release/v{major}.{minor}.{patch}", where major, minor, and patch are numbers separated by periods.
  6. Replaces the "master" or "main" branch name with "production", replaces "develop" with "development" and extracts versions from release branches.
  7. Sorts the output list according to SemVer (major, minor, and patch).

Output

The commit cc7486d exists in the following versions:
development
production
v1.2.1
v1.2.2
v1.3.0
#!/bin/bash
usage() {
echo "Usage: $0 -c <commit-hash> [-r <repository-path>]"
echo " -c: The commit hash to search for (required)."
echo " -r: The path to the Git repository (optional, defaults to the current directory)."
}
# Check if any arguments are provided
if [ "$#" -eq 0 ]; then
usage
exit 1
fi
repo_path="."
commit_hash=""
while getopts ":c:r:" opt; do
case "${opt}" in
c)
commit_hash="${OPTARG}"
;;
r)
repo_path="${OPTARG}"
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
usage
exit 1
;;
:)
echo "Option -${OPTARG} requires an argument." >&2
usage
exit 1
;;
esac
done
# Check if the commit hash is provided
if [ -z "${commit_hash}" ]; then
echo "Error: commit-hash is required."
usage
exit 1
fi
# Check if the provided path is a valid Git repository
if ! git -C "${repo_path}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Error: The provided path is not a valid Git repository."
exit 1
fi
# Fetch the latest commits from the remote (suppress output)
if ! git -C "${repo_path}" fetch >/dev/null 2>&1; then
echo "Error: Failed to fetch the latest commits from the remote."
exit 1
fi
# Find all branches containing the commit
branches=$(git -C "${repo_path}" branch -r --contains "${commit_hash}")
if [ -z "${branches}" ]; then
echo "No branches contain the commit ${commit_hash}."
else
# Filter branches with "release/" prefix, "master", "main" or "develop" branch
filtered_branches=$(echo "${branches}" | grep -E '(\brelease\/v[0-9.]+$|\bmaster$|\bmain$|\bdevelop$)')
if [ -z "${filtered_branches}" ]; then
echo "No release or master branches contain the commit ${commit_hash}."
else
# Replace "master" with "production" and extract versions from release branches
output_list=$(echo "${filtered_branches}" | sed -E 's@.*release/([^/]+)@\1@;s@.*master@production@;s@.*main@production@;s@.*develop@development@')
# Sort the output list according to SemVer (major, minor, and patch)
sorted_output_list=$(echo "${output_list}" | sort -t '.' -k 1,1n -k 2,2n -k 3,3n)
echo "The commit ${commit_hash} exists in the following environments:"
echo "${sorted_output_list}"
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment