-1

So I have two laptops sharing a github repo (and the same branch). An automated program on one of the laptops is modifying robot.txt and I am manually modifying math.html on the other laptop.

The question is, assuming both laptops have the correct time, how do I achieve the effect of cp -u with git in an automated bash script? Note that git merge --allow-unrelated-histories is not ideal as I frequently run into the case of manually typing git commands to resolve (non-existent) conflicts.

SmoothKen
  • 131
  • 1
  • 2
  • 1
    If the two PCs's clocks are indeed "synchronized", and you only synchronize your source files once or twice a day (long after your actual source updates)... then you have absolutely no problem. Otherwise, if you want "up to the moment" file synchronization ... you might consider putting your repos in a [Dropbox](https://www.dropbox.com/) or an [MS OneDrive ](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage) folder (or equivalent). – paulsm4 Jul 31 '21 at 18:29
  • @paulsm4 The script is syncing every 5 minutes (```sleep 300```). If possible, I wish to use bash script rather than relying on third party software. – SmoothKen Jul 31 '21 at 18:33
  • 1
    Strongly consider using a real automation software. Syncthing, owncloud, nextcloud. No, rsync is not enough for 2-side synchronization, and there are newer stuff then csync. `with git in an automated bash script?` You will have problems and will end up using an automated software anyway. `s not ideal as I frequently` Exactly. So use software created to deal with that. – KamilCuk Jul 31 '21 at 18:39
  • 1
    Do not put your repositories in a cloud file syncing service, since that can cause repository corruption. – bk2204 Jul 31 '21 at 21:15
  • @KamilCuk If I use csync, I may need to setup my own server. rclone may be a good idea though. But here is scenario I am worrying about: imagine laptop1 deletes ```abc.txt``` and get synced to remote, now from laptop2, should the script choose to add ```abc.txt``` back to remote or remove it from local? In the answer I made, git can deal with this by looking at local commit history and conclude that "oh, timestamp is the same but remote get deleted, hence I should delete local". – SmoothKen Aug 01 '21 at 05:55

2 Answers2

2

You could:

  • pull changes
  • add your changes
  • commit these changes
  • push changes

Like:

git pull --rebase --autostash &&
git add -A &&
git commit -m "autosync: $(date -R)" &&
git push

With How do I programmatically determine if there are uncommitted changes? you could add a check if there are any changes.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • More robust than merge. But it seems that file editors will have to reload ```math.html``` (i.e. files we change on our sides) after autostash. – SmoothKen Aug 01 '21 at 18:23
0

Something like the following should work (unless two laptops are modifying the same file, which leads to a push competition). Please let me know if you find any errors/improvements.

if git fetch origin master -q 2>/dev/null
then
    # first add (but do not commit) to compare with origin/master
    git add . -A --ignore-errors

    while read -r file
    do 
        remote_time=`git log origin/master -1 --pretty="format:%at" -- "$file" 2>/dev/null`
        local_time=`git log -1 --pretty="format:%at" -- "$file" 2>/dev/null`
        
        # If remote time is not empty and local time 
        # is either empty (new file from remote) or 
        # has a smaller value (updated file from remote)

        if [[ $remote_time != '' && ($local_time == '' || $remote_time > $local_time) ]]
        then
            git checkout origin/master --no-overlay -- "$file" 2>/dev/null
        fi
    done < <(git diff --name-only origin/master 2>/dev/null)
    # (imagine without the following reset, the HEAD 
    # and working tree now also differs at those files     
    # we obtained from remote just now and therefore 
    # they get committed again.) reset ensures commit 
    # only contains file that we want to update from 
    # our side
    git reset --soft origin/master
    git add . -A --ignore-errors &&
    git commit -m "sync.sh" -q >/dev/null &&
    git push -f origin master -q 
fi
SmoothKen
  • 131
  • 1
  • 2
  • Related https://stackoverflow.com/questions/13594344/force-git-to-always-choose-the-newer-version-during-a-merge. Although none of the answers resolves the question. – SmoothKen Aug 01 '21 at 22:11