Re: [PATCH v3] doc: add a explanation of Git's data model

2 messages, 2 authors, 2025-10-16 · open the first message on its own page

Re: [PATCH v3] doc: add a explanation of Git's data model

From: Junio C Hamano <hidden>
Date: 2025-10-16 16:54:47

"Julia Evans" [off-list ref] writes:
quoted
quoted
+[[tree]]
+trees::
+    A tree is how Git represents a directory. It lists, for each item in
+    the tree:
++
+[[file-mode]]
+1. The *file mode*, for example `100644`. The format is inspired by Unix
+   permissions, but Git's modes are much more limited. Git only supports these file modes:
++
+  - `100644`: regular file (with type `blob`)
+  - `100755`: executable file (with type `blob`)
+  - `120000`: symbolic link (with type `blob`)
+  - `040000`: directory (with type `tree`)
+  - `160000`: gitlink, for use with submodules (with type `commit`)
It is not really "supporting" file modes.  Rather, Git only records
5 kinds of entities associated with each path in a tree object, and
uses numbers taht remotely resemble POSIX file modes to represent
these 5 kinds.

Perhaps "supports" -> "uses"?
"Uses" sounds good to me.
Also "much more limited" is misleading.  We only represent 5 kinds
of things, so we use only 5 mode-bits-looking numbers.
quoted
quoted
+2. The *type*: either <<blob,`blob`>> (a file), `tree` (a directory),
+  or <<commit,`commit`>> (a Git submodule, which is a
+  commit from a different Git repository)
+3. The <<object-id,*object ID*>>
+4. The *filename*
Here it may be worth noting that this "filename" is a single
pathname component (roughly, what you would see in non-recursive
"ls").  In other words, it may be a directory name.
Comments?
quoted
quoted
+[[blob]]
+blobs::
+    A blob is how Git represents a file. A blob object contains the
+    file's contents.
"represents a file" hints as if the thing may know its name, but
that is not the case (its name is given only by surrounding tree).

"A blob is how Git represents uninterpreted series of bytes, and
most commonly used to store file's contents." or something, perhaps?
I'll say "A blob is how Git represents a file's contents", unless Git has
another use for blobs that I don't know about (I think it's not
that much of a stretch to say that a symbolic link is a special kind
of file where the "contents" are the the link destination).
A few configuration variables like mailmap.blob name a blob object,
for which _only_ its contents, i.e., the sequence of bytes, matter
and where they originally were stored does not matter.

But we are falling into the area of tautology, as any sequence of
bytes can be stored in a file so they can be called "contents of a
file".  But the point is that these bytes do not have to be stored
to become a blob (think: "git cat-file -t blob -w --stdin").
I think it's always clearer to be more specific when possible, if there's only
one purpose for blobs it's unnecessary (and IMO a bit misleading, because
it makes the reader wonder if there are other purposes that they should
know about) to say that blobs can be used to store any arbitrary bytes for
any purpose.
I do not think describing other use cases is unnecessary.  Even if
we limit ourselves to discuss a single purpose for blob, i.e. to
represent the contents of a file, we should stress that blob is to
store _only_ contents, and not other aspects of the file (e.g., in
what paths with what mode), and that is where my reaction to "how
Git reprsents a file" comes from.
quoted
quoted
+[[branch]]
+branches: `refs/heads/<name>`::
+    A branch is a name for a commit ID.
Well a commit ID is an alternative way to refer to a commit object
*name*, so it is a bit strange to say "a name for a commit ID".

Perhaps "A branch ref stores a commit ID." is better?
I think I'll leave this alone, none of the many test readers reported
being confused by it.
Would a confused person report that they are confused? ;-)
I see that you don't like the "name for a commit ID" phrasing :)
Maybe there's another way to say it, though again none of the test
readers said they were confused by this or disagreed with the phrasing.
Yes, I get that given "refs/heads/main", you want to say "main" is
one of the ways to have repo_get_oid() to yield the commit object,
and you are using "name" in that sense, but it is more like a ref
can be used to name an object.  It is *not* the name of the object,
because the object can have other names, and more importantly, it
(i.e., to give a name for an object) is not the only thing that a
ref can do.  And that is why I do not like that phrasing, combined
with the target of giving that name is spelled "a commit ID".  The
commit ID is already another way to name the thing the refname can
be also used to name: a commit object.  A commit object and a commit
object name are different things.  The latter is a name that can
refer to the former.  And a ref can be used just like the latter to
refer to the former (i.e. "commit object").

By the way, I do like the way many of your responses are "will think
about it more", not "I'll take your version".

Very much appreciated.

Thanks.

Re: [PATCH v3] doc: add a explanation of Git's data model

From: Julia Evans <hidden>
Date: 2025-10-16 19:00:15

On Thu, Oct 16, 2025, at 12:54 PM, Junio C Hamano wrote:
"Julia Evans" [off-list ref] writes:
quoted
quoted
quoted
+[[tree]]
+trees::
+    A tree is how Git represents a directory. It lists, for each item in
+    the tree:
++
+[[file-mode]]
+1. The *file mode*, for example `100644`. The format is inspired by Unix
+   permissions, but Git's modes are much more limited. Git only supports these file modes:
++
+  - `100644`: regular file (with type `blob`)
+  - `100755`: executable file (with type `blob`)
+  - `120000`: symbolic link (with type `blob`)
+  - `040000`: directory (with type `tree`)
+  - `160000`: gitlink, for use with submodules (with type `commit`)
It is not really "supporting" file modes.  Rather, Git only records
5 kinds of entities associated with each path in a tree object, and
uses numbers taht remotely resemble POSIX file modes to represent
these 5 kinds.

Perhaps "supports" -> "uses"?
"Uses" sounds good to me.
Also "much more limited" is misleading.  We only represent 5 kinds
of things, so we use only 5 mode-bits-looking numbers.
What does it mislead the reader to think? My goal is to communicate that
if you want to tell Git to remember that a file's Unix permissions were
700, that's not possible.
quoted
quoted
quoted
+2. The *type*: either <<blob,`blob`>> (a file), `tree` (a directory),
+  or <<commit,`commit`>> (a Git submodule, which is a
+  commit from a different Git repository)
+3. The <<object-id,*object ID*>>
+4. The *filename*
Here it may be worth noting that this "filename" is a single
pathname component (roughly, what you would see in non-recursive
"ls").  In other words, it may be a directory name.
Comments?
Oops, missed this in my first pass.

I looked at them man pages for a couple of commands ("mv", "cp")
and it looks like it's normal to refer to files and directories jointly
as "files", or refer to them as having a "file name". So I think it's okay
to call it a "file name" even if the "file" may be a directory.
quoted
quoted
quoted
+[[blob]]
+blobs::
+    A blob is how Git represents a file. A blob object contains the
+    file's contents.
"represents a file" hints as if the thing may know its name, but
that is not the case (its name is given only by surrounding tree).

"A blob is how Git represents uninterpreted series of bytes, and
most commonly used to store file's contents." or something, perhaps?
I'll say "A blob is how Git represents a file's contents", unless Git has
another use for blobs that I don't know about (I think it's not
that much of a stretch to say that a symbolic link is a special kind
of file where the "contents" are the the link destination).
A few configuration variables like mailmap.blob name a blob object,
for which _only_ its contents, i.e., the sequence of bytes, matter
and where they originally were stored does not matter.

But we are falling into the area of tautology, as any sequence of
bytes can be stored in a file so they can be called "contents of a
file".  But the point is that these bytes do not have to be stored
to become a blob (think: "git cat-file -t blob -w --stdin").
I'm trying to think through what the goal of explaining the nature of
a "blob" is.

To me describing blobs primarily as "bytes" makes it sound a bit like
"Git will treat this as opaque binary data, Git will not attempt to
interpret the contents of a blob in any way" (which is certainly true
for many blob storage systems!).

But it's not true that Git treats blobs as opaque binary data, unlike
other blob storage systems, Git has diff and merge algorithms to
interpret the contents of the file to some extent and try to do useful
things with them.

Another goal we could have is to be clear that there are no limits to
what kind of files you can store in Git: you can equally well store text
files and binary files.
quoted
I think it's always clearer to be more specific when possible, if there's only
one purpose for blobs it's unnecessary (and IMO a bit misleading, because
it makes the reader wonder if there are other purposes that they should
know about) to say that blobs can be used to store any arbitrary bytes for
any purpose.
I do not think describing other use cases is unnecessary.  Even if
we limit ourselves to discuss a single purpose for blob, i.e. to
represent the contents of a file, we should stress that blob is to
store _only_ contents, and not other aspects of the file (e.g., in
what paths with what mode), and that is where my reaction to "how
Git reprsents a file" comes from.
I think it does make sense to say the blob stores only the contents,
though IMO that's fairly clear already since we've already explained
where the other parts of the file are stored by the time we get to
explaining "blob".
quoted
quoted
quoted
+[[branch]]
+branches: `refs/heads/<name>`::
+    A branch is a name for a commit ID.
Well a commit ID is an alternative way to refer to a commit object
*name*, so it is a bit strange to say "a name for a commit ID".

Perhaps "A branch ref stores a commit ID." is better?
I think I'll leave this alone, none of the many test readers reported
being confused by it.
Would a confused person report that they are confused? ;-)
Everyone leaving feedback gets a prompt something like this
asking them to categorize their feedback,
and "I'm confused" is one of the options.
https://jvns.ca/images/feedback-categories.png

I definitely got many "I'm confused" and "I have a question"
comments about other things that were confusing to readers.
quoted
I see that you don't like the "name for a commit ID" phrasing :)
Maybe there's another way to say it, though again none of the test
readers said they were confused by this or disagreed with the phrasing.
Yes, I get that given "refs/heads/main", you want to say "main" is
one of the ways to have repo_get_oid() to yield the commit object,
and you are using "name" in that sense, but it is more like a ref
can be used to name an object.  It is *not* the name of the object,
because the object can have other names, and more importantly, it
(i.e., to give a name for an object) is not the only thing that a
ref can do.  
That's interesting,  what else can a ref do other than to give a name to
an object?
And that is why I do not like that phrasing, combined
with the target of giving that name is spelled "a commit ID".  The
commit ID is already another way to name the thing the refname can
be also used to name: a commit object.  A commit object and a commit
object name are different things.  The latter is a name that can
refer to the former.
I'm curious about why it's important to you to make this distinction
between a commit ID and a commit object. To me the commit ID and the
commit object come as a package, since the commit ID is calculated from
the commit object.
 And a ref can be used just like the latter to
refer to the former (i.e. "commit object").
By the way, I do like the way many of your responses are "will think
about it more", not "I'll take your version".

Very much appreciated.
I'm glad to hear that! It's a fun puzzle to figure out how to express
things clearly and accurately and concisely.

- Julia
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help