Intro
Most of the commands need to be run from the root of your cloned repository (e.g. the directory containing a .git subdirectory).
For given commands you can type either eg cg commmit or cg-commit; the man page is available via man cg-commit.
For more common everyday commands see the list in cg help.
Setup
How do I get my copy of the repository?
Once you have your access setup:
$ cg clone git+ssh://[<user@>]scm.sourcemage.org/smgl/grimoire.git $ ls grimoire $ cd grimoire
Any other initial setup I need?
Tell cg who you are:
$ echo -e "[user]\n\tname = My Name\n\temail = mail@example.com" >> .git/config
If you have many git repositories under your current user, you can set this for all of them
$ echo -e "[user]\n\tname = My Name\n\temail = mail@example.com" >> ~/.gitconfig
Basics
For just dealing with the primary branch of the grimoire (test for the grimoire, aka "master" in git):
How do I keep my copy current?
$ cg update
How do I update a spell, assuming I have no other changes I don't want to commit?
$ cg update $ $EDITOR path/to/spell/files $ cg add path/to/new/files $ cg rm path/to/old/files $ cg commit
An important difference here is that the cg-commit command is relative to the current path, in the same manner as svk for instance. That means that if you edited files in maindir/dir1/ and maindir/dir2/, executing cg-commit in the maindir/ directory will commit all the files. But if you execute cg-commit in the maindir/dir1, it will only commit files in this directory. Files in maindir/dir2 will not be commited. Most cogito commands work in this way.
Note : please think to fill the commit message with the spell name and the version number it is updated to.
Then to publish your changes :
$ cg push
Note: This commits *all* local changes, if you want to keep some not committed, you can remove the files from the files list in the commit message like in perfore. Also, this command must be launched at the root of the repository.
Oh no, a conflict! How do I resolve it?
$ $EDITOR path/to/conflicting/file $ git update-index path/to/conflicting/file $ git commit -F .msg $ rm .msg
I screwed up, how do I reset my checkout?
$ cg reset
I want to fix my last commit.
$ cg commit -p <some/path>
This will include the commit in diff form which you can edit.
What other info commands are there?
$ cg status Note: check cg-status --help for more info $ cg log [<some/path>] Note: check cg-log --help for more info $ cg diff
All these three commands are also relative to the current path like the commit command.
I have multiple files no longer tracked by Cogito (status denoted by "?"), how do I remove them ?
$ cg-clean -D
Intermediate Usage
I only want to commit certain files.
$ cg commit path/to/some/files
Note:
you can remove files you don't want to commit from the commit message as well
Best practice is to always do a commit per atomic change so that a separate commit id is available for future cherry-picks, reverts, etc. In other words, if you have 5 spells to update, do a commit per spell directory and not one commit that includes all 5 updates.
***ALL BRANCH RELATED STUFF IS UNDER PROGRESS***
How do I see all the available remote branches?
$ cg-branch-ls origin git+ssh://[<user@>]scm.sourcemage.org/smgl/grimoire.git
This command will show you the available remote branches, so at the beginning you should only have "origin", which represents the upstream "test" grimoire. In cogito, you never work directly with remote branches, you have to create a local branch to play with it.
How do I see all the different heads?
$ cg-status -g Heads: >master 7c560f20a2249511d38fa820f0f8866dcc8c7b2e R origin 7c560f20a2249511d38fa820f0f8866dcc8c7b2e
The heads are kind of handles for various sequences of commit. A head contains simply a pointer to the last commit in the sequence, and if you commit 'onto' a head, the pointer will be advanced to the new commit. The current head denoted with ">" is the one you are working on. So usually with all the commands above, you make your changes and commit in the "master" head (local branch) and push them in the "origin" head, which is a remote one (denoted by a "R").
I want to work on an upstream branch other than "master".
As mentioned before, you can't work directly with remote heads in cogito. So you have here two solutions :
1) Create a local head for each remote head
We first add the remote branch in the repository :
$ cg-branch-add branchname "git+ssh://[<user@>]scm.sourcemage.org/smgl/grimoire.git#branchname"
Then we can fetch the branch :
$ cg fetch branchname Fetching pack (head and objects)... Unpacking 9432 objects 100% (9432/9432) done Fetching tags... New branch: fd8b8f4ccc457867140f6a38a2367c4c83153ce3
Note that the command gives you a commit number which will be use in the next command to create the local head. This number can still be obtained later with cg-status -g. Therefore we can now create the local head :
$ cg-switch -r fd8b8f4ccc457867140f6a38a2367c4c83153ce3 localname Creating new branch localname: fd8b8f4ccc457867140f6a38a2367c4c83153ce3 Switching to branch localname...
This command creates a new head since localname doesn't exist yet, based on the latest commit number of the "branchname" head. Your repository should look like that :
$ cg-status -g
Heads:
R branchname fd8b8f4ccc457867140f6a38a2367c4c83153ce3
localname fd8b8f4ccc457867140f6a38a2367c4c83153ce3
>master 7c560f20a2249511d38fa820f0f8866dcc8c7b2e
R origin 7c560f20a2249511d38fa820f0f8866dcc8c7b2e
You can now work as you used to, but please take care that push/fetch/merge/update commands take origin as a default argument. So remember to use the name of the remote head if you don't want to screw up things :
$ $EDITOR some/files/etc. $ cg commit $ cg push branchname
And so if you want to update your local head :
$ cg update branchname
2) Clone each head in a seperate repository
$ cd some-other-dir $ cg clone git+ssh://upstreampath#branchname mylocalclone-branch
That's all I can then use the same commands as above to work on it... It does need to have the email and commiter set properly again though.
I want to get back to the main branch.
$ cg switch master
This obviously only works if you use the first methods to work on other branches.
I want to create a local WIP branch.
$ cg-switch -n WIP $ cg-switch WIP edit/add/commit/etc.
I want to push my WIP branch changes back to the mainline.
$ cg-switch origin $ cg-pull . WIP
I want to delete a local WIP branch.
UNKNOWN
I want to inspect a specific commit (before cherry-pick for instance)
$ cg-diff -p -r <sha1 refspec of the commit>
The -p option tells cogito to make the diff between the parent of the specified commit and this commit.
I want to cherry-pick a change from one local branch to another local branch.
$ cg patch -C <sha1 refspec of the commit>
I want to cherry-pick something from one local branch to a remote branch.
UNKNOWN
I want to revert a commit.
$ cg log path/to/file $ cg-restore --help
Advanced Usage
I want to publish my WIP branch on the central server.
UNKNOWN
I don't get the various `git pull` syntaxes.
The full syntax is: git pull <src repository> <remote branch src>:<local branch dst>. That means "fetch <src repository>/<remote branch src> into <local branch dst>, and then merge <local branch dst> into whatever my working copy is". This syntax always works in any situation, but you can shortcut it in some situations:
<local branch dst> defaults to the current branch your working copy is on.
You can use . (current directory) as the <src repository> if you just want to pull between local branches; this works because you'll be in the directory that has the .git meta dir.
Related to the above, note that git pull ssh://... devel is technically the most direct way to update branch "devel", but requires more typing than git fetch; git pull . devel.
git pull <name of a remotes file> will do git fetch <all branches in that remotes file>; git pull . <first branch listed in the remotes file>:<current branch>. This is why git pull origin works by default for updating the master branch, but is a Bad Idea in any other situation.
Note also that if you don't want the final merge piece, use git fetch instead.
I only want to push my commits up to a certain point.
UNKNOWN
I'm tired of typing my SSH key passphrase.
You may want to use ssh-agent to avoid having to type in your SSH password while working on the repositories (assuming you cloned with developer access). First we load the ssh-agent :
$ eval `ssh-agent` Agent pid 10044
The above PID will be different for you. Now we load our key (assuming you only have one key or want to load them all):
$ ssh-add
If you have a specific key for the grimoire and want to only load that, use:
$ ssh-add ~/.ssh/grimoire_id_rsa
Assuming you named your grimoire SSH key ~/.ssh/grimoire_id_rsa.
You can also consider using a passphrase-less key, as long as the physical security of the private key file is reasonable (your development machine isn't share with other users, you have firewall protection in place, etc.).
I have multiple git repositories, do I have to specifiy the author and email in each?
git will try to use the /etc/passwd gecos field and user@host for your name and email, but if this isn't accurate you can set $GIT_AUTHOR_NAME and $GIT_AUTHOR_EMAIL. You can also set $GIT_COMMITTER_NAME and $GIT_COMMITTER_EMAIL, but git tries to get these from the $GIT_AUTHOR_* vars. AUTHOR is the person originally responsible for the commit; COMMITTER is the person committing the commit (ie, the person cherry-picking or reverting someone else's commit).
Why do my commit emails have extra "Merge branch 'master'" messages?
When you do a git pull, it fetches any changes to the upstream branches, merges them into your checkout, and does an auto-commit back to your local repo. This auto-commit produces this message, and it gets sent along when you push.
If you want to avoid this you can try using git fetch; git rebase origin instead of git pull origin. rebase works by replaying all the new commits instead of trying to merge them. If your working copy is (mostly) clean when you rebase, it will work as well as a merge and won't produce the extra commit/message. However, be aware that while a failed pull/merge will complete regardless and just leave you with conflicts to clean up, if a rebase runs into a conflict it will stop immediately and ask you to figure out what's going on. Therefore if your working tree isn't very clean you may not want to use rebase unless you're prepared for some extra work to clean it up.
