Rsync script to keep files at most recent state

24 Views Asked by At

I have a folder with a lot of cloned git repositories, but I don't always code locally. Sometimes I change the code directly on a remote machine, where the code is usually executed. So far, I've used rsync to update the machine in which I intend to work next, but I always have to keep track of where the code is more recent, or else I'm at risk of mixing up source and destination and losing some progress. And that goes for each of the repositories separately!

So, I'm trying to come up with a way of always keeping both machines synced at the most recent state of the repositories, no matter which one has it. I'm thinking of putting together a script which would consist of this (I'd run it on the root folder containing my git repositories, so it always sync them all at once):

rsync -avzru local_folder/ remote_folder
rsync -avzru remote_folder/ local_folder

I'm already used to the tags avzr (archive mode, verbose, compression and recursive), but this time, I'd be using the u (update) tag too, which should ignore a file transfer if it's had a more recent change at the destination.

Would running both of these commands in a row every time solve my problem? I'm open to any corrections and suggestions to improve on my solution.

1

There are 1 best solutions below

0
galabov On

If the most recent change for both directories is a deletion in local_folder this sync:

rsync -avzru local_folder/ remote_folder
rsync -avzru remote_folder/ local_folder

will revert the deletion change (restore the files/dirs) regardless of the execution order.

There are different approaches to this problem, setting up a VPN to your server and pushing to one place only, using mirror repos (may not be applicable in this situation), git submodules, having multiple push targets, and so on.

If the idea is to stick to this approach, then my suggestion, that will only work if you do not make changes to both the remote and local directories before a sync, will be to track the modification timestamps of all directories and sync accordingly.

The creation/modification/deletion of files/directories that are direct children to directory A/ will update the modified timestamp of directory A/, but will not change the modified timestamp of the parent directory of directory A/. This can be observed by running ls -lFa in between performing changes.

To get the last modification time for directory A/ according to all it's contents and the directory itself (execute in the parent directory of A/):

# get all of the dirs in dir 'A/' -> get the timestamps -> sort desc then take the first
find "A" -type d -exec stat -c %Y {} + | sort -nr | head -n 1

Syncing 2 directories:

#!/bin/bash

dir1="A"
dir2="B"

latest1=$(find "$dir1" -type d -exec stat -c %Y {} + | sort -nr | head -n 1)
latest2=$(find "$dir2" -type d -exec stat -c %Y {} + | sort -nr | head -n 1)

if [ $latest1 -gt $latest2 ]; then
    echo -e "\033[0;32m$dir1 is more recent. Synchronizing to $dir2...\n\033[0;0m"
    rsync -avz --delete "$dir1/" "$dir2"
elif [ $latest1 -lt $latest2 ]; then
    echo -e "\033[0;32m$dir2 is more recent. Synchronizing to $dir1...\n\033[0;0m"
    rsync -avz --delete "$dir2/" "$dir1"
else 
    echo -e "\033[0;32mAlready up to date.\n\033[0;0m"
fi