Go forward in time to December 2008.
Git makes it easy to to collaborate with other people. To do this, you need to understand what Git means by pushing/pulling and setting up remote repositories.
How do commits happen?
Git is a machine that deals with practically only two things: hooking commits together in a directed graph, and moving tags around.
Let's start with a simple repository that only has three commits:
Note that each commit points to its parent commit. The commit at the top is the latest one. The commit at the bottom is the first one, and it points to null, as it has no parent.
Now let's look at a repository with two branches. Each branch has a name; we'll call them "alpha" and "beta".
Git also calls these "refs" or "heads", since they are, well, references to particular commits, or the head commits of a branch. Each ref is like a tag attached to a commit. When you "make a new commit to a branch", the corresponding ref moves to point to the new commit. Since refs are tags that move, they have cute little wheels in the drawings here.
Now let's make a commit to the "beta" branch:
git commit -m  "New commit for beta"
But wait! How does Git know to which branch you want to commit?
Git has a special ref called HEAD. It doesn't point to a particular commit, but instead it points to another ref. The HEAD is "your current branch", or the branch to which Git will commit. So, let's show the HEAD in the repository above: here, "beta" is the current branch, so HEAD points to it.
Now that we know how Git knows about the current branch, we'll actually make a new commit. It is shown in dark blue here:
See how "beta" now points to the new commit, but HEAD still points to "beta"? That's all that happens during a commit.
Where are refs stored?
Those names for "alpha" and "beta" are stored in a special place to store refs. Look at the .git/refs/heads subdirectory of a Git repository, and you will see some of the branch names that you have defined. If you look inside one of those files, you'll simply see the SHA-1 hash of the commit to which the ref points.
So, the real names of "alpha" and "beta" are refs/heads/alpha and refs/heads/beta, respectively. Git lets you refer to them by their short names for convenience.
You may also see a .git/refs/tags directory. That is where tags are stored — a tag is like one of the refs we saw, but it doesn't have cute little wheels. A tag does not move when you commit. Here is a tag for version 1.0 of our project:
You may also see a .git/refs/remotes directory. What's that about?
A remote is a repository that you want to access repeatedly, so you tell Git about it. It can be where you cloned your repository from, or another repository from which you want to pull or push. In short, it is a repository that contains more or less the same data as yours, but that is not your repository.
Imagine that you do this:
git clone git://example.com/git/killer-app
Your just-cloned repository now looks like this:
Let's dissect the refs one by one:
HEAD - Pointer to your current branch, as usual, in this case master. New commits will go to your master branch.
master - Shorthand for refs/heads/master; this is the only "local branch" in your repository. By convention, when you first clone a remote repository, the current branch of the remote repository becomes your master branch, just so that you have somewhere to work on.
remotes/origin/master - This is a branch in the remote repository. By convention, the repository that you cloned from is called origin. In this example, the origin's master branch happened to be its HEAD (i.e. its current branch), so that branch is what got set up as our master. By the way, the full name of this branch would be refs/remotes/origin/master — that is where the .git/refs/remotes/... stuff comes from.
remotes/origin/zoinks - This is just a random branch in the remote repository.
Your friend Larry tells you that he has something interesting going on in his repository. You already have a clone of pretty much the same thing (maybe you both cloned from the same origin). So, you add a remote for Larry's repository:
git remote add larry git://larry.com/killer-app
Git now knows about Larry's repository. Let's fetch his data:
git fetch larry
Now our repository looks like this:
Git grabbed whatever was in Larry's repository, and hooked it to our own repository in the appropriate places. In this case, Larry had his master branch with one commit that we didn't have (the purple one), and his branch got named as remotes/larry/master in our copy. If Larry had other branches, they would be hooked in the appropriate spots in our graph of commits, and they would have names like remotes/larry/branchname.
In the next part, we'll see how to merge Larry's changes into ours, and how to monitor his work to pull from it regularly.
You know when you are browsing some source code and you come up to a function call or a variable declaration, and you need to look at the source for that function or that variable's type? And then you do that, but then you need to check another function, or header file, or something else? And then... etcetera, and finally you want to unroll the stack in your head to go back to the original place, or somewhere in the middle. But where were you in the beginning?
What you want is a stack of positions in the files you are browsing, and a way to push/pop that stack. Emacs provides an easy way to do that.
If you are somewhere and you need to visit another place, hit C-SPC to set the mark as usual. Now visit that other place — it can be another file, another place in your current file, etc. If you need to visit yet another place, or shave another yak, hit C-SPC again before visiting it.
When you want to go back in the stack, hit C-x C-SPC. This runs the pop-global-mark command, which will take you back to the last place you marked. The stack is actually a ring, so you never hit its "bottom"; you just go back to the latest marked place.
If you need a "hot bookmark" rather than a place in the stack, use a quick register. Hit C-x r SPC and then an alphanumeric key to save the current point. Go somewhere else, and finally hit C-x r j and the same alphanumeric key to restore the point where you saved it. This way you can "drop an anchor" anywhere, and assign it to a letter or number.
Luciana does something new and cute every day, but yesterday she cruised across the room, for the first time ever, just so she could grab the salad bowl that mommy and daddy were using. And that is just magical.
And then she cruised back, tipped over a big box of wooden blocks, worked the lid open, and took out the blocks one by one.
Our daughter is teaching herself world domination, one step at a time.
I am learning woodworking, and these how-to videos by master carpenters are a really nice reference. "We cut these dovetail pins a millimeter too long so that we can later plane them flush with the tail and get a clean finish". I haven't seen a book that tells you that kind of stuff.
I am in the process of seeing why gtk-vnc (the VNC client implementation used by Vinagre, virt-viewer, et al) is much slower by default than TightVNC. It seems to be something around the preferred ordering of encodings which VNC supports, plus TightVNC's funny extensions. So, I have been modifying the ever-amazing Wireshark to support decoding TightVNC's extensions to the basic VNC protocol. This will make it easy to compare what TightVNC and gtk-vnc are doing.
I just ran into a bug in Nautilus caused by a FIXME from December 2000, from the Eazel days. The bug only gets triggered by my patch to allow desktop icons defined by the sysadmin; the original code doesn't seem to be subject to this. Dr. House, move over for here I come.
I am starting to think that Nautilus, like any big system with a lot of history, is not a beautiful piece of clockwork. It is not neurotic and exact; it is more like a living organism where data flows in semi-predictable directions and all your changes to the code have to be prepared for anything. You cannot know exactly what data you will get, or all the code paths that may lead to your code getting called.
This is not a bad thing by itself. You cannot have a large, mature system that functions with 100% predictably, like clockwork. You have to allow for things to happen even if you did not expect them.
Go backward in time to October 2008.Federico Mena-Quintero <email@example.com> Tue 2008/Nov/11 10:31:32 CST