this post was submitted on 08 Mar 2024
12 points (100.0% liked)

Git

2910 readers
1 users here now

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

Resources

Rules

  1. Follow programming.dev rules
  2. Be excellent to each other, no hostility towards users for any reason
  3. No spam of tools/companies/advertisements. It’s OK to post your own stuff part of the time, but the primary use of the community should not be self-promotion.

Git Logo by Jason Long is licensed under the Creative Commons Attribution 3.0 Unported License.

founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
[–] Kissaki 1 points 8 months ago (1 children)

I think this post makes an unnecessary distinction and unnecessarily leaves their connection open, making it more complex.

The baseline and reasoning should always be the HEAD, represented by .git/HEAD. Describing what they call a "revision parameter" or output should always refer to and be defined by that baseline. Because that's what it uses and refers to.

Instead of "closely related" we can say one refers to the other. The context on "ways git uses HEAD in its output" implies/seems to nudge to me that it's something different; but again, a HEAD label references HEAD. There's no variance in what HEAD refers to.

HEAD -> sha1 (commit)                          => detached head (not on any branch)
HEAD -> refs/heads/branchname -> sha1 (commit) => on branch branchname

All of these things (HEAD, HEAD^^^, HEAD@[2}) are called “revision parameters”. They’re documented in man gitrevisions, and Git will try to resolve them to a commit ID.

While they listed a commit range in the example, they fail to mention it here. A revision range does not resolve to only one commit. ("Specifying ranges" is documented on the same git man page.)


For example, git talks about “detached HEAD state”, but never about “attached HEAD state” – git’s documentation never uses the term “attached” at all to refer to HEAD. And git talks about being “on” a branch, but never “not on” a branch.

I think it's a good choice to not unnecessarily complicate default mode and usage. Detached HEAD is the exceptional state, and not commonly used.

So it’s very hard to guess that on branch main is actually the opposite of HEAD detached. How is the user supposed to guess that HEAD detached has anything to do with branches at all, or that “on branch main” has anything to do with HEAD?

I can agree it's not obvious though. It requires understanding of what HEAD actually is - which is useful for the other things you list too (specifying revisions and understanding output).

I'm not sure if there's a good or better way for introducing the user to it though. It's inherent tool complexity. And I don't think calling every HEAD attached when it points to a branch is verbose to the point of being detrimental.


I don't find the HEAD in diffs between merge and rebase confusing. When I rebase commits I am always aware of the replay activity. (I mainly use TortoiseGit where it is always obvious through updating rebase progress.)

Displaying the original HEAD before the rebase started would be wrong and even more confusing. Because that HEAD and commit is no longer part of any of the changes. You are on a different base, and you are cherry picking onto it.

[–] [email protected] 2 points 8 months ago (1 children)

I thought HEAD was just a ref that points to the commit in history where you are right now. Like a "you are here" label. That's it.

Detached HEAD meaning that the HEAD ref doesn't point to the same commit as the branch ref that always follows the last commit in a development branch.

The author is really complicating things.

[–] Kissaki 2 points 8 months ago (1 children)

Detached HEAD meaning that the HEAD ref doesn’t point to the same commit as the branch ref that always follows the last commit in a development branch

IMO this is misleading, or incomplete.

HEAD is different from branches in that it can point to a commit or a branch. A branch always points to a commit.

When HEAD is in [branch] detached state, there is no branch to refer to/we can refer to. We are outside of branches.


From a use case perspective that may illustrate the difference:

When HEAD points to a branch, and I commit, I commit to that branch.

When HEAD points to a commit ([branch] detached HEAD), and I commit, I create a commit, and HEAD points to the new commit, but there is no branch pointing to it. (A followup is needed, e.g. creating a branch, or updating an existing branch, to keep the new commit discoverable even after we change what HEAD points to - e.g. by switching to a branch.)


I thought HEAD was just a ref

"refs" are stored in .git/refs/heads - but HEAD is not. In that sense, HEAD is not a ref like the others (branches and tags and whatever else you put there, like pull request references).

HEAD is either a reference or a reference to a reference. Branches are references.

[–] [email protected] 3 points 8 months ago

HEAD is different from branches in that it can point to a commit or a branch. A branch always points to a commit.

That's what I was saying.

When HEAD is in [branch] detached state, there is no branch to refer to/we can refer to. We are outside of branches.

You can still be in detached HEAD state and still be in a branch in a sense that your working tree reflects a commit that's in a series of commit that follow a certain bifurcation. If that makes any sense.

But as soon as you make changes and commit, you create a "branch within a branch" though that "branch" doesn't have a branch ref pointing to it.