git tutorialhttp://www.fieldses.org/%7Ebfields/kernel/git.html

First we'll just import a project into git and fool around with it a bit. Then we'll play with the linux kernel repository. But before we do either of those we need to get git and install it.

Installing git

Distributions don't necessarily have up-to-date versions of git yet, so you need to install it yourself. Thankfully that's fairly easy.

First, download the latest snapshot from

http://www.codemonkey.org.uk/projects/git-snapshots/git/Unpack and cd into the git directory, and domake PYTHON_PATH=/usr/bin/python2.4 prefix=/usr/local all doc
sudo make prefix=/usr/local install install-doc

(I need PYTHON_PATH because git wants python 2.4 but /usr/bin/python on my machine is 2.3. You may not need it. The "prefix" arguments are also optional if you're happy with the default of "$HOME/bin".)

If the compile fails, check to see whether it's finding all the libraries and headers it needs. The mostly likely culprits are libcurl and asciidoc, so you may need to install those before getting a successful compile.

To be sure of having the most absolutely brand new version of git, you can then run

git clone git://git.kernel.org/pub/scm/git/git.git git
cd gitand build and install as before. At any time you can update just usinggit pull

and get a quick view of the latest changes to git using

git whatchangedImporting a new project

First, note that you can get documentation for any git command using

man git-commandname

Assume you already have a tarball myproject.tar.gz with your initial work.

tar -xzvf myproject.tar.gz
cd myproject
git init-dbYou've initialized the working directory; now tell git that you want it to track every file (recursively) under the current directory, withgit add .Finally,git commit -a

creates the initial commit that imports all of these new files. It will prompt you for a commit message, then record the current state of all the files to the repository.

Try modifying some files, then run

git diff

To see your modifications so far. When you're happy with the change,

git commit -a

will commit it.

To add a new file, first create the file, then

git add path/to/new/file

then commit as usual. No special command is required when removing a file; just remove it, then commit.

At any point you can view the history of your changes using

git whatchanged

or, to see the history, together with complete diffs at each step,

git whatchanged -p

A single git repository can maintain multiple branches of development. To create a new branch named "experimental"

git branch experimental

If you now run

git branch

you'll get a list of all existing branches.

experimental
* master

The "experimental" branch is the one you just created, and the "master" branch is a default branch that was created for you automatically. The asterisk marks the branch you are currently on; type

git checkout experimental

to switch to the experimental branch. Now edit a file, commit the change, and switch back to the master branch:

# edit file
git commit -a
git checkout master

Check that the change you made is no longer visible, since it was made on the experimental branch and you're back on the master branch.

You can make a different change on the master branch:

# edit file
git commit -a

at this point the two branches have diverged, with different changes made in each. To merge the changes made in the two branches, run

git pull . experimental

If the changes don't conflict, you're done. If there are conflicts, markers will be left in the problematic files showing the conflict;

git diffwill show this. Once you've edited the files to resolve the conflicts,git commit -a

will commit the result of the merge. Finally,

gitk

will show a nice graphical representation of the resulting history.

Note that, unlike cvs, git doesn't use a single central repository; instead the repository is being kept inside your current working directory (in the ".git" directory). One way to share changes with someone else is by asking them to do a "git pull". In the example git pull which we used to do the merge above,

git pull . experimental

we were asking git to "pull" changes from the branch named "experimental" in the current directory (specified by the period). Instead of the current directory, we could have specified a different directory. So

git pull /path/to/different/repository experimental

would pull changes from the branch experimental in the git repository at the given path. Or

git pull html://foo.com/pub/repository experimental

would pull changes from a git repo on a website. If the second argument is left out, the default is to pull from the branch named "master". It is also possible to pull via ssh or via a git-specific protocol; see the git-pull man page for details.

Git can also be used in a mode more like CVS, with a central repository that various users push changes to; see the git-push man page and Documentation/cvs-migration.txt in the git source tree.

Examining the Linux kernel repository

You can fetch the linux kernel repository with

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6
cd linux-2.6

as usual, you can see recent changes with any of

git whatchanged
git whatchanged -p
gitk

You can see the list of available "tags" (which mark release versions) with

ls .git/refs/tags/

and reset the current working tree to a known version with, for example,

git reset --hard v2.6.12

To update your already-existing repository to the latest upstream, just run

git pull

The URL you used on the original clone is stored in .git/remotes/origin, so there's no need to tell git that URL again.

Some good commands to explore next:

  • git diff: We saw it this used above to compare the current state of the working tree with the last checked out version. But git diff can be used to compare arbitrary versions from the repository, and can be restricted to consider only certain files; see the man page for details.
  • git bisect: When there is a regression in your project, one way to track down the bug is by searching through the history to find the exact commit that's to blame. Git bisect can help you perform a binary search for that commit. It is smart enough to perform a close-to-optimal search even in the case of complex non-linear history with lots of merged branches.

You may also want to look through the Documentation subdirectory of the git source tree for further information.