Background & Motivations
I’ve been a Mercurial user since about 2017. It’s always worked well for me, but I’ve found myself wondering over the last couple of years if another VCS might be a better fit for me. One reason is that I’m not an advanced user, using only a fraction of what Mercurial has to offer. I don’t collaborate with anyone else so I only need to record changes, push my code out to backup servers, revert (occasionally), email patches to my production servers etc.
So today, I decided to use Got to track changes on a real project and this post documents how it went.
Installation
We’ll need to download and compile Got from here. At the time of writing version 0.113 is the latest. Then, it’s the usual:
./configure
make
sudo make install
Which will install Got to /usr/local
To check everything worked, run:
simon@computer:~$ got -h
usage: got [-hV] command [arg ...]
commands: init import clone fetch checkout update log diff blame tree status ref branch tag add remove patch revert commit send cherrypick backout rebase histedit integrate merge stage unstage cat info
The Got Way
One of the things I found most appealing about Got is that repositories and work trees have to live in different locations. When you think about it, that makes complete sense. Most of us are used to having our repo’s inside our working directory. Yes, it’s convenient but I’ve now come to the conclusion that it’s not optimal. Your repo is one thing, your working directory is another thing.
Creating the Repo and importing code
As this project is a static web site, I dectided to create a separate directory for my repo:
got init /home/simon/tmp/repo/first_project.got
There’s no requirement to append .got
to the project, but it reminds me what I’m using.
simon@computer:~/tmp$ tree repo/first_project.got/
Let’s have a look to see what Got has created for us:
tree repo/first_project.got
repo/first_project.got/
├── config
├── description
├── HEAD
├── objects
│ └── pack
└── refs
4 directories, 3 files
Looks good. The next step may seem a bit clunky, but is what we need to do:
- Import code into our repository
- Check out the repository to a worktree
Right now, our repo is empty. Let’s do our first checkin:
simon@computer:~/tmp$ got import -r repo/first_project.got/ first_project/
A /home/simon/tmp/first_project/css/pico.min.css
A /home/simon/tmp/first_project/css/tacit.min.css
A /home/simon/tmp/first_project/fonts/Inter-Italic-VariableFont_opsz,wght.woff2
A /home/simon/tmp/first_project/fonts/Inter-VariableFont_opsz,wght.woff2
A /home/simon/tmp/first_project/software/visitors/index.html
A /home/simon/tmp/first_project/banner.png
A /home/simon/tmp/first_project/index.html
Created branch refs/heads/main with commit 95f800a6d501db76d7fe56978e6c396d0c3736bb
Now that our working directory’s contents have been added to our repo, we can delete the working directory and check out a worktree:
simon@computer:~/tmp$ rm -r first_project
simon@computer:~/tmp$ got co repo/first_project.got/ first_project
A first_project/asus.png
A first_project/css/pico.min.css
A first_project/css/tacit.min.css
A first_project/fonts/Inter-Italic-VariableFont_opsz,wght.woff2
A first_project/fonts/Inter-VariableFont_opsz,wght.woff2
A first_project/index.html
A first_project/software/visitors/index.html
Checked out refs/heads/main: 95f800a6d501db76d7fe56978e6c396d0c3736bb
Now shut up and hack
Now, inside our worktree
simon@computer:~/tmp/first_project$ got log
-----------------------------------------------
commit 95f800a6d501db76d7fe56978e6c396d0c3736bb (main)
from: Simon Harrison <mail@simonh.uk>
date: Sun Jun 8 20:16:54 2025 UTC
First checkin
Got uses a hidden directory to keep track of things — .got
. Let’s see what’s in there:
simon@computer:~/tmp/first_project$ ll
total 116K
drwxr-xr-x 6 simon simon 4.0K 2025-06-08 21:21 .
drwxrwxrwx 11 simon simon 4.0K 2025-06-08 21:21 ..
-rw-r--r-- 1 simon simon 84K 2025-06-08 21:21 asus.png
drwxr-xr-x 2 simon simon 4.0K 2025-06-08 21:21 css
drwxr-xr-x 2 simon simon 4.0K 2025-06-08 21:21 fonts
drwxr-xr-x 2 simon simon 4.0K 2025-06-08 21:21 .got
-rw-r--r-- 1 simon simon 4.6K 2025-06-08 21:21 index.html
drwxr-xr-x 3 simon simon 4.0K 2025-06-08 21:21 software
simon@computer:~/tmp/first_project$ tree .got
.got
├── base-commit
├── file-index
├── format
├── head-ref
├── lock
├── path-prefix
├── repository
└── uuid
1 directory, 8 files
Obviously, we’ll leave all that alone as Got will update them as we check in changes.
So at this point, we’re all setup to track changes to our code. The last thing I want to do right now is set up a backup that I can push to one of my servers.
We’ll do that in our repo:
simon@computer:~/tmp/first_project.got$ nano got.conf
And add the following, adjusting to fit your server
remote "simonh" {
server myserver.com
protocol ssh
repository "/home/simon/repo/got/first_project.got"
}
For this to work, we need to create a Got repo on our server that matches the repository
value above.
With this done, we can got send
our changes. By the way, most commands have aliases:
ci
— commitco
— checkoutse
— sendfe
— fetchpa
— patch
Consult the excellent man pages for the full list. Let’s send our changes to keep them safe:
simon@computer:~/tmp/first_project$ got se simonh
Connecting to "simonh" ssh://myserver.com/home/simon/repo/got/first_project.got
2 commits colored; 3 objects found; 6 trees scanned
packing 1 reference; 3 objects; deltify: 100%; uploading pack: 2.7K 100%
Server has accepted refs/heads/main
Got also comes with Tog, a CLI repository browser:
Creating & Listing Tags
Tags are equivalent to Mercurial bookmarks — a label for a commit.
simon@computer:~/tmp/first_project$ got tag -l
-----------------------------------------------
tag 0.2 807e609a829c43a9f3f9c8d4c1214b4371fe4485
from: Simon Harrison <mail@simonh.uk>
date: Sun Jun 8 16:12:03 2025 UTC
object: commit 3aa38f1608aee14a1a90a7eae3928f83e4c14baa
Second test of using tags
-----------------------------------------------
tag 0.1 c291af4175f48db379169437ac1a09e381a631f8
from: Simon Harrison <mail@simonh.uk>
date: Sun Jun 8 13:34:21 2025 UTC
object: commit 8e431b7a506992d02d5e39b283652bb5d3ae9d03
Just testing out tags
Passing -s
gives us a short one line summary:
simon@computer:~/tmp/first_project$ got tag -ls
2025-06-08 commit:3aa38f1608 0.2: Second test of using tags
2025-06-08 commit:8e431b7a50 0.1: Just testing out tags
We can create a tag easily:
simon@computer:~/tmp/first_project$ got tag '0.3'
Created tag d1d6792cb83866567525f66875b983faf7dcd4d7
simon@computer:~/tmp/first_project$ got tag -sl
2025-06-09 commit:f257381e43 0.3: Third version
2025-06-08 commit:3aa38f1608 0.2: Second test of using tags
2025-06-08 commit:8e431b7a50 0.1: Just testing out tags
Branching & Merging
To be honest, I don’t branch. If that changes I’ll update this section.
Conclusion
Initial setup for basic tracking of changes should take no more than fifteen / twenty minutes. Once you’ve done that, you’ll have a nice, well-documented VCS that has a tight focus. I’m going to continue using Got for this one project. I should point out that Got is not Git. Many features are not implemented (and may never be). However, it’s perfectly usable right now and if you’re looking for a no frills VCS, Got may be just what you need.
See Also
I wrote a post last year first look at Got which may be of interest.