Home > Software design >  Why is Git exclude operator excluding all commits, even for commit with no descendants
Why is Git exclude operator excluding all commits, even for commit with no descendants

Time:08-16

I have a simple repo with four commits

enter image description here

git git:(master) git log --pretty=reference
9843ccb (Adding file2, 2022-08-15)
6819130 (Committing the text update, 2022-08-03)
e269435 (Moving file1 to file1a, 2022-08-03)
14181db (First new file in repo, 2022-08-03)

If I do git log on the most recent commit 9843ccb, the result lists all four commits, because it shows all commits reachable from the specified commit, which includes all the ancestors.

git git:(master) git log 9843ccb --pretty=reference
9843ccb (Adding file2, 2022-08-15)
6819130 (Committing the text update, 2022-08-03)
e269435 (Moving file1 to file1a, 2022-08-03)
14181db (First new file in repo, 2022-08-03)

and if I do git log on the oldest commit, the result lists only one commit, because that commit has no ancestors. So far so good.

git git:(master) git log 14181db --pretty=reference
14181db (First new file in repo, 2022-08-03)

My problem is in understanding the exclude operator '^'. If I exclude the most recent commit, then I should see no results, because it excludes all commits reachable from this commit, which is all of them, as they are all ancestors. And that is what happens.

git git:(master) git log ^9843ccb --pretty=reference
git git:(master)

But if I exclude the oldest commit, I would not expect its descendants to be also excluded. However, that is what is happening.

git git:(master) git log ^14181db --pretty=reference
git git:(master)

Why is this? What have I misunderstood?

CodePudding user response:

A prefixed caret, or exclude syntax (^abc123), is short for (--not abc123) and is intended to be used along with other revisions.

For example, git log abc ^def could be spoken as:

Show me all commits reachable by abc that are not reachable by def.

If you don't use it with other revisions, for example, git log ^def, it could be spoken as:

Show me all commits reachable by nothing, that are not reachable by def.

Thus, no commits will be returned.

CodePudding user response:

It's a quirk, if you don't specify any revs the convenience commands will add HEAD by default, but if you do, they won't. That convenience check doesn't check whether you gave only exclusion specs, any non-option arg bypasses adding a default. You can say git log 14181db.. --pretty=reference instead.

  • Related