Skip to content

Instantly share code, notes, and snippets.

@codeaid
Created March 27, 2012 15:07
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save codeaid/5a97956bb0bacd6a38d5 to your computer and use it in GitHub Desktop.
Save codeaid/5a97956bb0bacd6a38d5 to your computer and use it in GitHub Desktop.
SCP added and modified GIT files
#!/bin/bash
escape() {
echo -e "\033[$1"
}
# misc styles
c_reset=`escape 0m`
c_bold_on=`escape 1m` ; c_bold_off=`escape 22m`
c_underline_on=`escape 4m` ; c_underline_off=`escape 24m`
# foreground colors
fg_default=`escape 39m`
fg_black=`escape 30m`
fg_red=`escape "1;31m"`
fg_green=`escape 32m`
fg_brown=`escape 33m`
fg_blue=`escape 34m`
fg_magenta=`escape 35m`
fg_cyan=`escape 36m`
fg_white=`escape 37m`
# background colors
bg_default=`escape 49m`
bg_black=`escape 40m`
bg_red=`escape 41m`
bg_green=`escape 42m`
bg_brown=`escape 43m`
bg_blue=`escape 44m`
bg_magenta=`escape 45m`
bg_cyan=`escape 46m`
bg_white=`escape 47m`
me=$(basename $0)
# ensure we have two arguments
if [ $# -ne 2 ]
then
echo
echo " usage: git scp <username@hostname> <target-dir>"
echo
exit 1
fi
username=$1
# remove trailing slashes
targetdir=$(echo $2 | sed 's/\/*$//g')
# get list of all changed files
changes=$(git status --porcelain 2>&1)
# exit if git status returned an error code
if [ $? -ne 0 ]
then
echo
echo " ${fg_red}$changes${c_reset}"
echo
exit 1
fi
# file counters
num_modified=0
num_deleted=0
# file length counters
maxfilelength=0
filelength=0
# extract added and modified files
files_modified=$(echo "$changes" | awk '{if($1~"A|M") print $2}')
# extract deleted files
files_deleted=$(echo "$changes" | awk '{if($1=="D") print $2}')
# print modified files (if any)
if [ "$files_modified" != "" ]
then
echo
echo " The following files will be COPIED:"
for file in $files_modified;
do
echo " ${fg_green}$file${c_reset}"
((num_modified++))
filelength=$(echo $file | wc -c)
if [ $filelength -gt $maxfilelength ]
then
maxfilelength=$filelength
fi
done
echo " ${fg_cyan}Total files: $num_modified${c_reset}"
fi
# print deleted files (if any)
if [ "$files_deleted" != "" ]
then
echo
echo " The following files will be DELETED:"
for file in $files_deleted;
do
echo " ${fg_red}$file${c_reset}"
((num_deleted++))
filelength=$(echo $file | wc -c)
if [ $filelength -gt $maxfilelength ]
then
maxfilelength=$filelength
fi
done
echo " ${fg_cyan}Total files: $num_deleted${c_reset}"
fi
if [ $num_modified -eq 0 ] && [ $num_deleted -eq 0 ]
then
echo
echo "Nothing to sync"
echo
exit 0
fi
echo
echo -n 'Do you want to continue (yes/no)?: '
read answer
# exit it "yes" or "y" not received
if [ "$answer" != "yes" ] && [ "$answer" != "y" ]
then
echo
exit 1
fi
echo
# copy files
if [ "$num_modified" -gt 0 ]
then
echo " ${c_underline_on}Copying:${c_reset}"
for file in $files_modified;
do
mask=$(printf '%%-%ds' $maxfilelength)
printf " $mask " $file
filedir=$(dirname $file)
cmd="scp $file $username:$targetdir/$filedir"
output=$($cmd 2>&1)
if [ $? -eq 0 ]
then
echo "${fg_green}ok${c_reset}"
else
echo "${fg_red}failed${c_reset} ($output)"
fi
done
echo
fi
# delete files
if [ "$num_deleted" -gt 0 ]
then
echo " ${c_underline_on}Deleting:${c_reset}"
for file in $files_deleted;
do
mask=$(printf '%%-%ds' $maxfilelength)
printf " $mask " $file
filedir=$(dirname $file)
cmd="ssh $username rm -f $targetdir/$file"
output=$($cmd 2>&1)
if [ $? -eq 0 ]
then
echo "${fg_green}ok${c_reset}"
else
echo "${fg_red}failed${c_reset} ($output)"
fi
done
echo
fi
@tanakahisateru
Copy link

Nicer script than me! You are great. I can learn more from you. Thanks :D

I've understood what you wanted from your script. My script aims to upload recently committed changes as daily publishing or such as, but you needed something to test changes before to commit them.

@codeaid
Copy link
Author

codeaid commented Apr 5, 2012

Thanks! I hadn't done bash scripting for a long time. Had to quickly learn it on that day :)

Speaking about the functionality - you're right. I work on my localhost but I need to scp files to the dev server. And just because I can be changing files in different places in the project, copying them one by one quickly got tedious. So I decided to write this script, which would upload everything which is not in the git repository. But otherwise it can be pretty useless as you can't force uploading of unchanged files.

@kneipp
Copy link

kneipp commented Jul 26, 2014

Awesome! Very usefull, thank you for sharing.

@carsonreinke
Copy link

Thanks! FYI, updated because of issues with file/directories with spaces: https://gist.github.com/carsonreinke/3c42730a80dba02e7940d38b193c791e

@carsonreinke
Copy link

I finally just added this repo: https://github.com/carsonreinke/git-scp

@codeaid, I can transfer you ownership, you did most the work.

@kneipp
Copy link

kneipp commented Oct 5, 2020

6 years using your script! ;-)

@codeaid
Copy link
Author

codeaid commented Oct 5, 2020

@kneipp Haha! You madman! I didn't know this script existed until I got the notification. Great to hear that something of what I write is/was actually useful to someone :) Obrigado!

@carsonreinke Hey! Sorry, I completely missed your comments all those years ago! I've never been good at noticing Github notifications :/ That's very kind of you but don't worry about the ownership, you did the work so it's all yours. I put it out for people to use it so if someone finds it useful, that's all I ever wanted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment