Perhaps you’re testing across multiple machines and don’t want to push incomplete code. Maybe you’re working with a collegue on a particularly long flight. Or perhaps your main repository has become unreachable, and you don’t know when it will be back.
At its core, Git is designed to not require a central service or authority to work. This might come as something of a surprise, since most projects use a central authority such as GitHub, GitLab or BitBucket. However, within your pulled repository exists a complete history of your pulled branch’s changes, from the very first commit.
Because of this, any machine can act as a Git server. This can be leveraged even with the general internet unavailable; no special services or daemons are required. Not even a reliable network connection is required, so long as your have a USB drive handy. All that you need between two computers is both having git, and both able to communicate in some way.
## Option 1 – Bare repo on shared media
Those of us who collaborated with others in a pre-internet world know the usefulness of sneakernet. For the rest who are unaware, this is basically comprised of adding your data to media storage (these days, probably a USB drive) and phyiscally walking it over to where it needs to be. This is perhaps the simplest way to get around a downed service issue [xxx – revisit, don’t like wording].
To do this, first we initialize a bare repo on our media:
“`
cd /media/usb
git init –bare repo.git
“`
Then, we can add this path as a remote to push to
“`
cd ~/src/repo
git remote add usb-stick /media/usb/repo.git
git push usb-stick main
“`
Finally, we unmount the USB and bring it to the target machine and run the same setup before pulling:
“`
cd ~/src/repo
git remote add usb-stick /media/usb/repo.git
git pull usb-stick main
“`
Now, in order to sync later, the chosen media can be passed back and forth as your temporary central repository.
If you only need to pass a repository and not later share history, an even simpler cludgel is available. With the above example, `/media/usb/repo.git` is effectively a copy of `~/src/repo/.git`. It would also be possible to simply:
“`
cp -r ~/src/repo/.git /media/usb/repo.git
“`
Then, on the target machine:
“`
mkdir ~/src/repo
~/src/repo/
cp -r /media/usb/repo.git ~/src/repo/.git
git reset –hard
“`
At this point, you have a carbon copy of the history and a working source directory. Actually a bit better than the prior solution for initial sharing, because this method would share all branches on the source machine as well, instead of needing to individually push the same branches.
## Option 2 – Direct peer-to-peer over local IP
It’s also possible with a bridge, hotspot, or even just direct connection to do this over a two terminal network. In this example, we will assume that the source computer has an IP of 192.168.1.10 on this network.
It’s important to preface this by adding: don’t do this outside of an isolated network as this makes your served repo readable to anyone on your network. It’s the sort of solution meant for long car rides and international flights, not general use.
On our source machine:
“`
# Make our service path
mkdir -p /srv/git && cd /srv/git
# Init a bare repo
git init –bare repo.git
# Add this local repo to your remotes; like the USB method, we can simply use the path
cd ~/src/repo
git remote add local /srv/git/repo.git
git push local main
# Return to the service path and launch the git daemon
cd /srv/git
git daemon –base-path=. –export-all –reuseaddr –verbose –port=9418
“`
This invokes a lightweight, read-only service daemon that is built into git, running on git’s default port of 9418. It requires no authentication, which is fine for our very small, isolated network.
Then, our target can clone directly from this repository:
“`
cd ~/src
git clone git://192.168.1.10/repo.git
“`
Best practices would have both machines running their own daemon, commiting and pushing to their local path and each machine pulling from each other. If it’s more desirable however, one can also have our source machine act as a central authority. Again, not to be used outside an isolated network, and with additional peril, taht this method would allow not only readability to everything on the network, but writability as well.
“`
# Before running `git daemon`:
cd /srv/git/repo.git
git config receive.denyCurrentBranch ignore # `warn` is also an option in place of `ignore`
cd /srv/git
# Note the addition of –enable=receive-pack
git daemon –base-path=. –export-all –reuseaddr –verbose –port=9418 –enable=receive-pack
“`
## Option 3 – With SSH transport (most realistic for an office or VPN setting)
If `sshd` is available, changes can be pushed directly using SSH without running any daemon.
Note for MacOS: enable Remote Login in Sytem Settings -> General -> Sharing -> Advanced -> Remote Login
For Linux: `systemctl start sshd` (assuming the sshd package is available)
For Windows: You will require WSL, then installing the relevant package (most distros use the package `openssh-server`) and then port forwarding. This is beyond the scope of this guide, but it should be searchable, knowing what to look for.
This will also likely require permissions handling, also beyond the scope of this guide. For Linux, search for how to add users and ssh public keys and group permissions with `chmod` or `setfacl`.
As before, we will set up a directory for our repo and push to it normally:
“`
# Make our service path
mkdir -p /srv/git && cd /srv/git
# Init a bare repo
git init –bare repo.git
# Add this local repo to your remotes; like the USB method, we can simply use the path
cd ~/src/repo
git remote add local /srv/git/repo.git
git push local main
“`
Then, for our target machine, we can clone directly as if a path over SSH:
“`
git remote add machine1 ssh://user@192.168.1.10/srv/git/repo.git
git pull machine1 main
“`
If you wish to learn about more retro way of creating patch files (the method of choice for collaboration over email), I suggest looking into the offical documention for these methods https://git-scm.com/docs/git-bundle, https://git-scm.com/docs/git-send-email and https://git-scm.com/docs/git-format-patch.
| MT, Software and Platform Engineer Versatile software developer with expertise in programming (C, C++, Python, PHP, JavaScript), databases, cross-platform systems, and debugging, specializing in UNIX/Linux and Windows environments. |

