NOTE

git 1.5.x has improved remote branch handling that makes some of the below outdated. These are documented in Git_Guide. This document handles pre-1.5 git versions. If you have issues following these instructions, please ask for help.

Intro

Most of the commands need to be run from the root of your cloned repository (e.g. the directory containing a .git subdirectory). Alternately you can set $GIT_DIR to that directory and run commands elsewhere.

For given commands you can type either eg git commmit or git-commit; the man page is available via man git-commit.

For more common everyday commands see the list in git help.

Setup

How do I get my copy of the repository?

Once you have your access setup:

$ git clone ssh://[<user@>]scm.sourcemage.org/smgl/grimoire.git
$ ls
grimoire
$ cd grimoire

Note: If you don't want to authenticate for every action, you can also use git:// instead of ssh:// for read/update operations. You will need ssh:// for any write operations. Do not use http://, even if it seems to work. It is not a supported mechanism for developers getting timely updates.

Any other initial setup I need?

Tell git who you are:

$ git repo-config user.name "FirstName LastName"
$ git repo-config user.email "user@example.com"

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

This will make pushes require fewer keystrokes:

$ echo 'Push: refs/heads/master:refs/heads/origin' >>.git/remotes/origin

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?

Assuming you are on the master branch:

$ git pull

How do I update a spell, assuming I have no other changes I don't want to commit?

$ git pull origin
$ $EDITOR path/to/spell/files
$ git add path/to/new/files
  Note: deletions will be noted automatically.
$ git commit -a
  Note: fill the commit message with the spell name and the version number it is updated to.
$ git push origin master

Note: This commits *all* local changes, if you want to keep some not committed, see the Intermediate Usage section.

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?

$ git checkout -f

I want to fix my last commit.

$ $EDITOR path/to/spell/files
$ git commit --amend <some/path>

This will include the new changes you made and recommit with the previous commit message.

What other info commands are there?

$ git status
$ git log [<some/path>]
$ git show [<some commit id>]
$ git diff

Intermediate Usage

I only want to commit certain files.

$ git commit path/to/some/files

Note:

  • git commit with no args may complain about needing to update the index to include some files in the commit; specifying explicit paths will avoid this.

  • 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.

How do I see all the available branches?

$ git branch
  devel
* master
  origin
  stable-0.3
  stable-rc-0.4

The * denotes the current working branch. "master" is the mainline/trunk, aka the "test" grimoire. "origin" is a special branch that represents the upstream "master" branch; the local "master" branch is specially created for your modifications. You shouldn't ever edit in the origin branch. However, the other "devel" and "stable*" branches are directly tied to their upstream counterparts by default.

I want to work on an upstream branch other than "master".

$ git checkout <local name of other branch>
$ git fetch; git pull . <upstream name of other branch>
$ $EDITOR some/files/etc.
$ git push ssh://... <local name of other branch>:<upstream name of other branch>

Note:

  • Make sure you type the pull . <branch> ; you can only leave the . out for the master/origin pull. See the Advanced Usage section for details.

  • You can make a shortcut for the push command in .git/remotes/origin, using the previous example of a Push: line.

  • If you expect to do a lot of edits in these branches, please read the Advanced Usage section for a word on best practices.

I want to get back to the main branch.

$ git checkout master

I want to create a local WIP branch.

$ git branch devel-something
$ git checkout devel-something
edit/add/commit/etc.

Or just:

$ git checkout -b devel-something
edit/add/commit/etc.

I want to push my WIP branch changes back to the mainline.

$ git checkout master
$ git pull . devel-something

I want to delete a local WIP branch.

$ git branch -D devel-something

I want to cherry-pick a change from one local branch to another local branch.

$ git checkout <first local branch>
$ git log path/to/changed/file
$ git checkout <second local branch>
$ git cherry-pick <sha1 refspec from the previous 'git log' output>

I want to cherry-pick something from one local branch to a remote branch.

$ git fetch ssh://... <remote branch>:<tmp local branch>
$ git checkout <tmp local branch>
$ git cherry-pick <sha1 refspec of commit from other local branch>
$ git push ssh://... <tmp local branch>:<remote branch>
$ git branch -D <tmp local branch>

I want to revert a commit.

$ git log path/to/file
$ git revert <sha1 refspec of the bad commit>

Note: revert and cherry-pick automatically do a commit with a message that preserves the original commit id. man git-cherry-pick for options to change this behaviour.

Advanced Usage

I want to publish my WIP branch on the central server.

$ git push ssh://[<user@>scm.sourcemage.org/smgl/grimoire.git devel-something:devel-something

Note:

  • You can add your new branch to .git/remotes/origin to assist with using it.

  • Other people that already have this repository cloned have to git fetch this new branch to get it.

  • For most developers, the remote branch you create has to have a name that matches devel.*, or you will get a permission denied error.
  • There is currently no way to remotely delete a branch.
  • Even if the branch is deleted remotely, the deletion won't be pushed to people that already had it.

I want to work in various remote branches often.

When you do your clone, git creates an "origin" branch which should be treated as a pristine copy of the upstream "master", and a local "master" branch that is set to update from "origin". This way you have your own local branch for work, with a fallback to the upstream. If you are going to work in devel, stable-rc, stable, etc. a lot, it's probably a good idea to mirror this setup for these branches:

$ git checkout devel
$ git branch local-devel

For bonus points, edit .git/remotes/origin and setup the Pull: lines for these branches to work the way origin and (local) master do.

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.

$ git push ssh://... <sha1 spec>:<remote branch dst>

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.

Git_Guide_Pre-1.5 (last edited 2008-09-22 23:34:50 by localhost)