About Gitless
Gitless is an experimental version control system built on top of Git.
Many people complain that Git is hard to use. We think the problem lies
deeper than the user interface, in the concepts underlying Git. Gitless
is an experiment to see what happens if you put a simple veneer on an app
that changes the underlying concepts. Because Gitless is implemented on
top of Git (could be considered what Git pros call a "porcelain" of Git),
you can always fall back on Git. And of course your coworkers you share a
repo with need never know that you're not a Git aficionado.
Check out the documentation to get started. If you are a novice user
that never used any version control system the documentation
should be enough to get you started. If you are a Git pro looking to see
what's different from your beloved Git you'll be able to spot the
differences by glancing through the documentation.
Documentation
Commands
(link will take you to the point in the guide in which the
command is introduced)
Guide
Repository
Say you are in directory foo
and you want turn it into a
local repository. You do this with the
gl init
command. This will transform
the current working directory into an empty Gitless's repository and you
are now ready to start recording changes to files in foo
.
$ mdkir foo
$ cd foo/
$ gl init
# Local repo created in '/MyFiles/foo'
In most cases, there's probably already some existing repository that you
want to start working on instead of creating an empty repository (maybe
you just created a GitHub repo you want to now start using). To make a
local clone of a remote repository you can give the url of the repository
to the same gl init
command.
$ mkdir experiment
$ cd experiment/
$ gl init https://github.com/spderosso/experiment.git
# Initialized from remote
# 'https://github.com/spderosso/experiment.git'
File
A file in Gitless is one of the following: a
"Tracked File," an "Untracked File" or an "Ignored File."
Tracked File
A tracked file is a file whose changes Gitless will automatically detect.
Tracked files are automatically considered for commit if they are
modified. These will appear under the "Tracked files with modifications"
section of the gl status
command.
Untracked File
Conversely, an untracked file is a file whose changes Gitless will not
automatically detect and is listed under the "Untracked files" section of
the gl status
command. These are not automatically considered
for commit.
Ignored File
An ignored file is a file that is completely ignored by Gitless. These won't
even appear in the output of the gl status
command.
An example output of the status command
(foo.py
is a tracked file
with modifications, .gitignore
is an unmodified tracked file,
bar.py
is an untracked file and foo.py~
is an
ignored file):
$ ls
bar.py foo.py foo.py~ .gitignore
$ gl status
# On branch master, repo-directory //
#
# Tracked files with modifications:
# (these will be automatically considered for commit)
# (use gl untrack <f> if you don't want to track changes
# to file f)
# (if file f was committed before, use gl checkout <f>
# to discard local changes)
#
# foo.py
#
#
# Untracked files:
# (these won't be considered for commit)
# (use gl track <f> if you want to track changes to file f)
#
# bar.py
Now, how do files move between these three different disjoint
states?
A file is ignored if it's matched by the ignore specification described in
the .gitignore
file (which is usually present in the root of
the repository).
In the example above,
there is a .gitignore
file whose content is '*~'; since
foo.py~
is matched by that pattern it's therefore an
ignored file.
A new file that is not matched by the ignore spec is initially an untracked
file. If you want to make it a tracked file you can do so with the
gl track
command. A file
that has a commited version in the repository is
automatically a tracked file. You can stop tracking changes to a tracked file
with the gl untrack
command.
You can always revert a file back to some previous version with the
gl checkout
command.
As previously said, all tracked and modified files are automatically
considered for commit. Doing
gl commit
will commit
these changes (once you provide a
commit message). The commit command accepts a bunch of flags to make
selecting a subset of files to commit super easy:
-
Doing
gl commit f1 f2
will only commit files
f1
and f2
. If they are untracked it will make them tracked.
Since only those files specified will be commited this is a handy way
of leaving other tracked modified files out of the commit.
-
But what if you want to commit all of the tracked modified files but
leave one of them out? Having to list them all seems annoying. You
can do
gl commit -exc f
to exclude that file
f
you don't want to commit right now.
-
Additionally you can use the
-inc
flag to include untracked
files in the commit set (it will make them tracked).
Branch
A branch is an independent line of development. Each branch has its own
history (which you can look at with the
gl history
command). Any changes to
existing files or new files you create on a branch will not be present on
the other branch when you switch branches.
A new branch can be created with the
gl branch
command. Once created you will be automatically switched to that branch.
$ gl branch my-branch
# Created new branch my-branch
# Switched to branch my-branch
If you want to switch to another existing branch called master you can do:
$ gl branch master
# Switched to branch master
So, in summary gl branch name
switches to branch
name
and it creates that branch if it doesn't exist. To list all available
branches:
$ gl branch
# List of branches:
# (do gl branch <b> to create or switch to branch b)
# (do gl branch -d <b> to delete branch b)
# (do gl branch -su <upstream> to set an upstream for
# the current branch)
# (* = current branch)
#
# * master
# my-branch
Eventually what will happen is that branches will end up having divergent
changes. There are two ways of bringing changes from one branch onto the
current branch: merge or rebase. (If you have no idea what merge or rebase
mean, you can take look at Git's documentation.) (This will change
in Gitless 1.0 -- which will be released sometime soon.)
For merging the changes in my-branch
onto the current branch you do
gl merge my-branch
,
for rebasing the current branch using as a base my-branch
you do
gl rebase my-branch
.
During this process conflicts could occur. If so, the gl status
command will change
accordingly to indicate the files in conflict. Once you edit those files in
conflict you mark them as resolved with
gl resolve
(passing the files to mark as input). Once all
conflicts have been resolved
you do gl commit
to commit the merge commit in
case of a merge or to continue applying any remaining commits in case of
a rebase.
Of course, it is also possible to merge or rebase changes from remote
branches, or branches that are in remote repositories (not in your local
repository). Let's say "experiment" stands for the remote at
https://github.com/spderosso/experiment.git and that master is a branch
present in that remote repository. If so, doing
gl merge experiment/master
would merge any changes in that remote branch that are not present in your
local current branch. A very common use case is to have a remote
repository you always get changes from and send changes to it so that
others can retrieve them. To make this more easy, a branch can have an
"upstream branch". If a branch has an upstream associated with it, then
gl rebase
or gl merge
can be used as shorthands for
gl {rebase, merge} upstream_remote/upstream_branch
. To set an
upstream branch for the current branch use
gl branch -su upstream_remote/upstream_branch
.
To publish your changes to this upstream branch you can do
gl publish
. If the upstream
branch doesn't exist in the remote, then the branch will be created in the
remote after the publish.
When you create a local repository from a remote (by passing a url as
input to the gl init
command), all branches are
automatically configured to have as upstream their remote counterpart.
Remote
You can always use the direct url to
bring in changes to your local repository from a remote repository but
remembering all those long urls can be annoying. So an easier way is to
add that repository as a "remote" with the
gl remote
command.
For example, let's add my GitHub experiment repository as a remote:
$ gl remote experiment https://github.com/spderosso/experiment.git
# Remote experiment mapping to
# https://github.com/spderosso/experiment.git created successfully
# (to list existing remotes do gl remote)
# (to remove experiment do gl remote -d experiment)
And then you can use experiment/branch as a shorthand for referring to a
branch in the experiment repository.