# Using Git when collaborators use Dropbox

Hopefully, by now you're convinced of the benefits of using Git for version control; especially considering the vast ecosystem of tooling and collaboration workflows that has sprung up around Git, like GitHub.com and PullRequest.com, among *many* others.

However, inevitably, you will at some point collaborate with someone who still works directly on files in Dropbox. While you're waiting for this collaborator to be awed by your increased productivity and come around to using Git, we need to figure out some way for you to be able to use Git while they continue to use Dropbox.

This is a tricky problem, and unfortunately I'm not aware of any very simple, perfect solution; but there is a workable solution, although it takes some doing.

## The straightforward solution

To start off with, let me suggest the most straightforward solution:

* When you're about to start on a task, copy the contents of the Dropbox folder into a folder somewhere else on your machine.
* In that folder, you use Git, GitHub.com, PullRequest.com, and all the other tooling available to develop your solution on your own (or with other Git collaborators).
* Once you're done, copy your solution back into the Dropbox folder to share it with your team — i.e., share it with them the same way you would have otherwise done.
* They need not know or care that you used Git to version control while developing your solution.

This is a bit cumbersome, and makes it hard to work with other Git collaborators, but it will work.

## Why not just `git init` within Dropbox?

Unfortunately, we can't just initialize a Git repository within Dropbox due to the way that Dropbox continuously syncs changes between all collaborators.

* Your files would start to change under your feet if collaborators edit something, which makes it very hard to write code successfully.
* Similarly, your in-progress changes would start appearing on collaborators' machines; after all, since they aren't using Git, they don't know you're trying to work on a different branch and aren't ready to merge yet.
* As you switch back and forth between branches, you would make your collaborators *very* confused.
* As you are switching between branches and Dropbox is struggling to sync collaborators' machines, there's a risk of the `.git/` folder itself becoming corrupted and thus the repository becoming unusable.

## Our strategy: manage a separate repo inside the Dropbox folder

Our strategy will be to manage a separate copy inside the Dropbox folder, and treat it as if it was a repo on your collaborator's computer; and you will be `git push`ing and `git pull`ing for them.

* We will use Dropbox's "exclude folder" feature to *not* sync the `.git` folder.
* Now, as collaborators make changes to their files, those changes will accumulate in the repo in your Dropbox folder.
* We will assume that when our collaborators share something via Dropbox, it is the equivalent of when we merge something to `main` — it LGTThem and they've shipped it. Therefore, any changes that we see appear in our Dropbox folder, we will merge into `main` on our collaborators' behalf.
* The rest of our workflow will then remain the same; as always, we must remember to `git checkout main; git pull` before starting on any new task so that we base our new branch off of the freshest code.
* The difference is that we have now have a new Git collaborator living inside our Dropbox folder, representing all collaborators who are using Dropbox, and we have to periodically merge their changes to `main` on their behalf.
* We can also `git pull main; git rebase main` while working on an existing feature branch in order to update it with any new commits that have been added to `main` after we originally based our branch on it. (You will have to resolve conflicts, if there are any.)

## Implementation example

Let's see this in practice.

### Download software

Since we need to interact with Dropbox, we can't use Gitpod; we'll have to use our own computer to, at a minimum, do the syncing and merging for our collaborators.

* Ensure that you have [Dropbox](https://www.dropbox.com/install) installed on your computer, you are signed in, and syncing files successfully.
* [VSCode](https://code.visualstudio.com/) is my text editor of choice and virtually the same as the text editor in Gitpod. It has a vast array of extensions, as most text editors do; but, uniquely and particularly relevant to researchers, it has the [Remote - SSH extension](https://code.visualstudio.com/docs/remote/ssh) that you can use with e.g. Mercury.
* You've rolled up your sleeves and learned a lot about the original, command-line interface (CLI) to Git (with all its warts); and even learned about the elegant underlying Git Object Model. You now know more about Git than probably 80% of its users and are well equipped to operate on remote servers and [get out of Git messes](http://justinhileman.info/article/git-pretty/).

  However, it's still very convenient to use a GUI sometimes instead of the CLI. And, if you're trying to convince a non-believer (ahem, Dropbox collaborator) to adopt Git, it's nice to recommend a GUI to start with before scaring them off with Git's awful CLI.

  [GitKraken](https://www.gitkraken.com/) is my preferred graphical user interface (GUI) for Git. There are many others, including [SourceTree](https://www.sourcetreeapp.com/) and [GitHub Desktop](https://desktop.github.com/).

  I like GitKraken because:

  * It has support for all Git features that I commonly use ([including `rebase`](https://youtu.be/xot40u-_1FI), unlike GitHub Desktop).
  * It's free for non-commercial use.
  * It supports Mac, Windows, and Linux.
  * I prefer the UI to other options.
  * It has [excellent documentation, including videos](https://www.gitkraken.com/resources/learn-git).

    [Download GitKraken](https://www.gitkraken.com/download) and make sure you've integrated your GitHub account and set up your SSH keys [as described in this video between 3m48s and 10m42s](https://youtu.be/FNgHFFfI4YE?t=228). (The whole video is worth watching, at some point.) [Here's a GitKraken cheat sheet](https://www.gitkraken.com/resources/gitkraken-cheat-sheet) that you might want to keep handy.

### Start with a Git repository

We can get a Git repository to work with in a multitude of ways:

* Create a repository on GitHub, or choose an existing one, and then [clone it to your computer with GitKraken](https://support.gitkraken.com/working-with-repositories/open-clone-init/#cloning-an-existing-project).
* [Initialize the repository locally](https://support.gitkraken.com/working-with-repositories/open-clone-init/#initialize-a-new-project) with GitKraken. You can choose to, at the same time, push the new repo to GitHub.com.

![Initializing a repository and pushing it to GitHub with GitKraken](/files/-MHL-fX-2q7yz1UbiZEs)

Do *not* save this repository within your Dropbox folder. I have a folder called `code/` in my Home folder, within which I create a folder named after each GitHub organization I belong to, and within each of those I clone repositories that belong to the org. In this example, I created the repository at `~/code/boothresearch/rb-dropbox-project`.

### Open the repository in VSCode

Set VSCode as your editor of choice in GitKraken's preferences:

![Select text editor in GitKraken preferences](/files/-MHL1uDb4AK6bxvwwZiJ)

And then open the repository in VSCode:

![Open repository in VSCode](/files/-MHL3Kul_CazP0zgM9OB)

Once in VSCode, select `New Terminal` from the `Terminal` menu to get to a command prompt:

![Open a Terminal in VSCode](/files/-MHL38lGiufAqWRsaY2d)

This should now feel very familiar; it's almost exactly the same as Gitpod, just on your local computer instead (and [you can SSH to other computers like Mercury, too](https://code.visualstudio.com/docs/remote/ssh)).

### Clone a separate copy into your Dropbox folder

In GitKraken, clone the repository from GitHub into your Dropbox folder:

![Clone a separate copy into your Dropbox folder](/files/-MHM_ow_CncqcH6RNtcs)

You now have two copies of the repository: a new folder in your Dropbox, as well as the original folder you created in e.g. `~/code/boothresearch/`.

## Bringing in changes from Dropbox collaborators

To simulate a collaborator making changes to the repo, edit the README from one of your other connected devices; or, share the Dropbox folder with a friend and ask them to edit the README.

Then, check out the Dropbox clone in GitKraken, or `cd` into the Dropbox project folder in VSCode's Terminal and `git diff`. You should see output similar to:

```diff
rb-dropbox-project main %  cd ~/Dropbox/rb-dropbox-project
rb-dropbox-project main % git diff
diff --git a/README.md b/README.md
index 1ba87ce..eb0e84a 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
 rb-dropbox-project
+
+howdy from a Dropbox collaborator
```

### Commit the change and merge to main

In GitKraken or in the VSCode Terminal, commit and push the Dropbox changes to GitHub:

```
rb-dropbox-project main % git add -A
rb-dropbox-project main % git commit -m "Changes from Dropbox"
[dropbox 80ea966] Changes from Dropbox
 1 file changed, 2 insertions(+)
rb-dropbox-project main % git push
```

Use the GitHub merging flow you learned to merge the changes from Dropbox into `main`:

![Squash and merge to main on GitHub](/files/-MHL9QvpImV9C3xwNPhU)

### Pull the merged `main`

As usual, remember to pull in the changes from GitHub to your local `main` in your code folder; this time, you can use GitKraken:

![Pull changes from GitHub main to local main](/files/-MHL9NQxkRfLvlKTFekm)

Rinse and repeat any time you want to commit changes from your Dropbox collaborators to `main`!

## Sending our changes to Dropbox collaborators

When we do our work, we'll use our standard Git workflow:

* create a new branch for the task
* push to GitHub
* open a PR
* get feedback, code review, static analysis, etc
* refine and push additional commits until it's done
* squash and merge to `main`
* pull the updated `main` to local

Then, to bring those changes to our Dropbox collaborators, in GitKraken or Terminal, we'll pull `main` in the Dropbox repository.

That's that!

## Ignore the `.git` folder

What about the risk of the `.git/` folder becoming corrupted? Also, in case there are other people on your team also using the same trick to use Git in parallel with Dropbox, syncing this folder will cause conflicts between you. So, we should exclude it from Dropbox syncing so it stays local to your machine.

We used to have to use a hack involving Dropbox's "Selective Sync" feature to achieve an "ignored" folder. Fortunately, Dropbox has added [command-line commands to do exactly what we need on Windows, Mac, and Linux](https://help.dropbox.com/files-folders/restore-delete/ignored-files) (see section titled *Set a file or folder to no longer be ignored using the command line*). In my case, on a Mac, the command to ignore the `.git/` folder in the example project is:

```
xattr -w com.dropbox.ignored 1 ~/Dropbox/rb-dropbox-project/.git
```

In Dropbox's web interface, verify that you no longer are syncing the `.git/` folder:

![](/files/-MHVaHbkKbG3_M73MihQ)

Now any other Git collaborators can also freely use the same workflow, and you won't be all stepping on each others' toes.

Hopefully, this will allow you to use Git and all of its associated ecosystem while you're still changing hearts and minds! Good luck!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://handbook.booth.school/using-git-when-collaborators-use-dropbox.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
