# Syncing GitHub repositories local, remote and forks

It's a simple bash script but I'm hoping for feedback, advice and examples on how to improve the script and code. Can you guide me how to put more checks in the code and more if possible?

This code:

• Sets IFS variable and backs it up
• Sets a trap for signals that can kill the script and a trap for exit to do run a cleanup function.
• Then it pushes changes from the local TO the remote repository
• Then it syncs the local copy FROM the repository/fork
• Then there is code to update the Fork from the original but that will be used later on other repositories.
• Then it gives control back to these signals SIGINT SIGQUIT SIGTERM
• Then it's set to send a email with the result/status of what's been run after theexit

#!/usr/bin/env bash

IFS_OLD=$IFS IFS=$'\n\t'

cleanup ()
{
if [ -n "$1" ]; then echo "Aborted by$1"
elif [ $status -ne 0 ]; then echo "Failure (status$status)"
else
echo "Success"

## This is the mail it sent afterwards:

> Github SYNC System Report: Kundrum Hallur Kristjan Stefansson
> <somethingSomething@mail.com>      09:00 (3 hours ago)
> up-to-date with 'origin/master'.

> Finished syncing system and remotes!

> Success

I put it in a cron(crontab -e) on my Debian Stretch 9.9 system:

21 00 * * 7 /bin/bash /home/kristjan/gitRepo_May2019.sh | mail -s "Github SYNC System Report: hostname" somethingSomething@mail.com

Here are other questions on this site with code for the same or similar purpose:

Clone GitHub repository using Python

Python script to synchronise your locally cloned fork to its parent github repository

There's no need to reinstate the initial value of IFS because there's nowhere for the new value to propogate. When your script exits, the new value just ceases to exist. Same goes for the signal handlers.

On that note, why set IFS at all? I can't see any place that it has an effect.

Prefer [[ … ]] over [ … ] for tests (detailed explanation).

When testing for zero, consider an arithmetic test (( … )): it returns true for non-zero and false for zero, and doesn't require $in front of ordinary variable names (specials like$* or $# still need the dollar sign). For example, cleanup() might be rewritten: cleanup() { (($# )) && echo "Aborted by $1" && return (( status )) && echo "Failure (status$status)" && return $status echo "Success" } cd /home/kristjan/gitRepo_May2019/ || { echo "Failed to cd to /home/kristjan/gitRepo_May2019/!!!!!!!!"; exit 155; } This is a common pattern that can benefit from the use of a function: die() { echo "$2"; exit $1; } cd$dir || die 155 "Failed to cd to $dir" Alternatively, the command's error output is usually good enough: cd$dir || exit 155

Or, since you're checking basically everything for error exit, put set -e at the top of the script to make any error fatal.

if ! grep -r up-to-date

Don't use backticks here, recursively grepping STDIN doesn't make any sense, and grep's -w switch is probably appropriate:

if ! grep -w up-to-date