Skip to content

Instantly share code, notes, and snippets.

@Ruzzz
Last active September 14, 2025 18:30
Show Gist options
  • Select an option

  • Save Ruzzz/320f090f208af3bbd025322cbfea990d to your computer and use it in GitHub Desktop.

Select an option

Save Ruzzz/320f090f208af3bbd025322cbfea990d to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# Create an archive with Git, GPG, SSH and direnv settings
# Example: ./dump-git-opts.sh my-team ~/Projects/MyTeam
#
set -euo pipefail
if ! command -v realpath &>/dev/null; then
echo "[!] realpath not found, please install coreutils"
exit 1
fi
if ! command -v gpg &>/dev/null; then
echo "[!] gpg not installed, skipping GPG export"
fi
if [ $# -lt 2 ]; then
echo "Usage: $0 <projects_suffix> <projects_dir>"
exit 1
fi
PROJECTS_SUFFIX="${1,,}" # lowercase
BACKUP_DIR="./git-opts-$PROJECTS_SUFFIX"
ARCHIVE_NAME="git-opts-$PROJECTS_SUFFIX.tar.gz"
PROJECTS_DIR="$(realpath --relative-to="." "$2")" # путь относительно текущей папки, не абсолютный
echo "[*] Cleaning temporary directory: $BACKUP_DIR"
rm -rf "$BACKUP_DIR"
mkdir -p "$BACKUP_DIR"/{gpg,ssh,git/projects,direnv}
SIGNING_KEYS=()
# Backup global gitconfig
if [ -f ~/.gitconfig ]; then
echo "[*] Backing up global ~/.gitconfig"
cp ~/.gitconfig "$BACKUP_DIR/git/gitconfig"
main_key=$(git config --global user.signingkey || true)
if [ -n "$main_key" ]; then
SIGNING_KEYS+=("$main_key")
fi
fi
# Backup local .git/config files
echo "[*] Searching for .git/config in $PROJECTS_DIR"
while IFS= read -r -d '' git_config; do
project_path=$(dirname "$git_config")
relative_path="${project_path#$PROJECTS_DIR/}"
dest_path="$BACKUP_DIR/git/projects/$relative_path"
echo " [+] Saving $relative_path/.git/config"
mkdir -p "$dest_path"
cp "$git_config" "$dest_path/config"
key=$(git --git-dir="$project_path" config user.signingkey || true)
if [ -n "$key" ]; then
SIGNING_KEYS+=("$key")
fi
done < <(find "$PROJECTS_DIR" -type f -path "*/.git/config" -print0)
# Collect unique signing keys
if [ ${#SIGNING_KEYS[@]} -gt 0 ]; then
SIGNING_KEYS=($(printf "%s\n" "${SIGNING_KEYS[@]}" | sort -u))
echo "[*] Found ${#SIGNING_KEYS[@]} GPG keys to export"
else
echo "[*] No GPG signing keys found in git configs"
fi
# Export GPG keys
for key in "${SIGNING_KEYS[@]}"; do
echo " [+] Exporting GPG key: $key"
if ! gpg --export "$key" > "$BACKUP_DIR/gpg/${key}_pub.gpg"; then
echo " [!] Failed to export public key: $key"
fi
if ! gpg --export-secret-keys "$key" > "$BACKUP_DIR/gpg/${key}_priv.gpg"; then
echo " [!] Failed to export secret key: $key"
fi
done
# Backup SSH keys
if [ -d ~/.ssh ]; then
echo "[*] Backing up SSH keys"
cp -a ~/.ssh/* "$BACKUP_DIR/ssh/" 2>/dev/null || true
fi
# Backup .envrc files from projects
echo "[*] Searching for .envrc in $PROJECTS_DIR"
while IFS= read -r -d '' envrc; do
relative_path="${envrc#$PROJECTS_DIR/}"
dest_path="$BACKUP_DIR/direnv/$(dirname "$relative_path")"
echo " [+] $relative_path"
mkdir -p "$dest_path"
cp "$envrc" "$dest_path/.envrc"
done < <(find "$PROJECTS_DIR" -type f -name ".envrc" -print0)
# Create final archive
echo "[*] Creating archive: $ARCHIVE_NAME"
tar --owner=0 --group=0 -czf "$ARCHIVE_NAME" -C "$BACKUP_DIR" .
echo "[✔] Backup complete: $ARCHIVE_NAME"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment