News for hackers. Stuff that matters.
Re:Key Git Concepts Explained the Hard Way by stouset on Wednesday March 14, 2018 @04:54PM (#16588208)
I disagree that this is the case. I see it more as git is a DAG, and git's toolchain is simply a set of tools for manipulating the DAG.

It's not so much that git is a leaky abstraction as it is that git isn't an abstraction. If you don't know what a DAG is or how commits, files (e.g., blobs), trees, etc. are mapped into the DAG, of course you're going to have a hard time!

Re:Key Git Concepts Explained the Hard Way by aero142 on Wednesday March 14, 2018 @07:26PM (#16589286)
I could be able to write the git internals code from memory and it wouldn't help me know what `git checkout` was going to do.
Re:Key Git Concepts Explained the Hard Way by stouset on Wednesday March 14, 2018 @07:47PM (#16589405)
That's almost patently false, since `git checkout` is pretty much just a tool that takes a commit (or a name that points to a commit, like a branch or tag name) and updates the working tree, index, and the HEAD pointer to match the contents of the commit, with some extra safeguards to make sure uncommitted data isn't lost.

Three examples (that cover 95%+ of use-cases):

    $ git checkout some-branch
> Updates the index and working tree to reflect the contents of `some-branch`, and updates the HEAD pointer to indicate we're on the `some-branch` branch.

    $ git checkout -b some-branch
> Updates the index and working tree to reflect the contents of `some-branch`, with the "convenience" of creating it first through wrapping `git branch`. This is identical to calling `git branch some-branch; git checkout somebranch`.

    $ git checkout <optional-commit> -- path/to/a/file
> Updates the index and working tree to reflect the contents of the named file on the current or named branch/commit/tag/whatever.

TL;DR, `git checkout` has a very clear and well-defined responsibility: update the filesystem and index to reflect the contents of some commit. Various flags and options cause it to perform reasonable variations of this core responsibility (create a branch that doesn't exist first, or update individual files rather than the working tree as a whole). If the commit-name provide is a branch (and you're not checkout out individual files), it also updates the HEAD pointer to point to the named branch, so git "knows what branch you're on".

I would be absolutely astonished if you could write the git internals (or even just knew how they worked) and the idea of a tool to make the filesystem look like the internal contents of the repo wasn't immediately apparent. You might not have realized that that's all that `git checkout` does, but once you understand that, it's extremely straightforward.

Re:Key Git Concepts Explained the Hard Way by lozenge on Thursday March 15, 2018 @04:07AM (#16591122)
So it always updates the HEAD pointer, except when it doesn't, and you give it the name of an existing branch that represents the commit to change your working tree into, except when you specify -bf to use the HEAD commit, and except when you specify -b and a branch name that doesn't exist. You can also specify start_point to use instead of HEAD.

So, the checked out commit is the second ref specified, or HEAD, unless the flags are such that you can only specify one ref.

Git checkout also "merges" uncommitted changes with your new HEAD, which you didn't mention and makes me wonder why the command isn't called "git merge".

Re:Key Git Concepts Explained the Hard Way by markrages on Wednesday March 14, 2018 @11:26PM (#16590221)
Your comment would be at home on https://git-man-page-generator.lokaltog.net/
Re:Key Git Concepts Explained the Hard Way by aero142 on Thursday March 15, 2018 @12:53PM (#16594463)
I can forgive the '-b' creating a branch as a convenience. Having checkout perform safe operations by modifying HEAD when you pass a branch but destructive operations on the working tree when you pass a pathspec is too much. I appreciate your attempt to build a mental model for checkout, but I just don't find modifying HEAD and destructively overwriting working changes to be related operations.