+
+ Creating a new branch
+ ---------------------
+
+Branches in git are really nothing more than pointers into the git
+object space from within the ".git/refs/" subdirectory, and as we
+already discussed, the HEAD branch is nothing but a symlink to one of
+these object pointers.
+
+You can at any time create a new branch by just picking an arbitrary
+point in the project history, and just writing the SHA1 name of that
+object into a file under .git/refs/heads/. You can use any filename you
+want (and indeed, subdirectories), but the convention is that the
+"normal" branch is called "master". That's just a convention, though,
+and nothing enforces it.
+
+To show that as an example, let's go back to the git-tutorial archive we
+used earlier, and create a branch in it. You do that by simply just
+saying that you want to check out a new branch:
+
+ git checkout -b mybranch
+
+will create a new branch based at the current HEAD position, and switch
+to it.
+
+[ Side note: if you make the decision to start your new branch at some
+ other point in the history than the current HEAD, you can do so by
+ just telling "git checkout" what the base of the checkout would be.
+ In other words, if you have an earlier tag or branch, you'd just do
+
+ git checkout -b mybranch earlier-branch
+
+ and it would create the new branch "mybranch" at the earlier point,
+ and check out the state at that time. ]
+
+You can always just jump back to your original "master" branch by doing
+
+ git checkout master
+
+(or any other branch-name, for that matter) and if you forget which
+branch you happen to be on, a simple
+
+ ls -l .git/HEAD
+
+will tell you where it's pointing.
+
+NOTE! Sometimes you may wish to create a new branch _without_ actually
+checking it out and switching to it. If so, just use the command
+
+ git branch <branchname> [startingpoint]
+
+which will simply _create_ the branch, but will not do anything further.
+You can then later - once you decide that you want to actually develop
+on that branch - switch to that branch with a regular "git checkout"
+with the branchname as the argument.
+
+
+ Merging two branches
+ --------------------
+
+One of the ideas of having a branch is that you do some (possibly
+experimental) work in it, and eventually merge it back to the main
+branch. So assuming you created the above "mybranch" that started out
+being the same as the original "master" branch, let's make sure we're in
+that branch, and do some work there.
+
+ git checkout mybranch
+ echo "Work, work, work" >>hello
+ git commit hello
+
+Here, we just added another line to "hello", and we used a shorthand for
+both going a "git-update-cache hello" and "git commit" by just giving the
+filename directly to "git commit".
+
+Now, to make it a bit more interesting, let's assume that somebody else
+does some work in the original branch, and simulate that by going back
+to the master branch, and editing the same file differently there:
+
+ git checkout master
+
+Here, take a moment to look at the contents of "hello", and notice how they
+don't contain the work we just did in "mybranch" - because that work
+hasn't happened in the "master" branch at all. Then do
+
+ echo "Play, play, play" >>hello
+ echo "Lots of fun" >>example
+ git commit hello example
+
+since the master branch is obviously in a much better mood.
+
+Now, you've got two branches, and you decide that you want to merge the
+work done. Before we do that, let's introduce a cool graphical tool that
+helps you view what's going on:
+
+ gitk --all
+
+will show you graphically both of your branches (that's what the "--all"
+means: normally it will just show you your current HEAD) and their
+histories. You can also see exactly how they came to be from a common
+source.
+
+Anyway, let's exit gitk (^Q or the File menu), and decide that we want
+to merge the work we did on the "mybranch" branch into the "master"
+branch (which is currently our HEAD too). To do that, there's a nice
+script called "git resolve", which wants to know which branches you want
+to resolve and what the merge is all about:
+
+ git resolve HEAD mybranch "Merge work in mybranch"
+
+where the third argument is going to be used as the commit message if
+the merge can be resolved automatically.
+
+Now, in this case we've intentionally created a situation where the
+merge will need to be fixed up by hand, though, so git will do as much
+of it as it can automatically (which in this case is just merge the "b"
+file, which had no differences in the "mybranch" branch), and say:
+
+ Simple merge failed, trying Automatic merge
+ Auto-merging hello.
+ merge: warning: conflicts during merge
+ ERROR: Merge conflict in hello.
+ fatal: merge program failed
+ Automatic merge failed, fix up by hand
+
+which is way too verbose, but it basically tells you that it failed the
+really trivial merge ("Simple merge") and did an "Automatic merge"
+instead, but that too failed due to conflicts in "hello".
+
+Not to worry. It left the (trivial) conflict in "hello" in the same form you
+should already be well used to if you've ever used CVS, so let's just
+open "hello" in our editor (whatever that may be), and fix it up somehow.
+I'd suggest just making it so that "hello" contains all four lines:
+
+ Hello World
+ It's a new day for git
+ Play, play, play
+ Work, work, work
+
+and once you're happy with your manual merge, just do a
+
+ git commit hello
+
+which will very loudly warn you that you're now committing a merge
+(which is correct, so never mind), and you can write a small merge
+message about your adventures in git-merge-land.
+
+After you're done, start up "gitk --all" to see graphically what the
+history looks like. Notice that "mybranch" still exists, and you can
+switch to it, and continue to work with it if you want to. The
+"mybranch" branch will not contain the merge, but next time you merge it
+from the "master" branch, git will know how you merged it, so you'll not
+have to do _that_ merge again.
+
+
+ Merging external work
+ ---------------------
+
+It's usually much more common that you merge with somebody else than
+merging with your own branches, so it's worth pointing out that git
+makes that very easy too, and in fact, it's not that different from
+doing a "git resolve". In fact, a remote merge ends up being nothing
+more than "fetch the work from a remote repository into a temporary tag"
+followed by a "git resolve".
+
+It's such a common thing to do that it's called "git pull", and you can
+simply do
+
+ git pull <remote-repository>
+
+and optionally give a branch-name for the remote end as a second
+argument.
+
+The "remote" repository can even be on the same machine. One of
+the following notations can be used to name the repository to
+pull from:
+
+ Rsync URL
+ rsync://remote.machine/path/to/repo.git/
+
+ HTTP(s) URL
+ http://remote.machine/path/to/repo.git/
+
+ GIT URL
+ git://remote.machine/path/to/repo.git/
+
+ SSH URL
+ remote.machine:/path/to/repo.git/
+
+ Local directory
+ /path/to/repo.git/
+
+[ Digression: you could do without using any branches at all, by
+ keeping as many local repositories as you would like to have
+ branches, and merging between them with "git pull", just like
+ you merge between branches. The advantage of this approach is
+ that it lets you keep set of files for each "branch" checked
+ out and you may find it easier to switch back and forth if you
+ juggle multiple lines of development simultaneously. Of
+ course, you will pay the price of more disk usage to hold
+ multiple working trees, but disk space is cheap these days. ]
+
+It is likely that you will be pulling from the same remote
+repository from time to time. As a short hand, you can store
+the remote repository URL in a file under .git/branches/
+directory, like this:
+
+ mkdir -p .git/branches
+ echo rsync://kernel.org/pub/scm/git/git.git/ \
+ >.git/branches/linus
+
+and use the filename to "git pull" instead of the full URL.
+The contents of a file under .git/branches can even be a prefix
+of a full URL, like this:
+
+ echo rsync://kernel.org/pub/.../jgarzik/
+ >.git/branches/jgarzik
+
+Examples.
+
+ (1) git pull linus
+ (2) git pull linus tag v0.99.1
+ (3) git pull jgarzik/netdev-2.6.git/ e100
+
+the above are equivalent to:
+
+ (1) git pull rsync://kernel.org/pub/scm/git/git.git/ HEAD
+ (2) git pull rsync://kernel.org/pub/scm/git/git.git/ tag v0.99.1
+ (3) git pull rsync://kernel.org/pub/.../jgarzik/netdev-2.6.git e100
+
+
+ Publishing your work
+ --------------------
+
+So we can use somebody else's work from a remote repository; but
+how can _you_ prepare a repository to let other people pull from
+it?
+
+Your do your real work in your working directory that has your
+primary repository hanging under it as its ".git" subdirectory.
+You _could_ make that repository accessible remotely and ask
+people to pull from it, but in practice that is not the way
+things are usually done. A recommended way is to have a public
+repository, make it reachable by other people, and when the
+changes you made in your primary working directory are in good
+shape, update the public repository from it. This is often
+called "pushing".
+
+[ Side note: this public repository could further be mirrored,
+ and that is how kernel.org git repositories are done. ]
+
+Publishing the changes from your local (private) repository to
+your remote (public) repository requires a write privilege on
+the remote machine. You need to have an SSH account there to
+run a single command, "git-receive-pack".
+
+First, you need to create an empty repository on the remote
+machine that will house your public repository. This empty
+repository will be populated and be kept up-to-date by pushing
+into it later. Obviously, this repository creation needs to be
+done only once.
+
+[ Digression: "git push" uses a pair of programs,
+ "git-send-pack" on your local machine, and "git-receive-pack"
+ on the remote machine. The communication between the two over
+ the network internally uses an SSH connection. ]
+
+Your private repository's GIT directory is usually .git, but
+your public repository is often named after the project name,
+i.e. "<project>.git". Let's create such a public repository for
+project "my-git". After logging into the remote machine, create
+an empty directory:
+
+ mkdir my-git.git
+
+Then, make that directory into a GIT repository by running
+git-init-db, but this time, since it's name is not the usual
+".git", we do things slightly differently:
+
+ GIT_DIR=my-git.git git-init-db
+
+Make sure this directory is available for others you want your
+changes to be pulled by via the transport of your choice. Also
+you need to make sure that you have the "git-receive-pack"
+program on the $PATH.
+
+[ Side note: many installations of sshd do not invoke your shell
+ as the login shell when you directly run programs; what this
+ means is that if your login shell is bash, only .bashrc is
+ read and not .bash_profile. As a workaround, make sure
+ .bashrc sets up $PATH so that you can run 'git-receive-pack'
+ program. ]
+
+Your "public repository" is now ready to accept your changes.
+Come back to the machine you have your private repository. From
+there, run this command:
+
+ git push <public-host>:/path/to/my-git.git master
+
+This synchronizes your public repository to match the named
+branch head (i.e. "master" in this case) and objects reachable
+from them in your current repository.
+
+As a real example, this is how I update my public git
+repository. Kernel.org mirror network takes care of the
+propagation to other publicly visible machines:
+
+ git push master.kernel.org:/pub/scm/git/git.git/
+
+
+[ Digression: your GIT "public" repository people can pull from
+ is different from a public CVS repository that lets read-write
+ access to multiple developers. It is a copy of _your_ primary
+ repository published for others to use, and you should not
+ push into it from more than one repository (this means, not
+ just disallowing other developers to push into it, but also
+ you should push into it from a single repository of yours).
+ Sharing the result of work done by multiple people are always
+ done by pulling (i.e. fetching and merging) from public
+ repositories of those people. Typically this is done by the
+ "project lead" person, and the resulting repository is
+ published as the public repository of the "project lead" for
+ everybody to base further changes on. ]
+
+
+ Packing your repository
+ -----------------------
+
+Earlier, we saw that one file under .git/objects/??/ directory
+is stored for each git object you create. This representation
+is convenient and efficient to create atomically and safely, but
+not so to transport over the network. Since git objects are
+immutable once they are created, there is a way to optimize the
+storage by "packing them together". The command
+
+ git repack
+
+will do it for you. If you followed the tutorial examples, you
+would have accumulated about 17 objects in .git/objects/??/
+directories by now. "git repack" tells you how many objects it
+packed, and stores the packed file in .git/objects/pack
+directory.
+
+[ Side Note: you will see two files, pack-*.pack and pack-*.idx,
+ in .git/objects/pack directory. They are closely related to
+ each other, and if you ever copy them by hand to a different
+ repository for whatever reason, you should make sure you copy
+ them together. The former holds all the data from the objects
+ in the pack, and the latter holds the index for random
+ access. ]
+
+If you are paranoid, running "git-verify-pack" command would
+detect if you have a corrupt pack, but do not worry too much.
+Our programs are always perfect ;-).
+
+Once you have packed objects, you do not need to leave the
+unpacked objects that are contained in the pack file anymore.
+
+ git prune-packed
+
+would remove them for you.
+
+You can try running "find .git/objects -type f" before and after
+you run "git prune-packed" if you are curious.
+
+[ Side Note: "git pull" is slightly cumbersome for HTTP transport,
+ as a packed repository may contain relatively few objects in a
+ relatively large pack. If you expect many HTTP pulls from your
+ public repository you might want to repack & prune often, or
+ never. ]
+
+If you run "git repack" again at this point, it will say
+"Nothing to pack". Once you continue your development and
+accumulate the changes, running "git repack" again will create a
+new pack, that contains objects created since you packed your
+archive the last time. We recommend that you pack your project
+soon after the initial import (unless you are starting your
+project from scratch), and then run "git repack" every once in a
+while, depending on how active your project is.
+
+When a repository is synchronized via "git push" and "git pull",
+objects packed in the source repository are usually stored
+unpacked in the destination, unless rsync transport is used.
+
+
+ Working with Others
+ -------------------
+
+Although git is a truly distributed system, it is often
+convenient to organize your project with an informal hierarchy
+of developers. Linux kernel development is run this way. There
+is a nice illustration (page 17, "Merges to Mainline") in Randy
+Dunlap's presentation (http://tinyurl.com/a2jdg).
+
+It should be stressed that this hierarchy is purely "informal".
+There is nothing fundamental in git that enforces the "chain of
+patch flow" this hierarchy implies. You do not have to pull
+from only one remote repository.
+
+
+A recommended workflow for a "project lead" goes like this:
+
+ (1) Prepare your primary repository on your local machine. Your
+ work is done there.
+
+ (2) Prepare a public repository accessible to others.
+
+ (3) Push into the public repository from your primary
+ repository.
+
+ (4) "git repack" the public repository. This establishes a big
+ pack that contains the initial set of objects as the
+ baseline, and possibly "git prune-packed" if the transport
+ used for pulling from your repository supports packed
+ repositories.
+
+ (5) Keep working in your primary repository. Your changes
+ include modifications of your own, patches you receive via
+ e-mails, and merges resulting from pulling the "public"
+ repositories of your "subsystem maintainers".
+
+ You can repack this private repository whenever you feel
+ like.
+
+ (6) Push your changes to the public repository, and announce it
+ to the public.
+
+ (7) Every once in a while, "git repack" the public repository.
+ Go back to step (5) and continue working.
+
+
+A recommended work cycle for a "subsystem maintainer" who works
+on that project and has an own "public repository" goes like this:
+
+ (1) Prepare your work repository, by "git clone" the public
+ repository of the "project lead". The URL used for the
+ initial cloning is stored in .git/branches/origin.
+
+ (2) Prepare a public repository accessible to others.
+
+ (3) Copy over the packed files from "project lead" public
+ repository to your public repository by hand; preferrably
+ use rsync for that task.
+
+ (4) Push into the public repository from your primary
+ repository. Run "git repack", and possibly "git
+ prune-packed" if the transport used for pulling from your
+ repository supports packed repositories.
+
+ (5) Keep working in your primary repository. Your changes
+ include modifications of your own, patches you receive via
+ e-mails, and merges resulting from pulling the "public"
+ repositories of your "project lead" and possibly your
+ "sub-subsystem maintainers".
+
+ You can repack this private repository whenever you feel
+ like.
+
+ (6) Push your changes to your public repository, and ask your
+ "project lead" and possibly your "sub-subsystem
+ maintainers" to pull from it.
+
+ (7) Every once in a while, "git repack" the public repository.
+ Go back to step (5) and continue working.
+
+
+A recommended work cycle for an "individual developer" who does
+not have a "public" repository is somewhat different. It goes
+like this:
+
+ (1) Prepare your work repository, by "git clone" the public
+ repository of the "project lead" (or a "subsystem
+ maintainer", if you work on a subsystem). The URL used for
+ the initial cloning is stored in .git/branches/origin.
+
+ (2) Do your work there. Make commits.
+
+ (3) Run "git fetch origin" from the public repository of your
+ upstream every once in a while. This does only the first
+ half of "git pull" but does not merge. The head of the
+ public repository is stored in .git/refs/heads/origin.
+
+ (4) Use "git cherry origin" to see which ones of your patches
+ were accepted, and/or use "git rebase origin" to port your
+ unmerged changes forward to the updated upstream.
+
+ (5) Use "git format-patch origin" to prepare patches for e-mail
+ submission to your upstream and send it out. Go back to
+ step (2) and continue.
+
+
+[ to be continued.. cvsimports ]