Skip to content

Instantly share code, notes, and snippets.

@ErnestoCobos
Last active February 20, 2024 14:19
Show Gist options
  • Save ErnestoCobos/2a5242289d0a08b8e9641b36ea751e1b to your computer and use it in GitHub Desktop.
Save ErnestoCobos/2a5242289d0a08b8e9641b36ea751e1b to your computer and use it in GitHub Desktop.
Git configuration automation script to apply specific user settings per project based on the current directory. Includes detailed setup instructions for Zsh users, ensuring consistent and correctly attributed commits across client projects.
#!/bin/bash
# Git Configuration Automation Script with Directory Management
# -------------------------------------------------------------
# This enhanced script automates the process of applying Git configurations
# based on the current working directory, ensuring all repositories for a specific
# client use the correct Git user name and email settings. It is essential for maintaining
# consistent commit metadata across projects and minimizing the risk of commits being
# attributed to the wrong user. Additionally, it now includes functionality to detect
# when a project (repository) is deleted from or re-added to the client's directory,
# updating the configuration accordingly.
#
# How It Works:
# The script reads a JSON configuration file (`git-configs.json`) that contains mappings
# between directory paths and the corresponding Git configurations (user name and email),
# along with a list of subdirectories (`subDirs`) under each path. When executed, it
# checks the current directory against the configured paths and applies the matching Git
# configuration if found. If a repository is deleted or re-added, the script updates
# `subDirs` to reflect these changes, ensuring the Git configuration is accurate and current.
#
# JSON Configuration File Structure:
# The configuration file should be structured as follows, with each key being a path
# to a client's main directory, and each value being an object with `email`, `name`,
# and `subDirs` properties for Git configuration and directory tracking.
#
# Example:
# {
# "/Users/username/Projects/ClientA": {
# "email": "clienta@example.com",
# "name": "Client A",
# "subDirs": ["/Users/username/Projects/ClientA/Repo1", "/Users/username/Projects/ClientA/Repo2"]
# },
# "/Users/username/Projects/ClientB": {
# "email": "clientb@example.com",
# "name": "Client B",
# "subDirs": ["/Users/username/Projects/ClientB/Repo1"]
# }
# }
#
# Setup Instructions for Zsh Users:
# 1. Place the `git-configs.json` file in a directory accessible by this script.
# 2. Ensure this script is executable by running `chmod +x this_script_name.sh`.
# 3. To execute this script automatically in Zsh, open your `.zshrc` file in a text editor,
# add a line to source this script when a new shell session starts, and use the `chpwd`
# hook to execute this script after each directory change. Save the changes to `.zshrc`
# and apply them by running `source ~/.zshrc` or by opening a new terminal window.
#
# Usage:
# Navigate to a project directory in your terminal, and the script will automatically apply
# the appropriate Git configuration based on the current directory's match in the
# `git-configs.json` file. It will also update the configuration if projects are deleted
# or re-added to the client's directory, ensuring accurate and up-to-date Git settings.
#
# Note: This script requires `jq` for JSON parsing. Ensure it is installed and available in
# your PATH.
#
# Following these setup and usage guidelines, teams can streamline their Git workflow,
# ensuring all commits are correctly attributed and consistent across projects for each client,
# and dynamically manage project directories within each client's configuration.
# Workflow Diagram:
# +----------------------------------+ +-------------------+ +---------------------+ +------------------------+
# | Manually add the folder and | | Verify if the | No | Read the JSON | | Iterate over each |
# | configuration in +------->+ current directory +------->+ configuration file +------>+ configured directory |
# | git-configs.json | | is a Git repo | | (git-configs.json) | | in the JSON |
# +----------------------------------+ +--------+----------+ +---------------------+ +------------+-----------+
# | |
# Yes |
# | |
# v v
# +-----+------+ Configuration not exists / +-------------------------+ +--------------------------------+
# | End script | already applied for this dir | Apply Git configuration | | Update JSON file with the |
# | execution |<------------------------------------ + (name, email) and +------>+ current directory added to |
# +------------+ | update `subDirs` | | `subDirs` |
# +-------------------------+ +--------------------------------+
# Path to the JSON configuration file, located in the same directory as this script
CONFIG_FILE="$HOME/.config/git-configs.json"
# This script dynamically applies Git configurations based on the current directory.
# It reads settings from a JSON file, located in the same directory as the script.
# The JSON file contains key-value pairs where each key is a path to a directory
# (or parent directory of multiple repositories), and the value is an object
# containing 'email' and 'name' for Git configuration.
# JSON File Structure Example:
# {
# "/Users/username/Projects/ClientA": {
# "email": "clienta@example.com",
# "name": "Client A",
# "subDirs": ["/Users/username/Projects/ClientA/Repo1", "/Users/username/Projects/ClientA/Repo2"]
# },
# "/Users/username/Projects/ClientB": {
# "email": "clientb@example.com",
# "name": "Client B",
# "subDirs": ["/Users/username/Projects/ClientB/Repo1"]
# }
# }
# Each key in the JSON file represents a directory path for which the specified
# Git configuration (email and name) should be applied. This allows for different
# Git configurations to be automatically applied based on the current working directory.
# Function to apply Git configuration
apply_git_config() {
local config_email=$(jq -r ".[\"$1\"].email" "$CONFIG_FILE")
local config_name=$(jq -r ".[\"$1\"].name" "$CONFIG_FILE")
local config_subdirs=$(jq -r ".[\"$1\"].subDirs[]" "$CONFIG_FILE")
# Check if configuration exists for the path and has not been applied yet
if [ "$config_email" != "null" ] && [ "$config_name" != "null" ] && [[ ! " $config_subdirs " =~ " $CURRENT_DIR " ]]; then
git config user.email "$config_email"
git config user.name "$config_name"
# Update the 'subDirs' array in the JSON file
jq --arg dir "$1" --arg subdir "$CURRENT_DIR" 'if .[$dir].subDirs == null then .[$dir].subDirs = [$subdir] else if (.[$dir].subDirs | index($subdir)) == null then .[$dir].subDirs += [$subdir] else . end end' "$CONFIG_FILE" > temp.$$ && mv temp.$$ "$CONFIG_FILE"
fi
}
# Check if the current directory is a Git repository
if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
# Iterate through the directories defined in the JSON file and apply configuration if the current directory matches or is a subdirectory
CURRENT_DIR=$(pwd)
for KEY in $(jq -r 'keys[]' "$CONFIG_FILE"); do
if [[ "$CURRENT_DIR" == "$KEY"* ]]; then
apply_git_config "$KEY"
break
fi
done
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment