251 lines
6.0 KiB
Bash
Executable File
251 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Git Utility Functions
|
|
#
|
|
# General utility functions for git operations and formatting.
|
|
#
|
|
# Author: Claude Code get-git-diff skill
|
|
# Version: 1.0.0
|
|
|
|
set -euo pipefail
|
|
|
|
#######################################
|
|
# Get current branch name
|
|
# Outputs:
|
|
# Branch name, or "HEAD" if detached
|
|
#######################################
|
|
get_current_branch() {
|
|
local branch
|
|
|
|
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "HEAD")
|
|
echo "${branch}"
|
|
}
|
|
|
|
#######################################
|
|
# Get default branch (main or master)
|
|
# Outputs:
|
|
# Default branch name, or empty if not found
|
|
#######################################
|
|
get_default_branch() {
|
|
if git rev-parse --verify main >/dev/null 2>&1; then
|
|
echo "main"
|
|
elif git rev-parse --verify master >/dev/null 2>&1; then
|
|
echo "master"
|
|
else
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
#######################################
|
|
# Format diff filename
|
|
# Arguments:
|
|
# $1 - first commit short hash
|
|
# $2 - second commit short hash
|
|
# $3 - extension (optional, default: md)
|
|
# Outputs:
|
|
# Formatted filename like "diff_abc123_def456.md"
|
|
#######################################
|
|
format_diff_filename() {
|
|
local hash1="$1"
|
|
local hash2="$2"
|
|
local ext="${3:-md}"
|
|
|
|
echo "diff_${hash1}_${hash2}.${ext}"
|
|
}
|
|
|
|
#######################################
|
|
# Get repository root directory
|
|
# Outputs:
|
|
# Absolute path to repository root
|
|
#######################################
|
|
get_repo_root() {
|
|
git rev-parse --show-toplevel 2>/dev/null
|
|
}
|
|
|
|
#######################################
|
|
# Get repository name
|
|
# Outputs:
|
|
# Name of the repository (directory name)
|
|
#######################################
|
|
get_repo_name() {
|
|
local root
|
|
|
|
root=$(get_repo_root)
|
|
if [[ -n "${root}" ]]; then
|
|
basename "${root}"
|
|
fi
|
|
}
|
|
|
|
#######################################
|
|
# Get remote URL (if available)
|
|
# Arguments:
|
|
# $1 - remote name (optional, default: origin)
|
|
# Outputs:
|
|
# Remote URL or empty if not found
|
|
#######################################
|
|
get_remote_url() {
|
|
local remote="${1:-origin}"
|
|
|
|
git remote get-url "${remote}" 2>/dev/null || echo ""
|
|
}
|
|
|
|
#######################################
|
|
# Check if commit is reachable from another
|
|
# Arguments:
|
|
# $1 - ancestor commit
|
|
# $2 - descendant commit
|
|
# Returns:
|
|
# 0 if reachable, 1 if not
|
|
#######################################
|
|
is_ancestor() {
|
|
local ancestor="$1"
|
|
local descendant="$2"
|
|
|
|
git merge-base --is-ancestor "${ancestor}" "${descendant}" 2>/dev/null
|
|
}
|
|
|
|
#######################################
|
|
# Get common ancestor of two commits
|
|
# Arguments:
|
|
# $1 - first commit
|
|
# $2 - second commit
|
|
# Outputs:
|
|
# Common ancestor commit hash
|
|
#######################################
|
|
get_common_ancestor() {
|
|
local commit1="$1"
|
|
local commit2="$2"
|
|
|
|
git merge-base "${commit1}" "${commit2}" 2>/dev/null
|
|
}
|
|
|
|
#######################################
|
|
# Format timestamp
|
|
# Arguments:
|
|
# $1 - format (optional, default: "%Y-%m-%d %H:%M:%S")
|
|
# Outputs:
|
|
# Formatted current timestamp
|
|
#######################################
|
|
format_timestamp() {
|
|
local format="${1:-%Y-%m-%d %H:%M:%S}"
|
|
|
|
date "+${format}"
|
|
}
|
|
|
|
#######################################
|
|
# Create directory if it doesn't exist
|
|
# Arguments:
|
|
# $1 - directory path
|
|
# Returns:
|
|
# 0 if successful or already exists
|
|
#######################################
|
|
ensure_directory() {
|
|
local dir="$1"
|
|
|
|
if [[ ! -d "${dir}" ]]; then
|
|
mkdir -p "${dir}"
|
|
fi
|
|
}
|
|
|
|
#######################################
|
|
# Get git config value
|
|
# Arguments:
|
|
# $1 - config key (e.g., user.name)
|
|
# Outputs:
|
|
# Config value or empty if not set
|
|
#######################################
|
|
get_git_config() {
|
|
local key="$1"
|
|
|
|
git config --get "${key}" 2>/dev/null || echo ""
|
|
}
|
|
|
|
#######################################
|
|
# Check if working directory is clean
|
|
# Returns:
|
|
# 0 if clean, 1 if dirty
|
|
#######################################
|
|
is_working_tree_clean() {
|
|
git diff-index --quiet HEAD -- 2>/dev/null
|
|
}
|
|
|
|
#######################################
|
|
# Get list of all branches
|
|
# Arguments:
|
|
# $1 - type: "local", "remote", or "all" (default: local)
|
|
# Outputs:
|
|
# List of branches, one per line
|
|
#######################################
|
|
get_branches() {
|
|
local type="${1:-local}"
|
|
|
|
case "${type}" in
|
|
local)
|
|
git branch --format='%(refname:short)' 2>/dev/null
|
|
;;
|
|
remote)
|
|
git branch -r --format='%(refname:short)' 2>/dev/null
|
|
;;
|
|
all)
|
|
git branch -a --format='%(refname:short)' 2>/dev/null
|
|
;;
|
|
*)
|
|
echo "Error: Invalid branch type: ${type}" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#######################################
|
|
# Check if ref exists
|
|
# Arguments:
|
|
# $1 - ref name (branch, tag, commit)
|
|
# Returns:
|
|
# 0 if exists, 1 if not
|
|
#######################################
|
|
ref_exists() {
|
|
local ref="$1"
|
|
|
|
git rev-parse --verify "${ref}" >/dev/null 2>&1
|
|
}
|
|
|
|
# Allow script to be sourced or run directly
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
# Example usage
|
|
echo "=== Git Repository Utilities ==="
|
|
echo ""
|
|
|
|
echo "Current branch: $(get_current_branch)"
|
|
echo "Default branch: $(get_default_branch)"
|
|
echo "Repository root: $(get_repo_root)"
|
|
echo "Repository name: $(get_repo_name)"
|
|
|
|
remote_url=$(get_remote_url)
|
|
if [[ -n "${remote_url}" ]]; then
|
|
echo "Remote URL (origin): ${remote_url}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Git user name: $(get_git_config user.name)"
|
|
echo "Git user email: $(get_git_config user.email)"
|
|
|
|
echo ""
|
|
if is_working_tree_clean; then
|
|
echo "Working tree: clean"
|
|
else
|
|
echo "Working tree: dirty (uncommitted changes)"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Example filename: $(format_diff_filename "abc123" "def456")"
|
|
echo "Current timestamp: $(format_timestamp)"
|
|
|
|
echo ""
|
|
echo "=== Local Branches ==="
|
|
get_branches local | head -5
|
|
local_count=$(get_branches local | wc -l)
|
|
if [[ ${local_count} -gt 5 ]]; then
|
|
echo " ... and $((local_count - 5)) more"
|
|
fi
|
|
fi
|