Skip to content

Instantly share code, notes, and snippets.

@benjaminjt
Created March 29, 2017 14:43
Show Gist options
  • Save benjaminjt/728256a9c5eb3248ed3181c8be2b8be7 to your computer and use it in GitHub Desktop.
Save benjaminjt/728256a9c5eb3248ed3181c8be2b8be7 to your computer and use it in GitHub Desktop.
Sync uncommitted working directory changes with git

GitSync (Working Title)

Fast, one-to-many git working directory sync for uncommitted changes

What

This tool allows a someone to work on a client computer in a normal git workflow (commit sometimes, save often) to sync their local uncommitted working directory state with one or more servers, so that compiler and application services (i.e. the intensive part of a development environment) can be offloaded to more capable, shared, and potentially remote infrastructure.

How

  1. Client checks out git repo (if required)
  2. Client runs GitSyncServer on the desired infrastructure (if required)
  3. Client runs GitSync, and points it to the local git repo and the IP address of GitSyncServer

GitSync

  1. Begins listening to git-change and file-change events (this watcher could be external to the service)
  2. Runs NewSession to negotiate initial state
  3. Binds the git-change event to the NewSession handler
  4. Binds the file-change event to the SyncState handler

NewSession

  1. Terminates any current sessions
  2. Gets the current list of git remotes
  3. Fetches a list of the last N git commit hashes
  4. Makes a NewSessionRequest to the GitSyncServer (parsing the list of git remotes and commits)
  5. GitSyncServer will respond with the latest commit hash that is currently has in common with the list sent from the client
  6. Creates a Session from the common commit hash
  7. Calls Session#BuildPatch on the session object
  8. Calls Session#SendPatchDiff to update GitSyncServer

Session#BuildPatch

  1. Calls git diff --cached $COMMON_COMMIT_HASH and stores the result (the current uncommitted working directory state) along with an id for this patch (random?)
  2. Deletes all stored patches except the two most recent

SyncState

  1. Calls Session#BuildPatch to build the next patch
  2. Calls Session#SendPatchDiff to update GitSyncServer

Session#SendPatchDiff

  1. Checks if Session is currently storing 2 patches a. If 1 patch is stored, make a ApplyPatch request to GitSyncServer with the patch, its id, and the common commit hash b. If 2 patches are stored, continue
  2. Gets a diff from the two most recent patches
  3. Makes an ApplyPatchDiff request to GitSyncServer with that diff, the patch ids of the two patches (parent, and next), and the common commit hash

GitSyncServer

NewSessionRequest

  1. Check the remotes match
  2. Run git fetch
  3. Respond with the most recent common commit hash

ApplyPatch

  1. Checkout the common commit hash (discarding uncommitted changes)
  2. Store the patch and its id as the current patch

ApplyPatchDiff

  1. Checkout the common commit hash (discarding uncommitted changes)
  2. Check that the parent id from client matches the current patch id
  3. Apply the patch diff to the current patch to re-construct the next patch
  4. Call ApplyPatch with the next patch and its id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment