Mike, Git seems unintuitive because you don't have a good grasp of what it does behind the scenes. Imagine trying to get to grips with a Unix shell, if you had no concept of files or directories. In such a scenario, even a simple command like "cat" would seem incomprehensible.

If you'll indulge me, I'd like to propose a thought experiment.

* * Designing a patch database * *

Consider you're responsible for administering a busy open source project. You get dozens of patches a day from developers and you find it increasingly difficult to keep track of them. How might you go about managing this influx of patch files?

The first thing you might consider is how do you know what each patch is supposed to do? How do you know who to contact about the patch? Or when the patch was sent to you?

The solution to this is not too tricky; you just add some metadata to the patch detailing the author, the date, a description of the patch and so forth.

The next problem you face is that some patches rely on other patches. For instance, Bob might publicly post a patch for a great new scheduler, but then Carol might post a patch correcting some bugs in Bob's code. Carol's patch cannot be applied without first applying Bob's patch.

So you allow each patch to have parents. The parent of Carol's patch would be Bob's patch.

You've solved two major problems, but now you face one final one. If you want to talk to other people about these patches, you need a common naming scheme. It's going to be problematic if you label a patch as ABC on your system, but a colleague labels a patch as XYZ. So you either need a central naming database, or some algorithm that can guarantee everyone gives the same label to the same patch.

Fortunately, we have such algorithms; they're called one-way hashes. You take the contents of the patch, its metadata and parents, serialize all of that and SHA1 the result.

Three perfectly logical solutions, and ones you may even have come up with yourself under similar circumstances.

* * Merging patches * *

Under this system, how would a merge be performed? Let's say you have two patches, A and B, and you want to combine them somehow. One way is to just apply each in turn to your source, fix any differences that can't be automatically resolved (conflicts), and then produce a new patch C from the combined diff.

That works, but now you have to store A, B and C in your patch database, and you don't retain any history. But wait! Your patches can have parents, so what if you created a 'merge' patch, M, with parents A and B?

A B
\ /
M

This is externally equivalent to what you did to produce C: patches A and B are applied to the source code, and then you apply M to resolve the differences. M will contain both the differences that can be resolved automatically, and any conflicts we have to resolve manually.

Having solved your problem, you write the code to your patch database and present the resulting program to your colleague.

* * A user tries to merge * *

"How do I merge?" he asks.

"I've written a tool to help you do that," you say, "Just specify the two patches you want to combine, and the tool will merge them together."

"Um, it says I have a merge conflict."

"Well, fix the problem, then tell the system to add your file to the 'merge patch' it's making."

Your colleague dutifully hacks away, and solves the conflict. "So I've fixed the file," he says, "But when I tell it to 'commit file' it fails."

"Remember, this is a patch database," you reply, "We're not dealing with files, we're dealing with patches. You have to add your file changes to your patch, and then commit the patch. You can't commit an individual file."

"What? That's not very intuitive," he grumbles, "Hey! I've added the file to the patch, but it tells me the merge isn't complete!"

"You need to add all of the files that have differences that were automatically resolved as well."

"Why?!"

"Because," you explain patiently, "You might not like the way those files have been changed. It needs your approval that the way it's resolved the differences is correct."

"Why to I have to re-commit everything my buddy has made?" he complains, "Seriously, I want to just commit one file. What the hell is up with your system?"