JM Tech Power

Version control with jm proj: a complete guide

👁 6 views 👍 0 likes 💬 0 comments
Back to Articles

jm proj is version control and publishing for your projects, right from the terminal. The top-level verbs (jm proj init, commit, branch, merge, push…) are a real, content-addressed version-control system that lives in a local .jm folder — commits, branches, line-level merges, blame and all. Publishing a downloadable release is its own group, jm proj release. This guide walks through both, with copy-paste examples.

Setup

Install the jm CLI from the site, then sign in once — it opens your browser to authorize, just like gh:

jm auth login

That is all the setup you need. Everything below works offline except the sync commands (push, pull, clone, fetch).

Your first repository

Start version control in any folder, stage some files, and commit:

jm proj init                      # create a .jm repository here
jm proj add .                     # stage everything (or: jm proj add file.py)
jm proj commit -m "First commit"
jm proj status                    # what is staged vs unstaged
jm proj log                       # commit history

jm proj add stages changes into an index, exactly like git. A plain commit records what is staged; commit -a stages every tracked change first, so a one-liner is:

jm proj commit -a -m "Fix the parser"

Seeing what changed

jm proj diff                      # working tree vs last commit
jm proj diff HEAD~1 HEAD          # between two commits
jm proj diff --stat               # just a summary of files + line counts
jm proj show HEAD                 # a commit's message and full diff
jm proj blame src/main.py         # who last changed each line

Branches and merging

Create a branch, switch to it, and merge it back. The merge is a real line-level 3-way merge: edits to different parts of the same file merge automatically, and conflict markers appear only where two changes actually overlap.

jm proj branch feature            # create a branch
jm proj checkout feature          # switch to it
# ...edit, commit...
jm proj checkout main
jm proj merge feature             # fast-forward or a 3-way merge

If a merge conflicts, jm proj writes the usual <<<<<<< / ======= / >>>>>>> markers into the affected files and pauses. Resolve them, then commit — the result becomes a proper two-parent merge commit:

# edit the conflicted files to resolve them
jm proj commit -m "Merge feature"

Rebase

Replay your branch's commits on top of another, for a linear history. It pauses on conflict so you can resolve and continue — or bail out entirely:

jm proj checkout feature
jm proj rebase main               # replay feature onto main
jm proj rebase --continue         # after resolving a conflict
jm proj rebase --abort            # give up and restore the original branch

Undo, tag, and rescue work

jm proj tag v1.0                  # tag the current commit
jm proj revert <commit>           # a new commit that undoes another
jm proj reset --hard <commit>     # move HEAD, index and working tree
jm proj cherry-pick <commit>      # replay one commit onto HEAD

jm proj stash                     # shelve uncommitted work (untracked files too)
jm proj stash list
jm proj stash pop                 # bring it back

Working with a remote

Every project on JM Tech Power has a server-side object store. Clone one, push your commits, and pull others' work — pull is a fetch plus a line-level merge:

jm proj clone owner/my-tool       # clone a project's repository
jm proj push                      # push commits to the project
jm proj fetch                     # download objects/refs without merging
jm proj pull                      # fetch + merge the remote branch

Publishing a release

Version control is for your history; a release is a downloadable, browsable snapshot for the world. That lives under jm proj release. Scaffold a manifest, then publish:

jm proj release init --name "My Tool" --category Tools --os Linux --license MIT
# ...build...
jm proj release push --notes "First release" --highlight "Initial launch"

The first push creates the project and writes its id, owner and slug back into jm.toml; later pushes publish a new version. Browse any published project's source without cloning:

jm proj release ls  owner/my-tool          # list source files
jm proj release cat owner/my-tool README.md
jm proj release releases owner/my-tool     # every version
jm proj release diff owner/my-tool         # source diff between the latest two

Collaboration

Fork a project, open a pull request from your fork, and use stars and issues — GitHub-style, from the terminal:

jm proj fork owner/my-tool
jm proj pr-create owner/my-tool --from you/my-tool --title "Add dark mode"
jm proj pulls owner/my-tool
jm proj star  owner/my-tool
jm proj issues owner/my-tool
jm proj issue-create owner/my-tool --title "Crash on start" --body "Steps: ..."

A complete example

Start a tool, version it, publish it, then ship a fix on a branch:

mkdir my-tool && cd my-tool
jm proj init
echo "print('hello')" > main.py
jm proj add . && jm proj commit -m "First cut"

# publish a downloadable release
jm proj release init --name "My Tool" --category Tools --os Linux --license MIT
jm proj release push --notes "v0.1.0"

# fix a bug on a branch and merge it
jm proj branch fix-crash
jm proj checkout fix-crash
# ...edit main.py...
jm proj commit -a -m "Fix crash on empty input"
jm proj checkout main
jm proj merge fix-crash

# share it: push commits and publish the new release
jm proj push
jm proj release push --notes "v0.1.1" --highlight "Fix crash on empty input"

Cheat sheet

  • Track: init, add, rm, mv, commit, status, stash
  • History: log, show, diff, blame, tag
  • Branch: branch, checkout, merge, rebase, cherry-pick
  • Undo: reset, revert
  • Remote: clone, push, fetch, pull
  • Publish: release init, release push, release ls/cat/diff/releases
  • Collaborate: fork, pr-create, pulls, star, issues

Run jm proj <command> -h for the full options on any command, or jm readme for the complete manual.

Comments (0)

No comments yet. Be the first to comment!