Game of Trees
Game of Trees (Got) is a simple, easy to use
version control system that aims to be compatible
with git repos.
It's still under development, but can be used today
as a substitute for git. It is freely reusable under
a BSD license.
Install
$ doas pkg_add got
Configuring got
First, we need to tell got about the author of the repo:
$ export GOT_AUTHOR="username <username@example.com>"
Replace username
and username@example.com
. It's recommended to add this as part of your ?~/.profile:
$ echo 'export GOT_AUTHOR="username <username@example.com>"' >> ~/.profile
Let's also enable tab-completion of got commands:
$ echo 'set -A complete_got_1 -- $(got -h 2>&1 | sed -n s/commands://p)' >> ~/.profile
By default, got uses the text editor ed if ?$EDITOR or ?$VISUAL are not set.
Clone a repository
To clone a repo without encryption (WARNING: insecure):
$ got clone git://example.com/repo.git
Replace example.com/repo.git
with your actual path.
For this guide, we will use the ngircd git repo as an example:
$ cd ~
$ got clone git://github.com/ngircd/ngircd
To clone a repo using ssh:
$ got clone ssh://example.com/repo.git
For example, to clone OpenBSD's github repo:
$ cd /var/git/
$ got clone ssh://git@github.com/openbsd/src.git
HTTP URLs currently requires ?git:
$ git clone https://github.com/ngircd/ngircd
Checkout code
Once you have a repository, you must first checkout
the code into a work tree before you can use it:
$ got checkout /path/to/repository
Replace /path/to/respository
.
Let's checkout the ngircd code:
$ cd ~
$ got checkout ~/ngircd.git
You can check out code from a specific branch or
commit with -b
and -c
:
$ got checkout -b branch -c commit /path/to/repository
got creates an ID SHA1 hash for every commit, so replace commit
with that hash.
Before we can checkout another work tree from ngircd, we must delete the old one:
$ rm -r ~/ngircd
$ got checkout -b HEAD -c f4ade537d550b872b7e86e6ffce940dfbad4c60c ~/ngircd.git
This will first delete the old work tree, then check out the f4ade537d550b872b7e86e6ffce940dfbad4c60c commit from HEAD of the ngircd.git repo.
got checkout
will show these status codes:
|| border=1 width=50%25 class="sortable simpletable"
||# Status || Meaning ||
|| A || new file added ||
|| E || file already exists ||
For the next step, we will go ahead and delete this work tree, then check out a work tree based on the most recent commit:
$ rm -r ~/ngircd
$ got checkout ~/ngircd.git
Create a new repository
To create an empty repository:
$ got init /path/to/repository
Replace /path/to/repository
. For example:
$ got init ~/ircnowd.git
This will create a got repo called ircnowd.
Afterwards, we need to import the code for the repository:
$ got import -m "Import sources" -r /path/to/repository /path/to/code
Replace /path/to/repository
and /path/to/code
. For example:
$ got import -m "Import sources" -r ~/ircnowd.git ~/ngircd
This will import the code from ngircd
into ircnowd.git
.
Fetch new changes
To fetch changes from a remote repo:
$ got fetch
Add file
To add an unversioned file for the next commit:
$ got add filename
Replace filename
. For example:
$ echo 'print "hello, world"' > ~/ngircd.git/hello.sh
$ got add ~/ngircd.git/hello.sh
If adding a directory:
$ got add -R pathname
-R
allows recursion. Replace pathname
.
Let's add a directory with a file inside ngircd.git
, then begin tracking the directory with got:
$ mkdir -p ~/ngircd.git/newcode/
$ echo 'print "IRCNow and Forever"' > ~/ngircd.git/newcode/ircnow.sh
$ got add -R ~/ngircd.git/newcode
Remove file
To remove a versioned file for deletion from the repo in the next commit:
$ got remove filename
Replace filename
.
Let's remove hello.sh:
$ got remove ~/ngircd.git/hello.sh
If removing a directory:
$ got remove -R pathname
-R
allows recursion. Replace pathname
.
Let's remove the newcode
directory:
$ got remove -R ~/ngircd.git/newcode/
View changes
To view changes in a work tree:
$ got diff
If you provide two objects, got will show the diff between just those two:
$ got diff object1 object2
Replace object1
and object
with the ID SHA1 hash.
For example:
$ got diff ab0eb099e9c0ed60d25fb50dd78d2a638d3b49b8 f4ade537d550b872b7e86e6ffce940dfbad4c60c
This will give you the diff of two files with those ID hashes.
Blame
For a line-by-line history of a file:
$ got blame /path/to/file
Use -c commit
and replace committ
with the ID SHA1 hash to start history from that specific commit. For example:
$ cd ~/ngircd
$ got blame -c 71ae2b7d ~/ngircd/NEWS
Update
To update the work tree to the most recent commit on the work tree's branch:
$ got update
This will require manual merging of files if there are conflicts.
|| border=1 width=100%25 class="sortable simpletable"
||# Status || Meaning ||
|| U || file updated, no local changes ||
|| G || file updated, local changes merged ||
|| C || file updated, conflicts occurred during merge ||
|| D || file deleted ||
|| A || new file added ||
|| ~ || versioned file blocked by non-regular file ||
|| # || missing versioned file restored ||
|| # || file not updated due to merge conflicts ||
|| ? || changes for an unversioned file not merged ||
NOTE: If there are staged changes, you must first commit or unstage them before using got update
.
Suppose we check out a specific commit:
$ cd ~
$ rm -r ngircd
$ got checkout -b HEAD -c f4ade537d550b872b7e86e6ffce940dfbad4c60c ~/ngircd.git
We can then update a specific commit:
$ got update -c c8b12af1d2d155ec79dc2044a4ff177cf07de4fe
View status
To view the status of files in a work tree:
$ got status
|| border=1 width=100%25 class="sortable simpletable"
||# Status || Meaning ||
|| M || modified ||
|| A || added in next commit ||
|| D || deleted in next commit ||
|| C || modified or added but contains merge conflicts ||
|| # || versioned file expected but missing ||
|| ~ || versioned file blocked by non-regular file ||
|| ? || unversioned item, not tracked ||
If changes are staged, the second column uses these codes:
|| border=1 width=100%25 class="sortable simpletable"
||# Status || Meaning ||
|| M || modification staged ||
|| A || addition staged ||
|| D || deletion staged ||
Show History
To show commit history:
$ got log
This will produce a log of all commits from the current
branch:
...
-----------------------------------------------
commit ab0eb099e9c0ed60d25fb50dd78d2a638d3b49b8
from: Alexander Barton <alex@barton.de>
date: Tue Dec 11 22:04:21 2001 UTC
- Test auf stdint.h (HAVE_STDINT_H) hinzugefuegt.
-----------------------------------------------
commit f4ade537d550b872b7e86e6ffce940dfbad4c60c
from: Alexander Barton <alex@barton.de>
date: Tue Dec 11 21:53:04 2001 UTC
Initial revision
To display commits from other branches -b
, starting at a
specific commit -c
, limited by the number of commits
-l
:
$ got log -b -c commit -l N
Replace commit
with the ID SHA1 hash and N
with the
number of commits.
For example:
$ got log -b -c 71ae2b7d7f9ae7bc02ed072c07100de0027373d6 -l 10
-----------------------------------------------
commit 71ae2b7d7f9ae7bc02ed072c07100de0027373d6 (master, origin/master, tags/rel-26.1)
from: Alexander Barton <alex@barton.de>
date: Sat Jan 2 13:32:48 2021 UTC
ngIRCd Release 26.1
...
It's also possible to show commits that match a regular expressions:
$ got log -s regex
Replace regex
with a regular expression:
$ got log -s ssl
-----------------------------------------------
commit daa88b765111b14047c97256bd2a9a2daabe123b
from: Christoph Biedl <ngircd.anoy@manchmal.in-ulm.de>
date: Mon Dec 5 22:51:07 2016 UTC
via: Alexander Barton <alex@barton.de>
Fix building ngIRCd with OpenSSL 1.1
...
Branching
To print the name of the current branch of the work tree:
$ cd /path/to/worktree
$ got branch
To list all the branches:
$ got branch -l
Inside a work tree, you can create a branch and switch to it:
$ got branch branchname
Replace branchname
.
You can also delete a branch:
$ got branch -d branchename
Only the branch reference branchname
is deleted; commit, tree, and blob objects remain in the repo.
To branch at a specific commit:
$ got branch -c commit branchname
Replace commit
with the ID SHA1 hash and replace branchname
. For example:
$ got branch -c 02850008f4a4e8fff5799157d21ee7924345b3e1 gnutls
This creates the gnutls branch of ngircd.
Tags
To list all existing tags:
$ got tag -l
To create a tag pointing to the most recent commit:
$ got tag -m "Message" tagname
Replace tagname
and Message
.
To create a tag pointing to a specific commit:
$ got tag -c commit -m "Message" tagname
Replace commit
with the ID SHA1 hash and replace Message
and tagname
. For example:
$ got tag -c 3c627dd70d032fa2c5087617da27586cf85e899a -m "Debian OpenSSL Build" debopenssl
This will create the debopenssl
tag to point to commit 3c627dd70d032fa2c5087617da27586cf85e899a
.
Revert changes
If you make any changes to files or folders in a work tree,
you can revert those changes:
WARNING: There is no way to undo reverted changes!
$ got revert /path/to/file
Replace /path/to/file
. Files added with got add
become unversioned, and files deleted with got remove
are restored.
To be safe, use -p
so that got asks before reverting.
You can also add -R
for recursion:
$ got revert -R -p /path/to/folder
For example:
$ cd ~/ngircd
$ mkdir JUNK
$ echo "Here is some new junk" > JUNK/INFO
$ got add -R JUNK/
$ got revert -R -p JUNK/
Commit
To commit changes in a work tree:
$ got commit -m "Commit message"
Replace Commit message
with a commit message.
If changes have been staged, only staged changes will be
committed.
|| border=1 width=50%25 class="sortable simpletable"
||# Status || Meaning ||
|| M || modified file ||
|| D || file deleted ||
|| A || new file added ||
NOTE: If changes are not based on the most recent
commit, you may first be required to run got update
before commits can be made.
NOTE: Before running got commit
, make sure to set
up the GOT_AUTHOR environment variable (see above).
Send Changes
To send changes to a remote repo:
$ got send -r ssh://path.com/to/repo
Replace ssh://path.com/to/repo
with the protocol and URL.
By default, if no remote repo is provided, the work tree's origin (its default repo) will be used.
Changes are only be sent if they are based on up-to-date branches in the remote repo. If not, new changes must first be fetched with got fetch
and local branches must be rebased with got rebase
. -f
ignores this requirement.
WARNING: Try to avoid -f
because it may result
in inconsistent tags in different repos.
To send all branches:
$ got send -r ssh://path.com/to/repo -a
Replace path.com/to/repo
. To specify a specific branch:
$ got send -r ssh://path.com/to/repo -b branchname
Replace branchname
. To delete a branch (only references
are deleted):
$ got send -r ssh://path.com/to/repo -d branchname
Rebase
When you have multiple branches, you may want to rebase
the commits of one branch onto your current branch:
$ got rebase branchname
Replace branchname
. Note that branchname
must have a
common ancestor with the current branch.
Commits from branchname
are made to the work tree's current branch.
To show a list of past rebases:
$ got rebase -l
Staging
To stage for the next commit:
$ got stage
To stage just one file:
$ got stage /path/to/file
stage [-l] [-p] [-F response-script] [-S] [path ...]
|| border=1 width=50%25 class="sortable simpletable"
||# Status || Meaning ||
|| A || addition staged ||
|| M || modification staged ||
|| D || deletion staged ||
If there are staged changes, got commit will not commit
any paths that do not have staged changes.
To list staged changes:
$ got stage -l
If a file is out of date compared with the work tree's current branch, you must run got update
before staging.
To unstage all changes:
$ got unstage
To unstage a single file:
$ got unstage /path/to/file
Info
To show metadata about a work tree:
$ got info
To show additional data about a file:
$ got info /path/to/file