https://github.com/rraval/git-nomad
Synchronize work-in-progress git branches in a light weight fashion
https://github.com/rraval/git-nomad
git
Last synced: 5 months ago
JSON representation
Synchronize work-in-progress git branches in a light weight fashion
- Host: GitHub
- URL: https://github.com/rraval/git-nomad
- Owner: rraval
- License: mit
- Created: 2021-05-24T12:49:53.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2025-05-30T18:33:33.000Z (6 months ago)
- Last Synced: 2025-06-04T13:49:00.064Z (5 months ago)
- Topics: git
- Language: Rust
- Homepage:
- Size: 6.85 MB
- Stars: 22
- Watchers: 2
- Forks: 2
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# git-nomad
[](https://coveralls.io/github/rraval/git-nomad)
[](https://rraval.github.io/git-nomad/doc/git_nomad/)
[](https://github.com/rraval/git-nomad/issues)
[](https://github.com/rraval/git-nomad/releases/latest)
[](https://github.com/rraval/git-nomad/commits/master)
[](https://github.com/rraval/git-nomad/blob/master/LICENSE)
Synchronize work-in-progress git branches in a light weight fashion. Motivation:
- You frequently work on the same repository from multiple machines, like a laptop and a desktop.
- You frequently rewrite history and use short understandable-by-only-you branch names, making pushing regular branches to git remotes cumbersome.
- You want all the efficiency and synchronization benefits of having a git clone available, meaning external syncing tools like Dropbox or network mounts are right out.
- You want this synchronization to work out-of-the-box with popular third party remote hosts like GitHub.
[](https://rraval.github.io/git-nomad/demo.html)
## Usage
[Install `git-nomad`](#installation) to make it available on your `$PATH`.
Assume you're hacking away with your usual git workflow:
```console
rraval@desktop:~/git-nomad$ git checkout -b feature
rraval@desktop:~/git-nomad$ touch new_file
rraval@desktop:~/git-nomad$ git add .
rraval@desktop:~/git-nomad$ git commit -m "new file"
```
Whenever you like, you can push the state of your local branches with:
```console
# Synchronizes with a remote called `origin` by default.
# See `--help` for overriding this explicitly.
rraval@desktop:~/git-nomad$ git nomad sync
Pushing local branches to origin... 3s
Fetching branches from origin... 0s
Listing branches at origin... 3s
desktop
refs/nomad/desktop/feature -> c340cd55853339e4d039746495cdb80cd9e46123
refs/nomad/desktop/master -> 267719fb8448cc1cbef2c35a638610573779f2ac
```
---
At some future point, you wish to pick up development on a different machine:
```console
rraval@laptop:~/git-nomad$ git nomad sync
Pushing local branches to origin... 2s
Fetching branches from origin... 1s
Listing branches at origin... 2s
desktop
refs/nomad/desktop/feature -> 1a101799507ba67d822b97105aafa0ac91ce5183
refs/nomad/desktop/master -> 267719fb8448cc1cbef2c35a638610573779f2ac
laptop
refs/nomad/laptop/master -> 267719fb8448cc1cbef2c35a638610573779f2ac
```
Which prints out refs to use to pick up where you left off:
```console
rraval@laptop:~/git-nomad$ git checkout -b feature refs/nomad/desktop/feature
# Hack away where you left off on desktop
```
---
Let's say that the `laptop` machine is where development is happening now, so
you go back to `desktop` to throw away the now outdated branch:
```console
rraval@desktop:~/git-nomad$ git checkout master
rraval@desktop:~/git-nomad$ git branch -D feature
Deleted branch feature (was 1a10179).
rraval@desktop:~/git-nomad$ git nomad sync
Pushing local branches to origin... 2s
Fetching branches from origin... 1s
Listing branches at origin... 0s
Pruning branches at origin... 0s
Delete refs/nomad/desktop/feature (was 1a101799507ba67d822b97105aafa0ac91ce5183)... 0s
desktop
refs/nomad/desktop/master -> 267719fb8448cc1cbef2c35a638610573779f2ac
laptop
refs/nomad/laptop/feature -> dedf3f9d3ad279a401877b351c3ec13aa47cbbd4
refs/nomad/laptop/master -> 267719fb8448cc1cbef2c35a638610573779f2ac
```
---
If you'd like to stop using `git-nomad` and clean up all the refs it has created:
```console
# See also the `purge --host` option.
rraval@desktop:~/git-nomad$ git nomad purge --all
Fetching branches from origin... 1s
Listing branches at origin... 0s
Pruning branches at origin... 2s
Delete refs/nomad/desktop/master (was 267719fb8448cc1cbef2c35a638610573779f2ac)... 0s
Delete refs/nomad/laptop/feature (was dedf3f9d3ad279a401877b351c3ec13aa47cbbd4)... 0s
Delete refs/nomad/laptop/master (was 267719fb8448cc1cbef2c35a638610573779f2ac)... 0s
```
## How it works
Git is unabashedly a [content-addressed filesystem][git-cafs] that manipulates `blob`, `tree`, and `commit` objects. Layered on top of this is a half decent version control system, though this claim is contentious at best.
Git branches are implemented on top of [a more general scheme called `refs`][git-refs], where the local branch `master` is simply the commit pointed to by `refs/heads/master`. Git reserves a few hierarchies for its own use:
- `refs/heads/*` represent local branches.
- `refs/tags/*` represent tags.
- `refs/remotes/*` represent remote branches.
`git-nomad` works directly with refs to implement its own light weight synchronization scheme:
1. Push local `refs/heads/*` to remote `refs/nomad/{user}/{host}/*`. This allows multiple users on multiple hosts to all use `git-nomad` on the same remote without overwriting data.
2. Fetch remote `refs/nomad/{user}/*` to local `refs/nomad/*`. This makes all the host refs for a given user available in a local clone.
3. Prune local `refs/nomad/*` refs where the corresponding branch has been deleted.
Using refs like this has advantages:
- You only pay the storage cost for the content unique to the branch. The bulk of repository history is shared!
- As refs get cleaned up, `git`s automatic garbage collection should reclaim space.
- Since these refs are under a separate `refs/nomad` hierarchy, they are not subject to the usual fast-forward only rules.
## Installation
[](https://repology.org/project/git-nomad/versions)
### On Linux or Mac OS X
Releases on GitHub have prebuilt binary assets: https://github.com/rraval/git-nomad/releases
1. Download the latest version for your OS.
2. Place the binary somewhere in your `$PATH` named `git-nomad`.
3. Check that things work with `git nomad --version`.
### On NixOS / via Nix
Install via [nixpkgs][nixpkg]:
```
$ nix-env --install git-nomad
```
### From source
If you have [`cargo`][cargo] available:
```
$ cargo install git-nomad
```
## Bleeding Edge
### Via `nix run`
Nix can build and run the binary directly from GitHub via:
```
$ nix run github:rraval/git-nomad
```
## Contributing
There are a few ways to make this project better:
1. Try it and [file issues][new-issue] when things break. Use the `-vv` flag to capture all information about the commands that were run.
2. Build packages for various operating systems.
[cargo]: https://www.rust-lang.org/tools/install
[git-cafs]: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
[git-refs]: https://git-scm.com/book/en/v2/Git-Internals-Git-References
[new-issue]: https://github.com/rraval/git-nomad/issues/new
[nixpkg]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/version-management/git-nomad/default.nix