Hacker News new | past | comments | ask | show | jobs | submit login
How HEAD works in Git (jvns.ca)
59 points by guiambros 9 months ago | hide | past | favorite | 18 comments



> I think HEAD would be more intuitive if git’s terminology around HEAD were a little more internally consistent.

HEAD is whatever commit is currently checked out, full stop.

When resolving conflicts during a rebase that HEAD will be the commit that the one being cherry-picked is being picked onto. To understand this it's useful to just know that rebase is just a script of cherry-picks.


Here's a great walk through for how Git works from the bottom up: https://jwiegley.github.io/git-from-the-bottom-up/

It's short, easy to understand and you'll understand HEAD.


That's a great resource but I find it too theoretical as a primer; to me, I need to understand git some already before the paper makes sense.

Whereas the following article is more "Lego Duplo" conceptually and helped me wrap my head around the relations between git abstractions much better,

http://www-cs-students.stanford.edu/~blynn/gitmagic/pr01.htm...

(I found it from another HN thread earlier this month.)



> [...] I don’t think you can do it with a regular git command. I’d be interested to know if there is a regular-git-command way to make .git/HEAD a non-branch reference though, and if so why you might want to do that!

various git checkout commands can get you there, e.g. `git checkout FETCH_HEAD` after fetching something like refs like refs/pull/x/head (github) or equivalent to-review thing (gerrit has refs/changes/x/y/z, gitlab refs/merge-requests/x/head)

I'm reviewing stuff all the time and never bother with branches much (I create a branch before moving off if required, or directly on the remote by pushing the current detached head with a name); and it annoys me to no end when tools like b4 want HEAD to be a branch and just don't work until I create one for the current commit. Thankfully ths has gotten pretty rare.

Alternatively you can explicitly get there through `git checkout --detach <branch>` but I'm not aware of much use case for this one.


I think Julia is talking about the literal contents of .git/HEAD. If you run `git checkout FETCH_HEAD`, you'll checkout the same commit ID that's in FETCH_HEAD, but the contents of .git/HEAD will be that commit ID. It won't literally be the string "FETCH_HEAD".

I'm pretty sure Julia is correct. The contents of HEAD are always either a commit ID or the name of a local branch ref. That's what she means by it not containing a non-branch reference. i.e. it will never be the literal string "ref: refs/tags/..." or "ref: refs/remotes/origin/...". It will always be either "ref: refs/heads/..." or a commit ID.


thanks; I indeed read though the first part too fast... "HEAD is either a reference or a commit id. the reference must be a branch if using git commands" indeed allows git commands to make detached heads (that surprised me a bit given she pointed at git branchless...)

I'm indeed not aware of any command that's store a tag in there, ignore me!


If you don't understand something simply, you don't understand it at all.

- Einstein (probably)

Git is waaaaaaay to complicated for my needs. I need a minimal subset of git that does (and only does) trunk based development.

https://trunkbaseddevelopment.com/


I've heard git described not as a version-control program, but as a toolkit for making a version-control program.

Which makes sense--it explains why sometimes there's no obvious "right" way to do things, and why there are spots where either there is no abstraction or it's pretty leaky in terms of implementation details.


I felt I fully understood git after I realized it was just a data structure.

The data structure isn't even complicated (there are commits, and then there are directories and files associated with the commits), and once I understood the tooling (i.e. git commands) in terms of how it manipulated the data structures, I was basically able to do whatever I intended to on the repo.


I mostly agree, but once you understand it, a new frustration emerges: "why can't I just do X on this graph?"


Does git not offer you what trunkbaseddevelopment offers you?


[flagged]


This adds confusion because it is not literally a symlink and it doesn't always act like a symlink either. It also assumes people understand the difference between a symbolic link and a hard link.

HEAD is a pointer. It points either indirectly to a commit through the name of a branch, or directly to a commit when you've checked out something other than a local branch (so called detached HEAD). In this way it acts both like a symlink and like a hard link. So:

HEAD -> branch name -> commit ID; or

HEAD -> commit ID.

Its literal representation is a file named HEAD whose contents are either the name of a branch or a commit ID.

A tag is also a pointer. It may also point either indirectly to a commit through an annotated tag object or directly to a commit (so called lightweight tag). So:

tag -> tag object -> commit ID; or

tag -> commit ID.

Its literal representation is a file under refs/tags named after the tag and whose contents are the ID of the tag or commit object.

(Ignoring optimizations such as packed refs and the exact formatting of ref files. See Git book and man pages for details, or poke around your local .git directory. It's very explorable.)


Everything in Git is a symlink or a hash lol


Yes, thats my point and the beauty of git.

I hope Linus is actually remembered for this more than the creation of Linux.


We’re getting there. I recently heard Linux described as “if the guy who designed Git made an operating system”.


Linux isn't that bad


> merge conflicts: <<<<<<< HEAD is just confusing

This section in particular piques my interest. I never found this confusing, since the change in HEAD is just representative of the order of operations (in rebase, you are setting the current commits "on top" of the commit you are rebasing onto, etc). This feels like what is confusing isn't really HEAD itself, it's a fundamental understanding of the git model?

I feel like folks using git without understanding the basics of what it does is what leads people astray? If so, why isn't this part of our basic training as engineers who use git?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: