#!/bin/bash # # Save/restore your .git/config files in a central place. # # When called as "git-config-save" or "git config-save", # this scripts traverses a folder looking for all .git/config files # and makes backups at ~/.config/gitconfigs. # # When called as "git-config-restore" or "git config-restore" # it does the reverse operation: restores all .git/config # files, replacing the current repository .git/config's by the one # available from ~/.config/gitconfigs. # # Use cases: # # - You work with the repositories in multiple machines and is # looking for a way to sync not just the content but also the # same repository configuration (user name, remotes, etc). # # - You want to delete working copies of repositories but want # to keep each repository configuration for future use. In that # case all you have to do is to clone the repository again and # run this command inside your working copy. # # You may want to put in a schedule job to process all your stuff regularly. # # Storage format: # # - Use ~/.config/gitconfigs/ as base. # - Repository identifier is determined by it's path in the system. # That's the best choice if you have the same repository checked out # multiple times and with different configurations. # - Repository identifier can also be determined by the first commit ID # (not repo URL or any other volatile information). So this # script may fail if you're doing improbable stuff like rebasing # your repo and removing the initial commit. # # How it saves an item: # # - Find all git configurations. # - Make a backup at $BASE/$ID/config.$DATE if config differs. # - Save the config at $BASE/ID. # # How it restore an item: # # - Copy each config from $BASE/ID, if available and if it differs. # - Restore always save a timestamped copy at .git/config.$DATE. # Parameters BASENAME="`basename $0`" BASE="$HOME/.config/gitconfigs" DATE="`date +%Y%m%d%I%M%S`" FILENAME="gitconfig.saved" OPTION="$1" COUNTER="$BASE/counter" SOMETIMES="20" # Ensure we have a base and that is minimally safe mkdir -p $BASE chmod 700 $BASE # Save config from a repository function git_config_save { # Check if we have a config if [ ! -e ".git/config" ]; then echo "$BASENAME: missing config at `pwd`" return fi # Repository ID # https://stackoverflow.com/questions/34874343/how-can-i-uniquely-identify-a-git-repository #ID="`git rev-list --parents HEAD | tail -1`" ID="$PWD" # Display ID #echo $ID # Create config folder mkdir -p $BASE/$ID # Make a backup if [ -f "$BASE/$ID/$FILENAME" ] && ! diff .git/config $BASE/$ID/$FILENAME &> /dev/null; then echo "Differences detected at `pwd`, making a backup..." cp $BASE/$ID/$FILENAME $BASE/$ID/$FILENAME.$DATE fi # Save cp .git/config $BASE/$ID/$FILENAME } # Restore config tor a repository function git_config_restore { # Check if we have a config if [ ! -e ".git/config" ]; then echo "$BASENAME: missing config at `pwd`" return fi # Repository ID # https://stackoverflow.com/questions/34874343/how-can-i-uniquely-identify-a-git-repository #ID="`git rev-list --parents HEAD | tail -1`" ID="$PWD" # Display ID #echo $ID # Create config folder mkdir -p $BASE/$ID # Check if we have a saved config if [ ! -f "$BASE/$ID/$FILENAME" ]; then echo "No config for `pwd`, skipping" return fi # Make a backup if ! diff .git/config $BASE/$ID/$FILENAME &> /dev/null; then cp .git/config .git/config.$DATE else echo "Identical configs for `pwd`, skipping" return fi # Restore cp $BASE/$ID/$FILENAME .git/config # Tell the user about the backup echo "Backup saved at $pwd/.git/config.$DATE" } # Check option if [ ! -z "$OPTION" ] && [ "$OPTION" == "--sometimes" ]; then if [ ! -e "$COUNTER" ]; then echo 0 > $COUNTER fi COUNT="`cat $COUNTER`" if (($COUNT >= $SOMETIMES)); then echo 0 > $COUNTER else let COUNT++ echo $COUNT > $COUNTER echo "Running only sometimes. This is run ${COUNT} of ${SOMETIMES}, skipping." exit 1 fi fi # Process everything we can find find -type d -name .git | while read repo; do # Get absolute folder PWD="`cd $repo/.. &> /dev/null && pwd`" #echo -n -e "Processing $PWD...\t" echo "Processing $PWD..." ( cd $PWD if [ "$BASENAME" == "git-config-save" ]; then git_config_save else git_config_restore fi ) done