When I started the Bitcoin client for the first time it spent several hours downloading (I think) all the blocks. What exactly was it downloading? Was it the full data for every block with every committed transaction ever?
Yes. Unless you are running some other software, in which case I have no idea how that software works.
On a related note, how does my client verify that a transaction is good (if it’s even possible for it do this)? I know there are a lot of pieces to the verification but the particular point I’m wondering about is how it confirms that a particular transaction input is in fact the output of an earlier transaction. It seems to do this my client would either need to have (1) the full contents of the input’s block; or (2) the full Merkle tree of the input’s block; or (3) the Merkle root of the input’s block + the Merkle branch of the input transaction. (1) seems unlikely since that’s a lot of data (I believe this is what a “full node” has). (3) doesn’t seem possible because AFAICT the protocol for a transaction doesn’t allow for including a Merkle branch. So I guess then it’s either (2) or something else entirely.
It sounds like you do know how transactions are verified. The inputs are looked up in an index kept for just that purpose.
Every node using the reference client is a "full node" with a full blockchain history. But, it turns out that you only need a subset of the blockchain for most things, including transaction verification. You can discard transactions after they are spent and just keep the unspent ones*. The set of unspent outputs is relative small, like a couple hundred MB, rather than several GB for the full block history.
Right now, the protocol doesn't allow requesting or sending partial blocks, but they are working on it. That will allow even lighter clients.
* Well, you need rollback history too.