Note: This is a work-in-progress, Please don't link to this project yet, it isn't ready for an audience yet. Thank you!
vex is a command line tool for tracking and sharing changes, like hg, git, or svn. Unlike other source
control systems, vex comes with vex undo, and vex redo.
Added the wrong file? Run: vex undo
$ vex add wrong_file.txt
$ vex undo
Deleted an important file? Run vex undo
$ vex remove important.txt
$ vex undo
Restored the wrong file? Run vex undo
$ vex restore file_with_changes.txt
$ vex undo
Committed on the wrong branch? Yes, vex undo
$ vex commit
$ vex undo
$ vex branch:save_as testing
Created a project with the wrong settings? ... vex undo!
$ vex init . --include='*.py'
$ vex undo
$ vex init . --include='*.rb' --include='Gemspec'
Undid something by accident? vex redo!
$ vex undo
$ vex redo
- Undo for almost everything!
- Commands are named after their purpose, rather than implemention.
- Tab Completion built in!
- Empty Directories are tracked too.
- You can work on a subdirectory, rather than the project as a whole.
- Output goes through
lessif it's too big for your terminal. - Changed files do not need to be
vex add'd before commit, just new ones - You can change branches without having to commit or remove unsaved changes.
- Branches can have multiple sessions attached, with different changes (committed & uncommited).
... and if there's a bug in vex, it tries its best to leave the project in a working state too!
Install python 3.6, I recommend using the wonderful "Homebrew" tool. Then, enable tab completion:
$ alias vex=/path/to/project/vex # or `pwd`/vex if you're inside the project
$ complete -o nospace -O vex vex
Every vex command looks like this:
vex <path:to:command> <--arguments> <--arguments=value> <value> ...
vex help <command> will show the manual, and vex <command> --help shows usage.
Commands can be one or more names seperated by :, like vex commit or vex undo:list
vex |
hg |
git |
|---|---|---|
vex undo |
hg rollback for commits |
git reset --hard HEAD~1 for commits |
vex redo |
... | ... |
vex undo:list |
... | ... |
vex redo:list |
... | ... |
vex |
hg |
git |
|---|---|---|
vex init |
hg init |
git init |
vex status |
hg status |
git add -u && git status |
vex log |
hg log |
git log --first-parent |
vex diff |
hg diff |
git diff --cached |
vex diff:branch |
hg diff |
git diff @{upstream} |
vex |
hg |
git |
|---|---|---|
vex add |
hg add |
git add |
vex forget |
hg forget |
git remove --cached (-r) |
vex remove |
hg remove |
git remove (-r) |
vex restore |
hg revert |
git checkout -- <file> |
vex switch |
N/A | N/A |
vex |
hg |
git |
|---|---|---|
vex id |
hg id |
git rev-parse HEAD |
vex commit |
hg commit |
git commit -a |
vex commit:amend |
... | git commit --amend |
vex message:edit |
... | ... |
vex message:get |
... | ... |
vex message:amend |
... | ... |
vex |
hg |
git |
|---|---|---|
vex branch:new |
hg bookmark -i, hg update -r |
git checkout -b new old |
vex branch:open |
hg update -r <name> |
git checkout |
vex branch:saveas |
hg bookmark <name> |
git checkout -b new |
vex branch:rename |
hg bookmark --rename |
git branch -m new |
vex branch:swap |
... | ... |
vex branches / branch:list |
hg bookmark |
git branch --list |
The argument to a command can take one the following form:
- Boolean:
--name,--name=true,--name=false - Single value
--name=... - Multiple values
--name=... --name=... - Positional
vex command <value> <value>
There are no single letter flags like, -x. Tab completion works, and vex opts for a new command over a flag to change behaviour.
vex init or vex init <directory>.
$ vex init . --include="*.py" --ignore="*.py?"
$ vex add
$ vex status
... # *.py files added and waiting for commit
By default, vex init name creates a repository with a /name directory inside.
(Note: vex undo/vex redo will undo vex init, but leave the /.vex directory intact)
You can create a git backed repo with vex init --git, or vex git:init. The latter command creates a bare, empty git repository, but the first one will include settings files inside the first commit. vex git:init also defaults to a checkout prefix of / and a branch called master. vex init --git uses the same defaults as vex init, a prefix that matches the name of the working directory, and a branch called latest.
vex undoundoes the last command that changed somethingvex undo:listshows the list of commands that can be undonevex undocan be run more than once,vex redoredoes the last undone commandvex redo:listshows the potential options,vex redo --choice=<n>to pick onevex redocan be run more than once, and redone more than once
vex switch(change repo subtree checkout)
vex addvex forgetvex ignorevex includevex removevex restore
TODO
vex restore --pick*
vex fileprops/vex propertiesvex fileprops:set
vex logvex statusvex diff <file> <file...>vex diff:branch <branch>
vex messageedit messagevex message:getprint messagevex commit <files>vex commit:prepare/ 'vex commit:prepared'
TODO
vex commit:amend*vex commit --pick*vex commit:rollback*vex commit:revert*vex commit:squash* (flatten a branch)
vex branchwhat branch are you onvex branch:newcreate a new branchvex branch:openopen existing branchvex branch:saveas(seegit checkout -b)vex branch:swapvex branch:renamevex brancheslist all branches
TODO
vex branch:close*
vex session(see all open branches/anonymous branches)vex sessions
TODO
vex session:new*vex session:open*vex session:detach*vex session:attach*vex rewind* (like git checkout)
When applying changes from another branch, vex creates new commits with new timestamps
vex commit:apply <branch>*vex commit:append <branch>* create a new commit for each change in the other branch, as-isvex commit:replay <branch>* create a new commit for each change in the branch, reapplying the changesvex commit:apply --squash* create a new commit with the changes from the other branchvex commit:apply --pick*
vex update* (rebase, --all affecting downstream branches too)vex update --manual* (handle conflcts)
vex project:init name*vex mount <branch/remote> <path>*
vex export*vex import*vex pull*vex push*vex sync* (pull, update, push)vex remotes*vex remotes:add*vex serve*vex clone*
vex purge*vex truncate*
vex project:settings*vex project:authors*vex project:set author.name ...*
vex baranch:lock <branch>* (sets a/.vex/settings/policyfile inside a branch with a{branch-name: policy }entryvex branch:set ..*
Store some environment variables and entry points in a settings file, and run those commands
vex env*vex exec/vex run*vex exec:make*vex exec:test*
The directory /.vex/settings/bin/ inside working copy is tracked, and added to the PATH
vex --rson/--json/--yaml* (note: subset of yaml)vex debugvex debug:cat*vex debug:ls*
vex commit --major/--minor/--patch*- /.vex/setting/features *
If vex crashes with a known exception, it will not print the stack trace by default. Additionally, after a crash, vex will try to roll back any unfinished changes. Use vex debug <command> to always print the stack trace, but this will leave the repo in a broken state, so use vex debug:rollback to rollback manually.
Note: some things just break horribly, and a rollback isn't enough. Use vex fake <command> to not break things and see what would be changed (for some commands, they rely on changes being written and so fake gives weird results, sorry).